From 7a2b82504bc3479d2a3b09c52c79ddc1d4a0087f Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Thu, 18 May 2023 14:08:11 +0100 Subject: [PATCH 001/580] fix merge conflicts with workflow --- build.gradle | 98 +++++++ gradle.properties | 21 ++ gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 62076 bytes gradle/wrapper/gradle-wrapper.properties | 6 + gradlew | 245 ++++++++++++++++++ gradlew.bat | 92 +++++++ settings.gradle | 10 + .../advancedbackups/AdvancedBackups.java | 46 ++++ .../PlatformMethodWrapper.java | 66 +++++ .../assets/advanced-backups/icon.png | Bin 0 -> 453 bytes src/main/resources/fabric.mod.json | 27 ++ 11 files changed, 611 insertions(+) create mode 100644 build.gradle create mode 100644 gradle.properties create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100644 gradlew create mode 100644 gradlew.bat create mode 100644 settings.gradle create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/PlatformMethodWrapper.java create mode 100644 src/main/resources/assets/advanced-backups/icon.png create mode 100644 src/main/resources/fabric.mod.json diff --git a/build.gradle b/build.gradle new file mode 100644 index 00000000..9230c446 --- /dev/null +++ b/build.gradle @@ -0,0 +1,98 @@ +plugins { + id 'fabric-loom' version '1.2-SNAPSHOT' + id 'maven-publish' +} + +version = project.mod_version +group = project.maven_group +archivesBaseName = 'AdvancedBackups-' + modloaderName + "-" + minecraftVersion + + + +repositories { + // Add repositories to retrieve artifacts from in here. + // You should only use this when depending on other mods because + // Loom adds the essential maven repositories to download Minecraft and libraries from automatically. + // See https://docs.gradle.org/current/userguide/declaring_repositories.html + // for more information about repositories. +} + +configurations { + // configuration that holds jars to include in the jar + extraLibs +} + +dependencies { + // To change the versions see the gradle.properties file + minecraft "com.mojang:minecraft:${project.minecraft_version}" + mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" + modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" + + // Fabric API. This is technically optional, but you probably want it anyway. + modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" + + // Uncomment the following line to enable the deprecated Fabric API modules. + // These are included in the Fabric API production distribution and allow you to update your mod to the latest modules at a later more convenient time. + + // modImplementation "net.fabricmc.fabric-api:fabric-api-deprecated:${project.fabric_version}" + + implementation files('dependencies/jansi-2.4.0.jar') + extraLibs files('dependencies/jansi-2.4.0.jar') +} + +processResources { + inputs.property "version", project.version + + filesMatching("fabric.mod.json") { + expand "version": project.version + } +} + +tasks.withType(JavaCompile).configureEach { + it.options.release = 17 +} + +java { + // Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task + // if it is present. + // If you remove this line, sources will not be generated. + withSourcesJar() + + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 +} + +jar { + manifest { + attributes([ + "Main-Class" : "co.uk.mommyheather.advancedbackups.cli.AdvancedBackupsCLI", + "Specification-Title" : "advancedbackups", + "Specification-Vendor" : "raveninthedark", + "Specification-Version" : "1", // We are version 1 of ourselves + "Implementation-Title" : project.name, + "Implementation-Version" : project.jar.archiveVersion, + "Implementation-Vendor" : "raveninthedark", + "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ") + ]) + } + from { + configurations.extraLibs.collect { it.isDirectory() ? it : zipTree(it) } + } +} + +// configure the maven publication +publishing { + publications { + mavenJava(MavenPublication) { + from components.java + } + } + + // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing. + repositories { + // Add repositories to publish to here. + // Notice: This block does NOT have the same function as the block in the top level. + // The repositories here will be used for publishing your artifact, not for + // retrieving dependencies. + } +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 00000000..60ac03c7 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,21 @@ +# Done to increase the memory available to gradle. +org.gradle.jvmargs=-Xmx1G +org.gradle.parallel=true + +# Fabric Properties +# check these on https://fabricmc.net/develop +minecraft_version=1.18.2 +yarn_mappings=1.18.2+build.4 +loader_version=0.14.19 + +# Mod Properties +mod_version=0.1 +maven_group=co.uk.mommyheather.advancedbackups +archives_base_name=advanced-backups +modloaderName =fabric +minecraftVersion =1.18 + +# Dependencies +fabric_version=0.76.0+1.18.2 + + diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..c1962a79e29d3e0ab67b14947c167a862655af9b GIT binary patch literal 62076 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 literal 0 HcmV?d00001 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..37aef8d3 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip +networkTimeout=10000 +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100644 index 00000000..aeb74cbb --- /dev/null +++ b/gradlew @@ -0,0 +1,245 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 00000000..93e3f59f --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,92 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 00000000..56266b41 --- /dev/null +++ b/settings.gradle @@ -0,0 +1,10 @@ +pluginManagement { + repositories { + maven { + name = 'Fabric' + url = 'https://maven.fabricmc.net/' + } + mavenCentral() + gradlePluginPortal() + } +} \ No newline at end of file diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java new file mode 100644 index 00000000..b9d74ca8 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -0,0 +1,46 @@ +package co.uk.mommyheather.advancedbackups; + +import net.fabricmc.api.ModInitializer; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; +import net.minecraft.server.MinecraftServer; +import net.minecraft.util.WorldSavePath; + +import java.util.function.Consumer; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; +import co.uk.mommyheather.advancedbackups.core.config.AVConfig; + +public class AdvancedBackups implements ModInitializer { + // This logger is used to write text to the console and the log file. + // It is considered best practice to use your mod id as the logger's name. + // That way, it's clear which mod wrote info, warnings, and errors. + + public static final Logger LOGGER = LoggerFactory.getLogger("advanced-backups"); + + public static final Consumer infoLogger = LOGGER::info; + public static final Consumer warningLogger = LOGGER::warn; + public static final Consumer errorLogger = LOGGER::error; + + public static MinecraftServer server; + + @Override + public void onInitialize() { + ServerLifecycleEvents.SERVER_STARTING.register((server) -> { + AdvancedBackups.server = server; + AVConfig.loadOrCreateConfig(); + LOGGER.info("Config loaded!!"); + PlatformMethodWrapper.worldName = server.getSaveProperties().getLevelName(); + PlatformMethodWrapper.worldDir = server.getSavePath(WorldSavePath.ROOT); + }); + + ServerLifecycleEvents.SERVER_STARTED.register((server) -> { + BackupWrapper.checkStartupBackups(); + }); + ServerLifecycleEvents.SERVER_STOPPING.register((server) -> { + BackupWrapper.checkShutdownBackups(); + }); + } +} \ No newline at end of file diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/PlatformMethodWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/PlatformMethodWrapper.java new file mode 100644 index 00000000..4779a7bc --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/PlatformMethodWrapper.java @@ -0,0 +1,66 @@ +package co.uk.mommyheather.advancedbackups; + +import java.nio.file.Path; +import java.util.function.Consumer; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.world.ServerWorld; + +public class PlatformMethodWrapper { + + public static String worldName = ""; + public static Path worldDir = null; + public static Boolean activity = false; + public static final Consumer infoLogger = AdvancedBackups.infoLogger; + public static final Consumer warningLogger = AdvancedBackups.warningLogger; + public static final Consumer errorLogger = AdvancedBackups.errorLogger; + + public static final String savesDisabledMessage = """ + + +*************************************** +SAVING DISABLED - PREPARING FOR BACKUP! +*************************************** +"""; + public static final String savesEnabledMessage = """ + + +********************************* +SAVING ENABLED - BACKUP COMPLETE! +********************************* +"""; + public static final String saveCompleteMessage = """ + + +************************************* +SAVE COMPLETE - PREPARING FOR BACKUP! +************************************* +"""; + + + public static void disableSaving() { + MinecraftServer server = AdvancedBackups.server; + for (ServerWorld level : server.getWorlds()) { + if (level != null && !level.savingDisabled) { + level.savingDisabled = true; + } + } + warningLogger.accept(savesDisabledMessage); + } + + public static void enableSaving() { + MinecraftServer server = AdvancedBackups.server; + for (ServerWorld level : server.getWorlds()) { + if (level != null && !level.savingDisabled) { + level.savingDisabled = false; + } + } + warningLogger.accept(savesEnabledMessage); + } + + public static void saveOnce() { + MinecraftServer server = AdvancedBackups.server; + server.saveAll(true, true, true); + warningLogger.accept(saveCompleteMessage); + } +} diff --git a/src/main/resources/assets/advanced-backups/icon.png b/src/main/resources/assets/advanced-backups/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..047b91f2347de5cf95f23284476fddbe21ba23fe GIT binary patch literal 453 zcmV;$0XqJPP)QAFYGys`80vegN0XDFh0OXKz&i8?Le#x7{1X)R+00000NkvXXu0mjf73i~T literal 0 HcmV?d00001 diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json new file mode 100644 index 00000000..91875b52 --- /dev/null +++ b/src/main/resources/fabric.mod.json @@ -0,0 +1,27 @@ +{ + "schemaVersion": 1, + "id": "advancedbackups", + "version": "${version}", + "name": "Advanced Backups", + "description": "An extremely advanced backup mod.\n\nSupports many backup types.\n\nConfig file and github contain documentation.", + "authors": [ + "Mommy Heather" + ], + "contact": { + "homepage": "https://github.com/mommyheather/advancedbackups" + }, + "license": "MIT", + "icon": "assets/advanced-backups/icon.png", + "environment": "*", + "entrypoints": { + "main": [ + "co.uk.mommyheather.advancedbackups.AdvancedBackups" + ] + }, + "depends": { + "fabricloader": ">=0.14.19", + "minecraft": "~1.18.2", + "java": ">=17", + "fabric-api": "*" + } +} \ No newline at end of file From 22dc9149a10d177c56b863e458710b71500e975f Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Thu, 18 May 2023 14:18:09 +0100 Subject: [PATCH 002/580] fix some funny workflow problems --- .gitignore | 26 +++ build.gradle | 217 ++++++++++++++++++ gradle.properties | 9 + .../advancedbackups/AdvancedBackups.java | 57 +++++ .../PlatformMethodWrapper.java | 67 ++++++ 5 files changed, 376 insertions(+) create mode 100644 .gitignore create mode 100644 build.gradle create mode 100644 gradle.properties create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/PlatformMethodWrapper.java diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..12ae3a47 --- /dev/null +++ b/.gitignore @@ -0,0 +1,26 @@ +# eclipse +bin +*.launch +.settings +.metadata +.classpath +.project + +# idea +out +*.ipr +*.iws +*.iml +.idea + +# gradle +build +.gradle +gradle + +# other +eclipse +run + +# Files from Forge MDK +forge*changelog.txt diff --git a/build.gradle b/build.gradle new file mode 100644 index 00000000..6abfa6df --- /dev/null +++ b/build.gradle @@ -0,0 +1,217 @@ +buildscript { + repositories { + // These repositories are only for Gradle plugins, put any other repositories in the repository block further below + maven { url = 'https://maven.minecraftforge.net' } + mavenCentral() + } + dependencies { + classpath group: 'net.minecraftforge.gradle', name: 'ForgeGradle', version: '5.1.+', changing: true + } +} +// Only edit below this line, the above code adds and enables the necessary things for Forge to be setup. +plugins { + id 'eclipse' + id 'maven-publish' +} +apply plugin: 'net.minecraftforge.gradle' + + +version = '0.1' +group = 'com.github.raveninthedark.advancedbackups' // http://maven.apache.org/guides/mini/guide-naming-conventions.html +archivesBaseName = 'AdvancedBackups-' + modloaderName + "-" + minecraftVersion + +// Mojang ships Java 17 to end users in 1.18+, so your mod should target Java 17. +java.toolchain.languageVersion = JavaLanguageVersion.of(17) + +println "Java: ${System.getProperty 'java.version'}, JVM: ${System.getProperty 'java.vm.version'} (${System.getProperty 'java.vendor'}), Arch: ${System.getProperty 'os.arch'}" +minecraft { + // The mappings can be changed at any time and must be in the following format. + // Channel: Version: + // official MCVersion Official field/method names from Mojang mapping files + // parchment YYYY.MM.DD-MCVersion Open community-sourced parameter names and javadocs layered on top of official + // + // You must be aware of the Mojang license when using the 'official' or 'parchment' mappings. + // See more information here: https://github.com/MinecraftForge/MCPConfig/blob/master/Mojang.md + // + // Parchment is an unofficial project maintained by ParchmentMC, separate from MinecraftForge + // Additional setup is needed to use their mappings: https://github.com/ParchmentMC/Parchment/wiki/Getting-Started + // + // Use non-default mappings at your own risk. They may not always work. + // Simply re-run your setup task after changing the mappings to update your workspace. + mappings channel: 'official', version: '1.18.2' + + // accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg') // Currently, this location cannot be changed from the default. + + // Default run configurations. + // These can be tweaked, removed, or duplicated as needed. + runs { + client { + workingDirectory project.file('run') + + // Recommended logging data for a userdev environment + // The markers can be added/remove as needed separated by commas. + // "SCAN": For mods scan. + // "REGISTRIES": For firing of registry events. + // "REGISTRYDUMP": For getting the contents of all registries. + property 'forge.logging.markers', 'REGISTRIES' + + // Recommended logging level for the console + // You can set various levels here. + // Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels + property 'forge.logging.console.level', 'debug' + + // Comma-separated list of namespaces to load gametests from. Empty = all namespaces. + property 'forge.enabledGameTestNamespaces', 'advancedbackups' + + mods { + advancedbackups { + source sourceSets.main + } + } + } + + server { + workingDirectory project.file('run') + + property 'forge.logging.markers', 'REGISTRIES' + + property 'forge.logging.console.level', 'debug' + + // Comma-separated list of namespaces to load gametests from. Empty = all namespaces. + property 'forge.enabledGameTestNamespaces', 'advancedbackups' + + mods { + advancedbackups { + source sourceSets.main + } + } + } + + // This run config launches GameTestServer and runs all registered gametests, then exits. + // By default, the server will crash when no gametests are provided. + // The gametest system is also enabled by default for other run configs under the /test command. + gameTestServer { + workingDirectory project.file('run') + + // Recommended logging data for a userdev environment + // The markers can be added/remove as needed separated by commas. + // "SCAN": For mods scan. + // "REGISTRIES": For firing of registry events. + // "REGISTRYDUMP": For getting the contents of all registries. + property 'forge.logging.markers', 'REGISTRIES' + + // Recommended logging level for the console + // You can set various levels here. + // Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels + property 'forge.logging.console.level', 'debug' + + // Comma-separated list of namespaces to load gametests from. Empty = all namespaces. + property 'forge.enabledGameTestNamespaces', 'advancedbackups' + + mods { + advancedbackups { + source sourceSets.main + } + } + } + + data { + workingDirectory project.file('run') + + property 'forge.logging.markers', 'REGISTRIES' + + property 'forge.logging.console.level', 'debug' + + // Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources. + args '--mod', 'advancedbackups', '--all', '--output', file('src/generated/resources/'), '--existing', file('src/main/resources/') + + mods { + advancedbackups { + source sourceSets.main + } + } + } + } +} + +// Include resources generated by data generators. +sourceSets.main.resources { srcDir 'src/generated/resources' } + +repositories { + // Put repositories for dependencies here + // ForgeGradle automatically adds the Forge maven and Maven Central for you + + // If you have mod jar dependencies in ./libs, you can declare them as a repository like so: + // flatDir { + // dir 'libs' + // } +} + +configurations { + // configuration that holds jars to include in the jar + extraLibs +} + +dependencies { + // Specify the version of Minecraft to use. If this is any group other than 'net.minecraft', it is assumed + // that the dep is a ForgeGradle 'patcher' dependency, and its patches will be applied. + // The userdev artifact is a special name and will get all sorts of transformations applied to it. + minecraft 'net.minecraftforge:forge:1.18.2-40.2.1' + //extraLibs 'com.sun.jna.platform:5.13.0' + implementation files('dependencies/jansi-2.4.0.jar') + extraLibs files('dependencies/jansi-2.4.0.jar') + + // Real mod deobf dependency examples - these get remapped to your current mappings + // compileOnly fg.deobf("mezz.jei:jei-${mc_version}:${jei_version}:api") // Adds JEI API as a compile dependency + // runtimeOnly fg.deobf("mezz.jei:jei-${mc_version}:${jei_version}") // Adds the full JEI mod as a runtime dependency + // implementation fg.deobf("com.tterrag.registrate:Registrate:MC${mc_version}-${registrate_version}") // Adds registrate as a dependency + + // Examples using mod jars from ./libs + // implementation fg.deobf("blank:coolmod-${mc_version}:${coolmod_version}") + + // For more info... + // http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html + // http://www.gradle.org/docs/current/userguide/dependency_management.html +} + +// Example for how to get properties into the manifest for reading at runtime. +jar { + manifest { + attributes([ + "Main-Class" : "co.uk.mommyheather.advancedbackups.cli.AdvancedBackupsCLI", + "Specification-Title" : "advancedbackups", + "Specification-Vendor" : "raveninthedark", + "Specification-Version" : "1", // We are version 1 of ourselves + "Implementation-Title" : project.name, + "Implementation-Version" : project.jar.archiveVersion, + "Implementation-Vendor" : "raveninthedark", + "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ") + ]) + } + from { + configurations.extraLibs.collect { it.isDirectory() ? it : zipTree(it) } + } +} + +// Example configuration to allow publishing using the maven-publish plugin +// This is the preferred method to reobfuscate your jar file +jar.finalizedBy('reobfJar') +// However if you are in a multi-project build, dev time needs unobfed jar files, so you can delay the obfuscation until publishing by doing +// publish.dependsOn('reobfJar') + +publishing { + publications { + mavenJava(MavenPublication) { + artifact jar + } + } + repositories { + maven { + url "file://${project.projectDir}/mcmodsrepo" + } + } +} + +tasks.withType(JavaCompile).configureEach { + options.encoding = 'UTF-8' // Use the UTF-8 charset for Java compilation +} diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 00000000..0cb3e73b --- /dev/null +++ b/gradle.properties @@ -0,0 +1,9 @@ +# Sets default memory used for gradle commands. Can be overridden by user or command line properties. +# This is required to provide enough memory for the Minecraft decompilation process. +org.gradle.jvmargs=-Xmx3G +org.gradle.daemon=false + + + +modloaderName =forge +minecraftVersion =1.18 \ No newline at end of file diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java new file mode 100644 index 00000000..cfbda984 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -0,0 +1,57 @@ +package co.uk.mommyheather.advancedbackups; + +import com.mojang.logging.LogUtils; + +import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; +import co.uk.mommyheather.advancedbackups.core.config.AVConfig; +import net.minecraft.world.level.storage.LevelResource; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.event.server.ServerStartedEvent; +import net.minecraftforge.event.server.ServerStartingEvent; +import net.minecraftforge.event.server.ServerStoppingEvent; + +import java.util.function.Consumer; + +import org.slf4j.Logger; + +@Mod("advancedbackups") +public class AdvancedBackups +{ + + private static final Logger LOGGER = LogUtils.getLogger(); + + public static final Consumer infoLogger = LOGGER::info; + public static final Consumer warningLogger = LOGGER::warn; + public static final Consumer errorLogger = LOGGER::error; + + + public AdvancedBackups() + { + // Register ourselves for server and other game events we are interested in + MinecraftForge.EVENT_BUS.register(this); + } + + @SubscribeEvent + public void onServerStarting(ServerStartingEvent event) + { + // Do something when the server starts + AVConfig.loadOrCreateConfig(); + LOGGER.info("Config loaded!!"); + PlatformMethodWrapper.worldName = event.getServer().getWorldData().getLevelName(); + PlatformMethodWrapper.worldDir = event.getServer().getWorldPath(LevelResource.ROOT); + + } + + @SubscribeEvent + public void onServerStarted(ServerStartedEvent event) { + BackupWrapper.checkStartupBackups(); + } + + @SubscribeEvent + public void onServerStopping(ServerStoppingEvent event) { + BackupWrapper.checkShutdownBackups(); + } + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/PlatformMethodWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/PlatformMethodWrapper.java new file mode 100644 index 00000000..b47a0d95 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/PlatformMethodWrapper.java @@ -0,0 +1,67 @@ +package co.uk.mommyheather.advancedbackups; + +import java.nio.file.Path; +import java.util.function.Consumer; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerLevel; +import net.minecraftforge.server.ServerLifecycleHooks; + +public class PlatformMethodWrapper { + + public static String worldName = ""; + public static Path worldDir = null; + public static Boolean activity = false; + public static final Consumer infoLogger = AdvancedBackups.infoLogger; + public static final Consumer warningLogger = AdvancedBackups.warningLogger; + public static final Consumer errorLogger = AdvancedBackups.errorLogger; + + public static final String savesDisabledMessage = """ + + +*************************************** +SAVING DISABLED - PREPARING FOR BACKUP! +*************************************** +"""; + public static final String savesEnabledMessage = """ + + +********************************* +SAVING ENABLED - BACKUP COMPLETE! +********************************* +"""; + public static final String saveCompleteMessage = """ + + +************************************* +SAVE COMPLETE - PREPARING FOR BACKUP! +************************************* +"""; + + + public static void disableSaving() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + for (ServerLevel level : server.getAllLevels()) { + if (level != null && !level.noSave) { + level.noSave = true; + } + } + warningLogger.accept(savesDisabledMessage); + } + + public static void enableSaving() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + for (ServerLevel level : server.getAllLevels()) { + if (level != null && !level.noSave) { + level.noSave = false; + } + } + warningLogger.accept(savesEnabledMessage); + } + + public static void saveOnce() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + server.saveEverything(true, true, true); + warningLogger.accept(saveCompleteMessage); + } +} From 05faafdf326155ec36ceac7723021bf8649b3a4d Mon Sep 17 00:00:00 2001 From: Heather <66441550+MommyHeather@users.noreply.github.com> Date: Thu, 18 May 2023 16:01:19 +0100 Subject: [PATCH 003/580] workflows aren't fun --- .../java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java new file mode 100644 index 00000000..a405cb41 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -0,0 +1 @@ +dasdas From 4aa3a53a8fcdbba3cdd1cf136055a368e8d587d1 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Thu, 18 May 2023 15:37:48 +0000 Subject: [PATCH 004/580] Update core files --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b32e5ae0..822f10ae 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,8 @@ # Advanced Backups # Note - early release. Some features here aren't implemented yet, and not all features are documented. -# test to stop workflow fuckin shitasda + +# copy work please A powerful backup mod for Minecraft, supporting Forge and Fabric. Many Minecraft versions are supported - request more if the one you want isn't yet supported. From feb92c8d08f14b5efb582909b82cf8deb5b8f96e Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Thu, 18 May 2023 15:54:10 +0000 Subject: [PATCH 005/580] Update core files --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 822f10ae..607ce2c1 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,6 @@ # Note - early release. Some features here aren't implemented yet, and not all features are documented. -# copy work please A powerful backup mod for Minecraft, supporting Forge and Fabric. Many Minecraft versions are supported - request more if the one you want isn't yet supported. From 011db0711073c9e4c83686768c6559ee8dca6447 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Thu, 18 May 2023 15:54:12 +0000 Subject: [PATCH 006/580] Update core files --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b32e5ae0..607ce2c1 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Advanced Backups # Note - early release. Some features here aren't implemented yet, and not all features are documented. -# test to stop workflow fuckin shitasda + A powerful backup mod for Minecraft, supporting Forge and Fabric. Many Minecraft versions are supported - request more if the one you want isn't yet supported. From 17d564950f858b66abbdd36bbd13edb019006a28 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Thu, 18 May 2023 15:54:54 +0000 Subject: [PATCH 007/580] Update core files --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b32e5ae0..607ce2c1 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Advanced Backups # Note - early release. Some features here aren't implemented yet, and not all features are documented. -# test to stop workflow fuckin shitasda + A powerful backup mod for Minecraft, supporting Forge and Fabric. Many Minecraft versions are supported - request more if the one you want isn't yet supported. From 92489fb4b7553ab9d41557729f4a2a0d1a3bf5b7 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Thu, 18 May 2023 16:06:59 +0000 Subject: [PATCH 008/580] Update core files --- .../mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java index 248dbac1..b341e13a 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java @@ -384,7 +384,6 @@ private static void restoreFullZip(int index, File worldFile) { FileInputStream fileInputStream = new FileInputStream(fileNames.get(index)); ZipInputStream zip = new ZipInputStream(fileInputStream); while ((entry = zip.getNextEntry()) != null) { - info(entry.getName()); File outputFile; //FTB Backups and some other mods need special handling. @@ -509,8 +508,6 @@ private static void restorePartialZip(int index, File worldFile) { Files.walkFileTree(root, new SimpleFileVisitor() { @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) throws IOException { - info(file.toString()); - info(file.toAbsolutePath().toString()); entries.put(file.toString(), file); return FileVisitResult.CONTINUE; } @@ -670,7 +667,6 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) thro outputFile.getParentFile().mkdirs(); } Files.copy(file, outputFile.toPath()); - info(outputFile.getName()); return FileVisitResult.CONTINUE; } }); From 977412c75a185e23f0b8f584744dbd0985dc93fa Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Thu, 18 May 2023 16:07:00 +0000 Subject: [PATCH 009/580] Update core files --- .../mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java index 248dbac1..b341e13a 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java @@ -384,7 +384,6 @@ private static void restoreFullZip(int index, File worldFile) { FileInputStream fileInputStream = new FileInputStream(fileNames.get(index)); ZipInputStream zip = new ZipInputStream(fileInputStream); while ((entry = zip.getNextEntry()) != null) { - info(entry.getName()); File outputFile; //FTB Backups and some other mods need special handling. @@ -509,8 +508,6 @@ private static void restorePartialZip(int index, File worldFile) { Files.walkFileTree(root, new SimpleFileVisitor() { @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) throws IOException { - info(file.toString()); - info(file.toAbsolutePath().toString()); entries.put(file.toString(), file); return FileVisitResult.CONTINUE; } @@ -670,7 +667,6 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) thro outputFile.getParentFile().mkdirs(); } Files.copy(file, outputFile.toPath()); - info(outputFile.getName()); return FileVisitResult.CONTINUE; } }); From 237d64e3964f3fdd495cd8a6dfb19e6d63893d56 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Thu, 18 May 2023 16:07:01 +0000 Subject: [PATCH 010/580] Update core files --- .../mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java index 248dbac1..b341e13a 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java @@ -384,7 +384,6 @@ private static void restoreFullZip(int index, File worldFile) { FileInputStream fileInputStream = new FileInputStream(fileNames.get(index)); ZipInputStream zip = new ZipInputStream(fileInputStream); while ((entry = zip.getNextEntry()) != null) { - info(entry.getName()); File outputFile; //FTB Backups and some other mods need special handling. @@ -509,8 +508,6 @@ private static void restorePartialZip(int index, File worldFile) { Files.walkFileTree(root, new SimpleFileVisitor() { @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) throws IOException { - info(file.toString()); - info(file.toAbsolutePath().toString()); entries.put(file.toString(), file); return FileVisitResult.CONTINUE; } @@ -670,7 +667,6 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) thro outputFile.getParentFile().mkdirs(); } Files.copy(file, outputFile.toPath()); - info(outputFile.getName()); return FileVisitResult.CONTINUE; } }); From 1442d0982e8c9d1cd50c9f0f50cb6362e3dc0b2e Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Thu, 18 May 2023 17:37:52 +0000 Subject: [PATCH 011/580] Update core files --- .../mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java index b341e13a..b2e879d7 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java @@ -503,7 +503,7 @@ private static void restorePartialZip(int index, File worldFile) { HashMap entries = new HashMap<>(); try { - FileSystem zipFs = FileSystems.newFileSystem(new File(fileNames.get(index)).toPath()); + FileSystem zipFs = FileSystems.newFileSystem(new File(fileNames.get(index)).toPath(), AdvancedBackupsCLI.class.getClassLoader()); Path root = zipFs.getPath(""); Files.walkFileTree(root, new SimpleFileVisitor() { @Override @@ -791,7 +791,7 @@ private static ArrayList sortStringsAlphabeticallyWithDirectoryPriority( private static void addBackupNamesToLists(File file, HashMap filePaths, HashMap dates, String colour) throws IOException { if (file.isFile()) { - FileSystem zipFs = FileSystems.newFileSystem(file.toPath()); + FileSystem zipFs = FileSystems.newFileSystem(file.toPath(), AdvancedBackupsCLI.class.getClassLoader()); Path root = zipFs.getPath(""); Files.walkFileTree(root, new SimpleFileVisitor() { @Override From 233197c804b0b313386dee8d088c5ad98d70eade Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Thu, 18 May 2023 17:37:53 +0000 Subject: [PATCH 012/580] Update core files --- .../mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java index b341e13a..b2e879d7 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java @@ -503,7 +503,7 @@ private static void restorePartialZip(int index, File worldFile) { HashMap entries = new HashMap<>(); try { - FileSystem zipFs = FileSystems.newFileSystem(new File(fileNames.get(index)).toPath()); + FileSystem zipFs = FileSystems.newFileSystem(new File(fileNames.get(index)).toPath(), AdvancedBackupsCLI.class.getClassLoader()); Path root = zipFs.getPath(""); Files.walkFileTree(root, new SimpleFileVisitor() { @Override @@ -791,7 +791,7 @@ private static ArrayList sortStringsAlphabeticallyWithDirectoryPriority( private static void addBackupNamesToLists(File file, HashMap filePaths, HashMap dates, String colour) throws IOException { if (file.isFile()) { - FileSystem zipFs = FileSystems.newFileSystem(file.toPath()); + FileSystem zipFs = FileSystems.newFileSystem(file.toPath(), AdvancedBackupsCLI.class.getClassLoader()); Path root = zipFs.getPath(""); Files.walkFileTree(root, new SimpleFileVisitor() { @Override From e4dde06d5eee1125121bd286e21200fce4b96967 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Thu, 18 May 2023 17:37:54 +0000 Subject: [PATCH 013/580] Update core files --- .../mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java index b341e13a..b2e879d7 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java @@ -503,7 +503,7 @@ private static void restorePartialZip(int index, File worldFile) { HashMap entries = new HashMap<>(); try { - FileSystem zipFs = FileSystems.newFileSystem(new File(fileNames.get(index)).toPath()); + FileSystem zipFs = FileSystems.newFileSystem(new File(fileNames.get(index)).toPath(), AdvancedBackupsCLI.class.getClassLoader()); Path root = zipFs.getPath(""); Files.walkFileTree(root, new SimpleFileVisitor() { @Override @@ -791,7 +791,7 @@ private static ArrayList sortStringsAlphabeticallyWithDirectoryPriority( private static void addBackupNamesToLists(File file, HashMap filePaths, HashMap dates, String colour) throws IOException { if (file.isFile()) { - FileSystem zipFs = FileSystems.newFileSystem(file.toPath()); + FileSystem zipFs = FileSystems.newFileSystem(file.toPath(), AdvancedBackupsCLI.class.getClassLoader()); Path root = zipFs.getPath(""); Files.walkFileTree(root, new SimpleFileVisitor() { @Override From f418c63cd6a74e96bee1e135f0c126d6bb5ece41 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Thu, 18 May 2023 19:31:35 +0100 Subject: [PATCH 014/580] Version bump for build --- build.gradle | 186 ++++++++++++++++++++++++++++++++++++++++++++++ gradle.properties | 7 ++ 2 files changed, 193 insertions(+) create mode 100644 build.gradle create mode 100644 gradle.properties diff --git a/build.gradle b/build.gradle new file mode 100644 index 00000000..37271587 --- /dev/null +++ b/build.gradle @@ -0,0 +1,186 @@ +buildscript { + repositories { + maven { url = 'https://files.minecraftforge.net/maven' } + mavenCentral() + } + dependencies { + classpath group: 'net.minecraftforge.gradle', name: 'ForgeGradle', version: '4.1.+', changing: true + } +} +apply plugin: 'net.minecraftforge.gradle' +// Only edit below this line, the above code adds and enables the necessary things for Forge to be setup. +apply plugin: 'eclipse' +apply plugin: 'maven-publish' + +version = '0.1' +group = 'com.github.raveninthedark.advancedbackups' // http://maven.apache.org/guides/mini/guide-naming-conventions.html +archivesBaseName = 'AdvancedBackups-' + modloaderName + "-" + minecraftVersion + +java.toolchain.languageVersion = JavaLanguageVersion.of(8) // Mojang ships Java 8 to end users, so your mod should target Java 8. + +println('Java: ' + System.getProperty('java.version') + ' JVM: ' + System.getProperty('java.vm.version') + '(' + System.getProperty('java.vendor') + ') Arch: ' + System.getProperty('os.arch')) +minecraft { + // The mappings can be changed at any time, and must be in the following format. + // Channel: Version: + // snapshot YYYYMMDD Snapshot are built nightly. + // stable # Stables are built at the discretion of the MCP team. + // official MCVersion Official field/method names from Mojang mapping files + // + // You must be aware of the Mojang license when using the 'official' mappings. + // See more information here: https://github.com/MinecraftForge/MCPConfig/blob/master/Mojang.md + // + // Use non-default mappings at your own risk. they may not always work. + // Simply re-run your setup task after changing the mappings to update your workspace. + mappings channel: 'official', version: '1.16.5' + // makeObfSourceJar = false // an Srg named sources jar is made by default. uncomment this to disable. + + accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg') + + // Default run configurations. + // These can be tweaked, removed, or duplicated as needed. + runs { + client { + workingDirectory project.file('run') + + // Recommended logging data for a userdev environment + // The markers can be changed as needed. + // "SCAN": For mods scan. + // "REGISTRIES": For firing of registry events. + // "REGISTRYDUMP": For getting the contents of all registries. + property 'forge.logging.markers', 'REGISTRIES' + + // Recommended logging level for the console + // You can set various levels here. + // Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels + property 'forge.logging.console.level', 'debug' + + mods { + AdvancedBackups { + source sourceSets.main + } + } + } + + server { + workingDirectory project.file('run') + + // Recommended logging data for a userdev environment + // The markers can be changed as needed. + // "SCAN": For mods scan. + // "REGISTRIES": For firing of registry events. + // "REGISTRYDUMP": For getting the contents of all registries. + property 'forge.logging.markers', 'REGISTRIES' + + // Recommended logging level for the console + // You can set various levels here. + // Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels + property 'forge.logging.console.level', 'debug' + + mods { + AdvancedBackups { + source sourceSets.main + } + } + } + + data { + workingDirectory project.file('run') + + // Recommended logging data for a userdev environment + // The markers can be changed as needed. + // "SCAN": For mods scan. + // "REGISTRIES": For firing of registry events. + // "REGISTRYDUMP": For getting the contents of all registries. + property 'forge.logging.markers', 'REGISTRIES' + + // Recommended logging level for the console + // You can set various levels here. + // Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels + property 'forge.logging.console.level', 'debug' + + // Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources. + args '--mod', 'AdvancedBackups', '--all', '--output', file('src/generated/resources/'), '--existing', file('src/main/resources/') + + mods { + AdvancedBackups { + source sourceSets.main + } + } + } + } +} + +// Include resources generated by data generators. +sourceSets.main.resources { srcDir 'src/generated/resources' } + +configurations { + // configuration that holds jars to include in the jar + extraLibs +} + +dependencies { + // Specify the version of Minecraft to use, If this is any group other then 'net.minecraft' it is assumed + // that the dep is a ForgeGradle 'patcher' dependency. And it's patches will be applied. + // The userdev artifact is a special name and will get all sorts of transformations applied to it. + minecraft 'net.minecraftforge:forge:1.16.5-36.1.0' + + implementation files('dependencies/jansi-2.4.0.jar') + extraLibs files('dependencies/jansi-2.4.0.jar') + // You may put jars on which you depend on in ./libs or you may define them like so.. + // compile "some.group:artifact:version:classifier" + // compile "some.group:artifact:version" + + // Real examples + // compile 'com.mod-buildcraft:buildcraft:6.0.8:dev' // adds buildcraft to the dev env + // compile 'com.googlecode.efficient-java-matrix-library:ejml:0.24' // adds ejml to the dev env + + // The 'provided' configuration is for optional dependencies that exist at compile-time but might not at runtime. + // provided 'com.mod-buildcraft:buildcraft:6.0.8:dev' + + // These dependencies get remapped to your current MCP mappings + // deobf 'com.mod-buildcraft:buildcraft:6.0.8:dev' + + // For more info... + // http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html + // http://www.gradle.org/docs/current/userguide/dependency_management.html + +} + +// Example for how to get properties into the manifest for reading by the runtime.. +jar { + manifest { + attributes([ + "Main-Class" : "co.uk.mommyheather.advancedbackups.cli.AdvancedBackupsCLI", + "Specification-Title" : "advancedbackups", + "Specification-Vendor" : "raveninthedark", + "Specification-Version" : "1", // We are version 1 of ourselves + "Implementation-Title" : project.name, + "Implementation-Version": "${version}", + "Implementation-Vendor" :"examplemodsareus", + "Implementation-Vendor" : "raveninthedark", + "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ") + ]) + } + from { + configurations.extraLibs.collect { it.isDirectory() ? it : zipTree(it) } + } +} + +// Example configuration to allow publishing using the maven-publish task +// This is the preferred method to reobfuscate your jar file +jar.finalizedBy('reobfJar') +// However if you are in a multi-project build, dev time needs unobfed jar files, so you can delay the obfuscation until publishing by doing +//publish.dependsOn('reobfJar') + +publishing { + publications { + mavenJava(MavenPublication) { + artifact jar + } + } + repositories { + maven { + url "file:///${project.projectDir}/mcmodsrepo" + } + } +} diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 00000000..49f560c5 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,7 @@ +# Sets default memory used for gradle commands. Can be overridden by user or command line properties. +# This is required to provide enough memory for the Minecraft decompilation process. +org.gradle.jvmargs=-Xmx3G +org.gradle.daemon=false + +modloaderName =forge +minecraftVersion =1.18 \ No newline at end of file From f7dd97fb5bc3a7ccf6eebe65a2d243f931a54277 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Thu, 18 May 2023 19:33:13 +0100 Subject: [PATCH 015/580] Initial commit to match v0.1 --- .../advancedbackups/AdvancedBackups.java | 55 +++++++++++++++++++ .../PlatformMethodWrapper.java | 49 +++++++++++++++++ .../resources/META-INF/accesstransformer.cfg | 1 + src/main/resources/META-INF/mods.toml | 28 +++++----- src/main/resources/pack.mcmeta | 7 +-- 5 files changed, 122 insertions(+), 18 deletions(-) create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/PlatformMethodWrapper.java create mode 100644 src/main/resources/META-INF/accesstransformer.cfg diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java new file mode 100644 index 00000000..e6ec8d6f --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -0,0 +1,55 @@ +package co.uk.mommyheather.advancedbackups; + + +import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; +import co.uk.mommyheather.advancedbackups.core.config.AVConfig; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.event.server.FMLServerStartedEvent; +import net.minecraftforge.fml.event.server.FMLServerStartingEvent; +import net.minecraftforge.fml.event.server.FMLServerStoppingEvent; + +import java.util.function.Consumer; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +@Mod("advancedbackups") +public class AdvancedBackups +{ + + private static final Logger LOGGER = LogManager.getLogger(); + + public static final Consumer infoLogger = LOGGER::info; + public static final Consumer warningLogger = LOGGER::warn; + public static final Consumer errorLogger = LOGGER::error; + + + public AdvancedBackups() + { + // Register ourselves for server and other game events we are interested in + MinecraftForge.EVENT_BUS.register(this); + } + + @SubscribeEvent + public void onServerStarting(FMLServerStartingEvent event) + { + // Do something when the server starts + AVConfig.loadOrCreateConfig(); + LOGGER.info("Config loaded!!"); + PlatformMethodWrapper.worldName = event.getServer().getWorldData().getLevelName(); + PlatformMethodWrapper.worldDir = event.getServer().storageSource.getWorldDir(); + + } + + @SubscribeEvent + public void onServerStarted(FMLServerStartedEvent event) { + BackupWrapper.checkStartupBackups(); + } + + @SubscribeEvent + public void onServerStopping(FMLServerStoppingEvent event) { + BackupWrapper.checkShutdownBackups(); + } + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/PlatformMethodWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/PlatformMethodWrapper.java new file mode 100644 index 00000000..95d30f37 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/PlatformMethodWrapper.java @@ -0,0 +1,49 @@ +package co.uk.mommyheather.advancedbackups; + +import java.nio.file.Path; +import java.util.function.Consumer; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.world.server.ServerWorld; +import net.minecraftforge.fml.server.ServerLifecycleHooks; + +public class PlatformMethodWrapper { + + public static String worldName = ""; + public static Path worldDir = null; + public static Boolean activity = false; + public static final Consumer infoLogger = AdvancedBackups.infoLogger; + public static final Consumer warningLogger = AdvancedBackups.warningLogger; + public static final Consumer errorLogger = AdvancedBackups.errorLogger; + + public static final String savesDisabledMessage = "\n\n\n***************************************\nSAVING DISABLED - PREPARING FOR BACKUP!\n***************************************"; + public static final String savesEnabledMessage = "\n\n\n*********************************\nSAVING ENABLED - BACKUP COMPLETE!\n*********************************"; + public static final String saveCompleteMessage = "\n\n\n*************************************\nSAVE COMPLETE - PREPARING FOR BACKUP!\n*************************************"; + + + public static void disableSaving() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + for (ServerWorld level : server.getAllLevels()) { + if (level != null && !level.noSave) { + level.noSave = true; + } + } + warningLogger.accept(savesDisabledMessage); + } + + public static void enableSaving() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + for (ServerWorld level : server.getAllLevels()) { + if (level != null && !level.noSave) { + level.noSave = false; + } + } + warningLogger.accept(savesEnabledMessage); + } + + public static void saveOnce() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + server.saveAllChunks(true, true, true); + warningLogger.accept(saveCompleteMessage); + } +} diff --git a/src/main/resources/META-INF/accesstransformer.cfg b/src/main/resources/META-INF/accesstransformer.cfg new file mode 100644 index 00000000..7b120a32 --- /dev/null +++ b/src/main/resources/META-INF/accesstransformer.cfg @@ -0,0 +1 @@ +public net.minecraft.server.MinecraftServer field_71310_m # storageSource \ No newline at end of file diff --git a/src/main/resources/META-INF/mods.toml b/src/main/resources/META-INF/mods.toml index ad0e6ca5..aabc446e 100644 --- a/src/main/resources/META-INF/mods.toml +++ b/src/main/resources/META-INF/mods.toml @@ -6,57 +6,57 @@ # The name of the mod loader type to load - for regular FML @Mod mods it should be javafml modLoader="javafml" #mandatory # A version range to match for said mod loader - for regular FML @Mod it will be the forge version -loaderVersion="[40,)" #mandatory This is typically bumped every Minecraft version by Forge. See our download page for lists of versions. +loaderVersion="[36,)" #mandatory This is typically bumped every Minecraft version by Forge. See our download page for lists of versions. # The license for you mod. This is mandatory metadata and allows for easier comprehension of your redistributive properties. # Review your options at https://choosealicense.com/. All rights reserved is the default copyright stance, and is thus the default here. -license="MIT" +license="All rights reserved" # A URL to refer people to when problems occur with this mod #issueTrackerURL="https://change.me.to.your.issue.tracker.example.invalid/" #optional # A list of mods - how many allowed here is determined by the individual mod loader [[mods]] #mandatory # The modid of the mod -modId="advancedbackups" #mandatory +modId="examplemod" #mandatory # The version number of the mod - there's a few well known ${} variables useable here or just hardcode it # ${file.jarVersion} will substitute the value of the Implementation-Version as read from the mod's JAR file metadata # see the associated build.gradle script for how to populate this completely automatically during a build version="${file.jarVersion}" #mandatory # A display name for the mod -displayName="Advanced Backups" #mandatory +displayName="Example Mod" #mandatory # A URL to query for updates for this mod. See the JSON update specification https://mcforge.readthedocs.io/en/latest/gettingstarted/autoupdate/ #updateJSONURL="https://change.me.example.invalid/updates.json" #optional # A URL for the "homepage" for this mod, displayed in the mod UI #displayURL="https://change.me.to.your.mods.homepage.example.invalid/" #optional # A file name (in the root of the mod JAR) containing a logo for display -#logoFile="advancedbackups.png" #optional +logoFile="examplemod.png" #optional # A text field displayed in the mod UI -#credits="Thanks for this example mod goes to Java" #optional +credits="Thanks for this example mod goes to Java" #optional # A text field displayed in the mod UI -#authors="Love, Cheese and small house plants" #optional +authors="Love, Cheese and small house plants" #optional # The description text for the mod (multi line!) (#mandatory) description=''' -An extremely advanced backup mod. +This is a long form description of the mod. You can write whatever you want here -Supports many backup types. +Have some lorem ipsum. -Config file and github contain documentation. +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed mollis lacinia magna. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Sed sagittis luctus odio eu tempus. Interdum et malesuada fames ac ante ipsum primis in faucibus. Pellentesque volutpat ligula eget lacus auctor sagittis. In hac habitasse platea dictumst. Nunc gravida elit vitae sem vehicula efficitur. Donec mattis ipsum et arcu lobortis, eleifend sagittis sem rutrum. Cras pharetra quam eget posuere fermentum. Sed id tincidunt justo. Lorem ipsum dolor sit amet, consectetur adipiscing elit. ''' # A dependency - use the . to indicate dependency for a specific modid. Dependencies are optional. -[[dependencies.advancedbackups]] #optional +[[dependencies.examplemod]] #optional # the modid of the dependency modId="forge" #mandatory # Does this dependency have to exist - if not, ordering below must be specified mandatory=true #mandatory # The version range of the dependency - versionRange="[40,)" #mandatory + versionRange="[36,)" #mandatory # An ordering relationship for the dependency - BEFORE or AFTER required if the relationship is not mandatory ordering="NONE" # Side this dependency is applied on - BOTH, CLIENT or SERVER side="BOTH" # Here's another dependency -[[dependencies.advancedbackups]] +[[dependencies.examplemod]] modId="minecraft" mandatory=true # This version range declares a minimum of the current minecraft version up to but not including the next major version - versionRange="[1.18.2,1.19)" + versionRange="[1.16.5,1.17)" ordering="NONE" side="BOTH" diff --git a/src/main/resources/pack.mcmeta b/src/main/resources/pack.mcmeta index 877382f4..c79a3626 100644 --- a/src/main/resources/pack.mcmeta +++ b/src/main/resources/pack.mcmeta @@ -1,8 +1,7 @@ { "pack": { - "description": "advancedbackups resources", - "pack_format": 9, - "forge:resource_pack_format": 8, - "forge:data_pack_format": 9 + "description": "examplemod resources", + "pack_format": 6, + "_comment": "A pack_format of 6 requires json lang files and some texture changes from 1.16.2. Note: we require v6 pack meta for all mods." } } From 8aa5aa716ad46697c7dd089af868253fd8244e77 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Thu, 18 May 2023 19:35:27 +0100 Subject: [PATCH 016/580] Version bump for build --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 49f560c5..ed335388 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,4 +4,4 @@ org.gradle.jvmargs=-Xmx3G org.gradle.daemon=false modloaderName =forge -minecraftVersion =1.18 \ No newline at end of file +minecraftVersion =1.16 \ No newline at end of file From 3f78b1e07451e6e562f83e01fa628762ad7131da Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Thu, 18 May 2023 19:36:51 +0100 Subject: [PATCH 017/580] Version bump for build --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 60ac03c7..17272aec 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,7 @@ yarn_mappings=1.18.2+build.4 loader_version=0.14.19 # Mod Properties -mod_version=0.1 +mod_version=0.2 maven_group=co.uk.mommyheather.advancedbackups archives_base_name=advanced-backups modloaderName =fabric From 36c2709e327491ce46b8f186d44a28b05d216b2c Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Thu, 18 May 2023 19:41:15 +0100 Subject: [PATCH 018/580] Version bump --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 37271587..4d1a8051 100644 --- a/build.gradle +++ b/build.gradle @@ -12,7 +12,7 @@ apply plugin: 'net.minecraftforge.gradle' apply plugin: 'eclipse' apply plugin: 'maven-publish' -version = '0.1' +version = '0.2' group = 'com.github.raveninthedark.advancedbackups' // http://maven.apache.org/guides/mini/guide-naming-conventions.html archivesBaseName = 'AdvancedBackups-' + modloaderName + "-" + minecraftVersion From d27683631326159983dfa1f22de8baae9744ec68 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Thu, 18 May 2023 19:42:46 +0100 Subject: [PATCH 019/580] Version bump --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 6abfa6df..bc7acb09 100644 --- a/build.gradle +++ b/build.gradle @@ -16,8 +16,8 @@ plugins { apply plugin: 'net.minecraftforge.gradle' -version = '0.1' -group = 'com.github.raveninthedark.advancedbackups' // http://maven.apache.org/guides/mini/guide-naming-conventions.html +version = '0.2' +group = 'co.uk.mommyheather.advancedbackups' // http://maven.apache.org/guides/mini/guide-naming-conventions.html archivesBaseName = 'AdvancedBackups-' + modloaderName + "-" + minecraftVersion // Mojang ships Java 17 to end users in 1.18+, so your mod should target Java 17. From f672c7cacec04806de4e234d5246b7bddecb7ec7 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Thu, 18 May 2023 20:13:18 +0000 Subject: [PATCH 020/580] Update core files --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 607ce2c1..12243020 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ Many Minecraft versions are supported - request more if the one you want isn't y ## Current Versions: - Forge 1.18 - Fabric 1.18 +- Forge 1.16 ## Features: Choose between zip, differential or incremental backups. From 2c5f660e58f6b0c6bc1aef4cccad0fd464eb3c3f Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Thu, 18 May 2023 20:13:19 +0000 Subject: [PATCH 021/580] Update core files --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 607ce2c1..12243020 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ Many Minecraft versions are supported - request more if the one you want isn't y ## Current Versions: - Forge 1.18 - Fabric 1.18 +- Forge 1.16 ## Features: Choose between zip, differential or incremental backups. From 0fa97e867d9277edbbcbb03b653bc474863a2b7d Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Thu, 18 May 2023 20:13:20 +0000 Subject: [PATCH 022/580] Update core files --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 607ce2c1..12243020 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ Many Minecraft versions are supported - request more if the one you want isn't y ## Current Versions: - Forge 1.18 - Fabric 1.18 +- Forge 1.16 ## Features: Choose between zip, differential or incremental backups. From d9b64edec9aa6aff044308e03539d27cd7acd915 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Fri, 19 May 2023 00:16:15 +0100 Subject: [PATCH 023/580] 1.12. some restoration needs changing in core library, seemingly a Files#walkFileTree bug... --- .../advancedbackups/AdvancedBackups.java | 84 +++++++++++++++++++ .../PlatformMethodWrapper.java | 50 +++++++++++ .../cli/AdvancedBackupsCLI.java | 15 +--- src/main/resources/mcmod.info | 16 ++++ src/main/resources/pack.mcmeta | 7 +- 5 files changed, 155 insertions(+), 17 deletions(-) create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/PlatformMethodWrapper.java create mode 100644 src/main/resources/mcmod.info diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java new file mode 100644 index 00000000..3a834bf8 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -0,0 +1,84 @@ +package co.uk.mommyheather.advancedbackups; + +import net.minecraft.init.Blocks; +import net.minecraft.server.MinecraftServer; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.Mod.EventHandler; +import net.minecraftforge.fml.common.event.FMLInitializationEvent; +import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; +import net.minecraftforge.fml.common.event.FMLServerStartedEvent; +import net.minecraftforge.fml.common.event.FMLServerStartingEvent; +import net.minecraftforge.fml.common.event.FMLServerStoppingEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.relauncher.Side; + +import org.apache.logging.log4j.Logger; + +import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; +import co.uk.mommyheather.advancedbackups.core.config.AVConfig; +import net.minecraftforge.common.MinecraftForge; + +import java.io.File; +import java.util.function.Consumer; + + +@Mod(modid = AdvancedBackups.MODID, name = AdvancedBackups.NAME, version = AdvancedBackups.VERSION) +public class AdvancedBackups +{ + public static final String MODID = "advancedbackups"; + public static final String NAME = "Advanced Backups"; + public static final String VERSION = "0.1"; + + private static Logger LOGGER; + public static Consumer infoLogger; + public static Consumer warningLogger; + public static Consumer errorLogger; + + public static MinecraftServer server; + + @EventHandler + public void preInit(FMLPreInitializationEvent event) + { + LOGGER = event.getModLog(); + infoLogger = LOGGER::info; + warningLogger = LOGGER::warn; + errorLogger = LOGGER::error; + } + + + + public AdvancedBackups() + { + // Register ourselves for server and other game events we are interested in + MinecraftForge.EVENT_BUS.register(this); + } + + @EventHandler + public void onServerStarting(FMLServerStartingEvent event) + { + // Do something when the server starts + AVConfig.loadOrCreateConfig(); + LOGGER.info("Config loaded!!"); + PlatformMethodWrapper.worldName = event.getServer().worlds[0].getWorldInfo().getWorldName(); + if (event.getSide() == Side.SERVER) { + PlatformMethodWrapper.worldDir = new File(event.getServer().getFolderName()).toPath(); + } + else { + PlatformMethodWrapper.worldDir = new File("saves/" + event.getServer().getFolderName()).toPath(); + } + + server = event.getServer(); + + } + + @EventHandler + public void onServerStarted(FMLServerStartedEvent event) { + BackupWrapper.checkStartupBackups(); + } + + @EventHandler + public void onServerStopping(FMLServerStoppingEvent event) { + BackupWrapper.checkShutdownBackups(); + } + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/PlatformMethodWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/PlatformMethodWrapper.java new file mode 100644 index 00000000..72fa0e4d --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/PlatformMethodWrapper.java @@ -0,0 +1,50 @@ +package co.uk.mommyheather.advancedbackups; + +import java.nio.file.Path; +import java.util.function.Consumer; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.world.World; +import net.minecraft.world.WorldServer; +import net.minecraftforge.fml.server.FMLServerHandler; + +public class PlatformMethodWrapper { + + public static String worldName = ""; + public static Path worldDir = null; + public static Boolean activity = false; + public static final Consumer infoLogger = AdvancedBackups.infoLogger; + public static final Consumer warningLogger = AdvancedBackups.warningLogger; + public static final Consumer errorLogger = AdvancedBackups.errorLogger; + + public static final String savesDisabledMessage = "\n\n\n***************************************\nSAVING DISABLED - PREPARING FOR BACKUP!\n***************************************"; + public static final String savesEnabledMessage = "\n\n\n*********************************\nSAVING ENABLED - BACKUP COMPLETE!\n*********************************"; + public static final String saveCompleteMessage = "\n\n\n*************************************\nSAVE COMPLETE - PREPARING FOR BACKUP!\n*************************************"; + + + public static void disableSaving() { + MinecraftServer server = AdvancedBackups.server; + for (WorldServer level : server.worlds) { + if (level != null && !level.disableLevelSaving) { + level.disableLevelSaving = true; + } + } + warningLogger.accept(savesDisabledMessage); + } + + public static void enableSaving() { + MinecraftServer server = AdvancedBackups.server; + for (WorldServer level : server.worlds) { + if (level != null && !level.disableLevelSaving) { + level.disableLevelSaving = false; + } + } + warningLogger.accept(savesEnabledMessage); + } + + public static void saveOnce() { + MinecraftServer server = AdvancedBackups.server; + server.saveAllWorlds(false); + warningLogger.accept(saveCompleteMessage); + } +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java index b2e879d7..f47cca5d 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java @@ -7,20 +7,9 @@ import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; -import java.nio.file.FileSystem; -import java.nio.file.FileSystems; -import java.nio.file.FileVisitResult; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.SimpleFileVisitor; -import java.nio.file.StandardCopyOption; +import java.nio.file.*; import java.nio.file.attribute.BasicFileAttributes; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.InputMismatchException; -import java.util.Properties; -import java.util.Scanner; +import java.util.*; import java.util.regex.Pattern; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; diff --git a/src/main/resources/mcmod.info b/src/main/resources/mcmod.info new file mode 100644 index 00000000..4797f5eb --- /dev/null +++ b/src/main/resources/mcmod.info @@ -0,0 +1,16 @@ +[ +{ + "modid": "advancedbackups", + "name": "Advanced Backups", + "description": "Powerful backup mod.", + "version": "${version}", + "mcversion": "${mcversion}", + "url": "https://github.com/MommyHeather/AdvancedBackups", + "updateUrl": "", + "authorList": ["MommyHeather"], + "credits": "", + "logoFile": "", + "screenshots": [], + "dependencies": [] +} +] diff --git a/src/main/resources/pack.mcmeta b/src/main/resources/pack.mcmeta index 877382f4..40182676 100644 --- a/src/main/resources/pack.mcmeta +++ b/src/main/resources/pack.mcmeta @@ -1,8 +1,7 @@ { "pack": { - "description": "advancedbackups resources", - "pack_format": 9, - "forge:resource_pack_format": 8, - "forge:data_pack_format": 9 + "description": "examplemod resources", + "pack_format": 3, + "_comment": "A pack_format of 3 should be used starting with Minecraft 1.11. All resources, including language files, should be lowercase (eg: en_us.lang). A pack_format of 2 will load your mod resources with LegacyV2Adapter, which requires language files to have uppercase letters (eg: en_US.lang)." } } From a273e749efc44ccc2be3f51c28f1efac5802b056 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Fri, 19 May 2023 10:16:27 +0000 Subject: [PATCH 024/580] Update core files --- .../cli/AdvancedBackupsCLI.java | 188 +++++++++++------- 1 file changed, 118 insertions(+), 70 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java index b2e879d7..18f8b56a 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java @@ -5,6 +5,7 @@ import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; +import java.io.InputStream; import java.io.PrintWriter; import java.io.StringWriter; import java.nio.file.FileSystem; @@ -17,12 +18,14 @@ import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; import java.util.Collections; +import java.util.Enumeration; import java.util.HashMap; import java.util.InputMismatchException; import java.util.Properties; import java.util.Scanner; import java.util.regex.Pattern; import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; import java.util.zip.ZipInputStream; import org.fusesource.jansi.AnsiConsole; @@ -513,7 +516,7 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) thro } }); - file = getFileToRestore(entries, "", entries); + file = getFileToRestore(entries, ""); info("Restoring " + file.toString() + "..."); Path outputFile = new File(worldFile, file.toString()).toPath(); Files.copy(file, outputFile, StandardCopyOption.REPLACE_EXISTING); @@ -529,8 +532,9 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) thro private static void restorePartialDifferential(int index, File worldFile) { //Do we need to check for past backups? if selected is a full backup, we do not. - HashMap filePaths = new HashMap<>(); + HashMap filePaths = new HashMap<>(); HashMap dates = new HashMap<>(); + HashMap entryOwners = new HashMap<>(); try { File backup = new File(fileNames.get(index)); if (!backup.getName().contains("-full")) { @@ -538,16 +542,16 @@ private static void restorePartialDifferential(int index, File worldFile) { for (int i = index;i>=0;i--) { String name = fileNames.get(i); if (name.contains("-full")) { - addBackupNamesToLists(new File(name), filePaths, dates, "\u001b[31m"); + addBackupNamesToLists(new File(name), entryOwners, filePaths, dates, "\u001b[31m"); break; } } } File file = new File(fileNames.get(index)); - addBackupNamesToLists(file, filePaths, dates, "\u001B[32m"); + addBackupNamesToLists(file, entryOwners, filePaths, dates, "\u001B[32m"); - HashMap properMapping = new HashMap<>(); + HashMap properMapping = new HashMap<>(); for (String date : dates.keySet()) { properMapping.put( date + " " + dates.get(date), @@ -555,28 +559,48 @@ private static void restorePartialDifferential(int index, File worldFile) { ); } - Path select = getFileToRestore(properMapping, "", properMapping); - Path input = select; + Object select = getFileToRestore(properMapping, ""); + if (select instanceof Path) { + Path input = (Path) select; - if (select.toString().replace("\\", "/").contains("-full/")) { - select = new File( - select.toString().replace("\\", "/") - .split("-full/")[1] - ).toPath(); - } - if (select.toString().replace("\\", "/").contains("-partial/")) { - select = new File( - select.toString().replace("\\", "/") - .split("-partial/")[1] - ).toPath(); + + if (select.toString().replace("\\", "/").contains("-full/")) { + select = new File( + select.toString().replace("\\", "/") + .split("-full/")[1] + ).toPath(); + } + if (select.toString().replace("\\", "/").contains("-partial/")) { + select = new File( + select.toString().replace("\\", "/") + .split("-partial/")[1] + ).toPath(); + } + + File outputFile = new File(worldFile, select.toString()); + if (!outputFile.getParentFile().exists()) { + outputFile.getParentFile().mkdirs(); + } + info("\n\nRestoring file : " + select); + Files.copy(input, outputFile.toPath(), StandardCopyOption.REPLACE_EXISTING); } + else if (select instanceof ZipEntry) { + ZipEntry entry = (ZipEntry) select; + + File outputFile = new File(worldFile, entry.toString()); + FileOutputStream outputStream = new FileOutputStream(outputFile); + + info("Restoring " + entry.toString() + "..."); - File outputFile = new File(worldFile, select.toString()); - if (!outputFile.getParentFile().exists()) { - outputFile.getParentFile().mkdirs(); + byte[] buffer = new byte[1028]; + InputStream inputSteam = entryOwners.get(entry.toString()).getInputStream(entry); + int length; + while ((length = inputSteam.read(buffer, 0, buffer.length)) > 0) { + outputStream.write(buffer, 0, length); + } + outputStream.flush(); + outputStream.close(); } - info("\n\nRestoring file : " + select); - Files.copy(input, outputFile.toPath(), StandardCopyOption.REPLACE_EXISTING); } @@ -588,8 +612,9 @@ private static void restorePartialDifferential(int index, File worldFile) { private static void restorePartialIncremental(int index, File worldFile) { //Do we need to check for past backups? if selected is a full backup, we do not. - HashMap filePaths = new HashMap<>(); + HashMap filePaths = new HashMap<>(); HashMap dates = new HashMap<>(); + HashMap entryOwners = new HashMap<>(); try { File backup = new File(fileNames.get(index)); if (!backup.getName().contains("-full")) { @@ -598,22 +623,22 @@ private static void restorePartialIncremental(int index, File worldFile) { for (i = index;i>=0;i--) { String name = fileNames.get(i); if (name.contains("-full")) { - addBackupNamesToLists(new File(name), filePaths, dates, "\u001b[31m"); + addBackupNamesToLists(new File(name), entryOwners, filePaths, dates, "\u001b[31m"); break; } } while (i < index) { String name = fileNames.get(i); - addBackupNamesToLists(new File(name), filePaths, dates, "\u001b[31m"); + addBackupNamesToLists(new File(name), entryOwners, filePaths, dates, "\u001b[31m"); i++; } } File file = new File(fileNames.get(index)); - addBackupNamesToLists(file, filePaths, dates, "\u001B[32m"); + addBackupNamesToLists(file, entryOwners, filePaths, dates, "\u001B[32m"); - HashMap properMapping = new HashMap<>(); + HashMap properMapping = new HashMap<>(); for (String date : dates.keySet()) { properMapping.put( date + " " + dates.get(date), @@ -621,28 +646,48 @@ private static void restorePartialIncremental(int index, File worldFile) { ); } - Path select = getFileToRestore(properMapping, "", properMapping); - Path input = select; + Object select = getFileToRestore(properMapping, ""); + if (select instanceof Path) { + Path input = (Path) select; - if (select.toString().replace("\\", "/").contains("-full/")) { - select = new File( - select.toString().replace("\\", "/") - .split("-full/")[1] - ).toPath(); - } - if (select.toString().replace("\\", "/").contains("-partial/")) { - select = new File( - select.toString().replace("\\", "/") - .split("-partial/")[1] - ).toPath(); + + if (select.toString().replace("\\", "/").contains("-full/")) { + select = new File( + select.toString().replace("\\", "/") + .split("-full/")[1] + ).toPath(); + } + if (select.toString().replace("\\", "/").contains("-partial/")) { + select = new File( + select.toString().replace("\\", "/") + .split("-partial/")[1] + ).toPath(); + } + + File outputFile = new File(worldFile, select.toString()); + if (!outputFile.getParentFile().exists()) { + outputFile.getParentFile().mkdirs(); + } + info("\n\nRestoring file : " + select); + Files.copy(input, outputFile.toPath(), StandardCopyOption.REPLACE_EXISTING); } + else if (select instanceof ZipEntry) { + ZipEntry entry = (ZipEntry) select; - File outputFile = new File(worldFile, select.toString()); - if (!outputFile.getParentFile().exists()) { - outputFile.getParentFile().mkdirs(); + File outputFile = new File(worldFile, entry.toString()); + FileOutputStream outputStream = new FileOutputStream(outputFile); + + info("Restoring " + entry.toString() + "..."); + + byte[] buffer = new byte[1028]; + InputStream inputSteam = entryOwners.get(entry.toString()).getInputStream(entry); + int length; + while ((length = inputSteam.read(buffer, 0, buffer.length)) > 0) { + outputStream.write(buffer, 0, length); + } + outputStream.flush(); + outputStream.close(); } - info("\n\nRestoring file : " + select); - Files.copy(input, outputFile.toPath(), StandardCopyOption.REPLACE_EXISTING); } @@ -701,7 +746,7 @@ public FileVisitResult postVisitDirectory(Path file, java.io.IOException arg1) { } - private static T getFileToRestore(HashMap files, String directory, HashMap original) { + private static T getFileToRestore(HashMap files, String directory) { ArrayList toDisplay = new ArrayList<>(); HashMap keyMap = new HashMap<>(); int index = 1; @@ -742,17 +787,17 @@ private static T getFileToRestore(HashMap files, String directory String line = input.nextLine(); if (line == "") { warn("Please enter a number!"); - return getFileToRestore(files, directory, original); + return getFileToRestore(files, directory); } userInput = Integer.parseInt(line); } catch (InputMismatchException | NumberFormatException e) { warn("That was not a number. Please enter a number."); - return getFileToRestore(files, directory, original); + return getFileToRestore(files, directory); } if (userInput <= 0 || userInput > (directory.equals("") ? toDisplay.size() : toDisplay.size() + 1)) { warn("Please enter a number in the specified range!"); - return getFileToRestore(files, directory, original); + return getFileToRestore(files, directory); } else if (userInput > toDisplay.size()) { return null; @@ -761,12 +806,12 @@ else if (!toDisplay.get(userInput - 1).contains("\u001B[33m directory\u001B[0m return files.get(keyMap.get(toDisplay.get(userInput -1))); } - T result = getFileToRestore(files, directory + toDisplay.get(userInput -1).replace("\u001B[33m directory\u001B[0m ", "") + "/", original); + T result = getFileToRestore(files, directory + toDisplay.get(userInput -1).replace("\u001B[33m directory\u001B[0m ", "") + "/"); if (result != null) { return result; } else { - return getFileToRestore(files, directory, original); + return getFileToRestore(files, directory); } } @@ -788,28 +833,31 @@ private static ArrayList sortStringsAlphabeticallyWithDirectoryPriority( } - private static void addBackupNamesToLists(File file, HashMap filePaths, HashMap dates, String colour) throws IOException { + private static void addBackupNamesToLists(File file, HashMap entryOwners, HashMap filePaths, + HashMap dates, String colour) throws IOException { if (file.isFile()) { - FileSystem zipFs = FileSystems.newFileSystem(file.toPath(), AdvancedBackupsCLI.class.getClassLoader()); - Path root = zipFs.getPath(""); - Files.walkFileTree(root, new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path path, BasicFileAttributes attributes) throws IOException { - String backupName = file.toString().replace("\\", "/"); - filePaths.put(path.toString(), path); - dates.put(path.toString(), colour - + backupName - .substring(backupName.toString().lastIndexOf("/") + 1) - .replace("backup-", "") - .replace("-full.zip", "") - .replace("-partial.zip", "") - + "\u001B[0m"); - return FileVisitResult.CONTINUE; - } - }); + ZipFile zipFile = new ZipFile(file); + Enumeration entryEnum = zipFile.entries(); + + while (entryEnum.hasMoreElements()) { + ZipEntry entry = entryEnum.nextElement(); + + String backupName = file.toString().replace("\\", "/"); + filePaths.put(entry.toString().replace("\\", "/"), entry); + dates.put(entry.toString().replace("\\", "/"), "\u001b[31m" + + backupName + .substring(backupName.toString().lastIndexOf("/") + 1) + .replace("backup-", "") + .replace("-full.zip", "") + .replace("-partial.zip", "") + + "\u001B[0m"); + entryOwners.put(entry.toString(), zipFile); + } + error("aswdasdsa"); } + else { Files.walkFileTree(file.toPath(), new SimpleFileVisitor() { @Override From a7d730e9fd39e4b6531b685275a71be134670b9d Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Fri, 19 May 2023 10:16:28 +0000 Subject: [PATCH 025/580] Update core files --- .../cli/AdvancedBackupsCLI.java | 188 +++++++++++------- 1 file changed, 118 insertions(+), 70 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java index b2e879d7..18f8b56a 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java @@ -5,6 +5,7 @@ import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; +import java.io.InputStream; import java.io.PrintWriter; import java.io.StringWriter; import java.nio.file.FileSystem; @@ -17,12 +18,14 @@ import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; import java.util.Collections; +import java.util.Enumeration; import java.util.HashMap; import java.util.InputMismatchException; import java.util.Properties; import java.util.Scanner; import java.util.regex.Pattern; import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; import java.util.zip.ZipInputStream; import org.fusesource.jansi.AnsiConsole; @@ -513,7 +516,7 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) thro } }); - file = getFileToRestore(entries, "", entries); + file = getFileToRestore(entries, ""); info("Restoring " + file.toString() + "..."); Path outputFile = new File(worldFile, file.toString()).toPath(); Files.copy(file, outputFile, StandardCopyOption.REPLACE_EXISTING); @@ -529,8 +532,9 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) thro private static void restorePartialDifferential(int index, File worldFile) { //Do we need to check for past backups? if selected is a full backup, we do not. - HashMap filePaths = new HashMap<>(); + HashMap filePaths = new HashMap<>(); HashMap dates = new HashMap<>(); + HashMap entryOwners = new HashMap<>(); try { File backup = new File(fileNames.get(index)); if (!backup.getName().contains("-full")) { @@ -538,16 +542,16 @@ private static void restorePartialDifferential(int index, File worldFile) { for (int i = index;i>=0;i--) { String name = fileNames.get(i); if (name.contains("-full")) { - addBackupNamesToLists(new File(name), filePaths, dates, "\u001b[31m"); + addBackupNamesToLists(new File(name), entryOwners, filePaths, dates, "\u001b[31m"); break; } } } File file = new File(fileNames.get(index)); - addBackupNamesToLists(file, filePaths, dates, "\u001B[32m"); + addBackupNamesToLists(file, entryOwners, filePaths, dates, "\u001B[32m"); - HashMap properMapping = new HashMap<>(); + HashMap properMapping = new HashMap<>(); for (String date : dates.keySet()) { properMapping.put( date + " " + dates.get(date), @@ -555,28 +559,48 @@ private static void restorePartialDifferential(int index, File worldFile) { ); } - Path select = getFileToRestore(properMapping, "", properMapping); - Path input = select; + Object select = getFileToRestore(properMapping, ""); + if (select instanceof Path) { + Path input = (Path) select; - if (select.toString().replace("\\", "/").contains("-full/")) { - select = new File( - select.toString().replace("\\", "/") - .split("-full/")[1] - ).toPath(); - } - if (select.toString().replace("\\", "/").contains("-partial/")) { - select = new File( - select.toString().replace("\\", "/") - .split("-partial/")[1] - ).toPath(); + + if (select.toString().replace("\\", "/").contains("-full/")) { + select = new File( + select.toString().replace("\\", "/") + .split("-full/")[1] + ).toPath(); + } + if (select.toString().replace("\\", "/").contains("-partial/")) { + select = new File( + select.toString().replace("\\", "/") + .split("-partial/")[1] + ).toPath(); + } + + File outputFile = new File(worldFile, select.toString()); + if (!outputFile.getParentFile().exists()) { + outputFile.getParentFile().mkdirs(); + } + info("\n\nRestoring file : " + select); + Files.copy(input, outputFile.toPath(), StandardCopyOption.REPLACE_EXISTING); } + else if (select instanceof ZipEntry) { + ZipEntry entry = (ZipEntry) select; + + File outputFile = new File(worldFile, entry.toString()); + FileOutputStream outputStream = new FileOutputStream(outputFile); + + info("Restoring " + entry.toString() + "..."); - File outputFile = new File(worldFile, select.toString()); - if (!outputFile.getParentFile().exists()) { - outputFile.getParentFile().mkdirs(); + byte[] buffer = new byte[1028]; + InputStream inputSteam = entryOwners.get(entry.toString()).getInputStream(entry); + int length; + while ((length = inputSteam.read(buffer, 0, buffer.length)) > 0) { + outputStream.write(buffer, 0, length); + } + outputStream.flush(); + outputStream.close(); } - info("\n\nRestoring file : " + select); - Files.copy(input, outputFile.toPath(), StandardCopyOption.REPLACE_EXISTING); } @@ -588,8 +612,9 @@ private static void restorePartialDifferential(int index, File worldFile) { private static void restorePartialIncremental(int index, File worldFile) { //Do we need to check for past backups? if selected is a full backup, we do not. - HashMap filePaths = new HashMap<>(); + HashMap filePaths = new HashMap<>(); HashMap dates = new HashMap<>(); + HashMap entryOwners = new HashMap<>(); try { File backup = new File(fileNames.get(index)); if (!backup.getName().contains("-full")) { @@ -598,22 +623,22 @@ private static void restorePartialIncremental(int index, File worldFile) { for (i = index;i>=0;i--) { String name = fileNames.get(i); if (name.contains("-full")) { - addBackupNamesToLists(new File(name), filePaths, dates, "\u001b[31m"); + addBackupNamesToLists(new File(name), entryOwners, filePaths, dates, "\u001b[31m"); break; } } while (i < index) { String name = fileNames.get(i); - addBackupNamesToLists(new File(name), filePaths, dates, "\u001b[31m"); + addBackupNamesToLists(new File(name), entryOwners, filePaths, dates, "\u001b[31m"); i++; } } File file = new File(fileNames.get(index)); - addBackupNamesToLists(file, filePaths, dates, "\u001B[32m"); + addBackupNamesToLists(file, entryOwners, filePaths, dates, "\u001B[32m"); - HashMap properMapping = new HashMap<>(); + HashMap properMapping = new HashMap<>(); for (String date : dates.keySet()) { properMapping.put( date + " " + dates.get(date), @@ -621,28 +646,48 @@ private static void restorePartialIncremental(int index, File worldFile) { ); } - Path select = getFileToRestore(properMapping, "", properMapping); - Path input = select; + Object select = getFileToRestore(properMapping, ""); + if (select instanceof Path) { + Path input = (Path) select; - if (select.toString().replace("\\", "/").contains("-full/")) { - select = new File( - select.toString().replace("\\", "/") - .split("-full/")[1] - ).toPath(); - } - if (select.toString().replace("\\", "/").contains("-partial/")) { - select = new File( - select.toString().replace("\\", "/") - .split("-partial/")[1] - ).toPath(); + + if (select.toString().replace("\\", "/").contains("-full/")) { + select = new File( + select.toString().replace("\\", "/") + .split("-full/")[1] + ).toPath(); + } + if (select.toString().replace("\\", "/").contains("-partial/")) { + select = new File( + select.toString().replace("\\", "/") + .split("-partial/")[1] + ).toPath(); + } + + File outputFile = new File(worldFile, select.toString()); + if (!outputFile.getParentFile().exists()) { + outputFile.getParentFile().mkdirs(); + } + info("\n\nRestoring file : " + select); + Files.copy(input, outputFile.toPath(), StandardCopyOption.REPLACE_EXISTING); } + else if (select instanceof ZipEntry) { + ZipEntry entry = (ZipEntry) select; - File outputFile = new File(worldFile, select.toString()); - if (!outputFile.getParentFile().exists()) { - outputFile.getParentFile().mkdirs(); + File outputFile = new File(worldFile, entry.toString()); + FileOutputStream outputStream = new FileOutputStream(outputFile); + + info("Restoring " + entry.toString() + "..."); + + byte[] buffer = new byte[1028]; + InputStream inputSteam = entryOwners.get(entry.toString()).getInputStream(entry); + int length; + while ((length = inputSteam.read(buffer, 0, buffer.length)) > 0) { + outputStream.write(buffer, 0, length); + } + outputStream.flush(); + outputStream.close(); } - info("\n\nRestoring file : " + select); - Files.copy(input, outputFile.toPath(), StandardCopyOption.REPLACE_EXISTING); } @@ -701,7 +746,7 @@ public FileVisitResult postVisitDirectory(Path file, java.io.IOException arg1) { } - private static T getFileToRestore(HashMap files, String directory, HashMap original) { + private static T getFileToRestore(HashMap files, String directory) { ArrayList toDisplay = new ArrayList<>(); HashMap keyMap = new HashMap<>(); int index = 1; @@ -742,17 +787,17 @@ private static T getFileToRestore(HashMap files, String directory String line = input.nextLine(); if (line == "") { warn("Please enter a number!"); - return getFileToRestore(files, directory, original); + return getFileToRestore(files, directory); } userInput = Integer.parseInt(line); } catch (InputMismatchException | NumberFormatException e) { warn("That was not a number. Please enter a number."); - return getFileToRestore(files, directory, original); + return getFileToRestore(files, directory); } if (userInput <= 0 || userInput > (directory.equals("") ? toDisplay.size() : toDisplay.size() + 1)) { warn("Please enter a number in the specified range!"); - return getFileToRestore(files, directory, original); + return getFileToRestore(files, directory); } else if (userInput > toDisplay.size()) { return null; @@ -761,12 +806,12 @@ else if (!toDisplay.get(userInput - 1).contains("\u001B[33m directory\u001B[0m return files.get(keyMap.get(toDisplay.get(userInput -1))); } - T result = getFileToRestore(files, directory + toDisplay.get(userInput -1).replace("\u001B[33m directory\u001B[0m ", "") + "/", original); + T result = getFileToRestore(files, directory + toDisplay.get(userInput -1).replace("\u001B[33m directory\u001B[0m ", "") + "/"); if (result != null) { return result; } else { - return getFileToRestore(files, directory, original); + return getFileToRestore(files, directory); } } @@ -788,28 +833,31 @@ private static ArrayList sortStringsAlphabeticallyWithDirectoryPriority( } - private static void addBackupNamesToLists(File file, HashMap filePaths, HashMap dates, String colour) throws IOException { + private static void addBackupNamesToLists(File file, HashMap entryOwners, HashMap filePaths, + HashMap dates, String colour) throws IOException { if (file.isFile()) { - FileSystem zipFs = FileSystems.newFileSystem(file.toPath(), AdvancedBackupsCLI.class.getClassLoader()); - Path root = zipFs.getPath(""); - Files.walkFileTree(root, new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path path, BasicFileAttributes attributes) throws IOException { - String backupName = file.toString().replace("\\", "/"); - filePaths.put(path.toString(), path); - dates.put(path.toString(), colour - + backupName - .substring(backupName.toString().lastIndexOf("/") + 1) - .replace("backup-", "") - .replace("-full.zip", "") - .replace("-partial.zip", "") - + "\u001B[0m"); - return FileVisitResult.CONTINUE; - } - }); + ZipFile zipFile = new ZipFile(file); + Enumeration entryEnum = zipFile.entries(); + + while (entryEnum.hasMoreElements()) { + ZipEntry entry = entryEnum.nextElement(); + + String backupName = file.toString().replace("\\", "/"); + filePaths.put(entry.toString().replace("\\", "/"), entry); + dates.put(entry.toString().replace("\\", "/"), "\u001b[31m" + + backupName + .substring(backupName.toString().lastIndexOf("/") + 1) + .replace("backup-", "") + .replace("-full.zip", "") + .replace("-partial.zip", "") + + "\u001B[0m"); + entryOwners.put(entry.toString(), zipFile); + } + error("aswdasdsa"); } + else { Files.walkFileTree(file.toPath(), new SimpleFileVisitor() { @Override From 012549757d7aa75f887cedbfa73d3045c12e9d8c Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Fri, 19 May 2023 10:16:29 +0000 Subject: [PATCH 026/580] Update core files --- .../cli/AdvancedBackupsCLI.java | 188 +++++++++++------- 1 file changed, 118 insertions(+), 70 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java index b2e879d7..18f8b56a 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java @@ -5,6 +5,7 @@ import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; +import java.io.InputStream; import java.io.PrintWriter; import java.io.StringWriter; import java.nio.file.FileSystem; @@ -17,12 +18,14 @@ import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; import java.util.Collections; +import java.util.Enumeration; import java.util.HashMap; import java.util.InputMismatchException; import java.util.Properties; import java.util.Scanner; import java.util.regex.Pattern; import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; import java.util.zip.ZipInputStream; import org.fusesource.jansi.AnsiConsole; @@ -513,7 +516,7 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) thro } }); - file = getFileToRestore(entries, "", entries); + file = getFileToRestore(entries, ""); info("Restoring " + file.toString() + "..."); Path outputFile = new File(worldFile, file.toString()).toPath(); Files.copy(file, outputFile, StandardCopyOption.REPLACE_EXISTING); @@ -529,8 +532,9 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) thro private static void restorePartialDifferential(int index, File worldFile) { //Do we need to check for past backups? if selected is a full backup, we do not. - HashMap filePaths = new HashMap<>(); + HashMap filePaths = new HashMap<>(); HashMap dates = new HashMap<>(); + HashMap entryOwners = new HashMap<>(); try { File backup = new File(fileNames.get(index)); if (!backup.getName().contains("-full")) { @@ -538,16 +542,16 @@ private static void restorePartialDifferential(int index, File worldFile) { for (int i = index;i>=0;i--) { String name = fileNames.get(i); if (name.contains("-full")) { - addBackupNamesToLists(new File(name), filePaths, dates, "\u001b[31m"); + addBackupNamesToLists(new File(name), entryOwners, filePaths, dates, "\u001b[31m"); break; } } } File file = new File(fileNames.get(index)); - addBackupNamesToLists(file, filePaths, dates, "\u001B[32m"); + addBackupNamesToLists(file, entryOwners, filePaths, dates, "\u001B[32m"); - HashMap properMapping = new HashMap<>(); + HashMap properMapping = new HashMap<>(); for (String date : dates.keySet()) { properMapping.put( date + " " + dates.get(date), @@ -555,28 +559,48 @@ private static void restorePartialDifferential(int index, File worldFile) { ); } - Path select = getFileToRestore(properMapping, "", properMapping); - Path input = select; + Object select = getFileToRestore(properMapping, ""); + if (select instanceof Path) { + Path input = (Path) select; - if (select.toString().replace("\\", "/").contains("-full/")) { - select = new File( - select.toString().replace("\\", "/") - .split("-full/")[1] - ).toPath(); - } - if (select.toString().replace("\\", "/").contains("-partial/")) { - select = new File( - select.toString().replace("\\", "/") - .split("-partial/")[1] - ).toPath(); + + if (select.toString().replace("\\", "/").contains("-full/")) { + select = new File( + select.toString().replace("\\", "/") + .split("-full/")[1] + ).toPath(); + } + if (select.toString().replace("\\", "/").contains("-partial/")) { + select = new File( + select.toString().replace("\\", "/") + .split("-partial/")[1] + ).toPath(); + } + + File outputFile = new File(worldFile, select.toString()); + if (!outputFile.getParentFile().exists()) { + outputFile.getParentFile().mkdirs(); + } + info("\n\nRestoring file : " + select); + Files.copy(input, outputFile.toPath(), StandardCopyOption.REPLACE_EXISTING); } + else if (select instanceof ZipEntry) { + ZipEntry entry = (ZipEntry) select; + + File outputFile = new File(worldFile, entry.toString()); + FileOutputStream outputStream = new FileOutputStream(outputFile); + + info("Restoring " + entry.toString() + "..."); - File outputFile = new File(worldFile, select.toString()); - if (!outputFile.getParentFile().exists()) { - outputFile.getParentFile().mkdirs(); + byte[] buffer = new byte[1028]; + InputStream inputSteam = entryOwners.get(entry.toString()).getInputStream(entry); + int length; + while ((length = inputSteam.read(buffer, 0, buffer.length)) > 0) { + outputStream.write(buffer, 0, length); + } + outputStream.flush(); + outputStream.close(); } - info("\n\nRestoring file : " + select); - Files.copy(input, outputFile.toPath(), StandardCopyOption.REPLACE_EXISTING); } @@ -588,8 +612,9 @@ private static void restorePartialDifferential(int index, File worldFile) { private static void restorePartialIncremental(int index, File worldFile) { //Do we need to check for past backups? if selected is a full backup, we do not. - HashMap filePaths = new HashMap<>(); + HashMap filePaths = new HashMap<>(); HashMap dates = new HashMap<>(); + HashMap entryOwners = new HashMap<>(); try { File backup = new File(fileNames.get(index)); if (!backup.getName().contains("-full")) { @@ -598,22 +623,22 @@ private static void restorePartialIncremental(int index, File worldFile) { for (i = index;i>=0;i--) { String name = fileNames.get(i); if (name.contains("-full")) { - addBackupNamesToLists(new File(name), filePaths, dates, "\u001b[31m"); + addBackupNamesToLists(new File(name), entryOwners, filePaths, dates, "\u001b[31m"); break; } } while (i < index) { String name = fileNames.get(i); - addBackupNamesToLists(new File(name), filePaths, dates, "\u001b[31m"); + addBackupNamesToLists(new File(name), entryOwners, filePaths, dates, "\u001b[31m"); i++; } } File file = new File(fileNames.get(index)); - addBackupNamesToLists(file, filePaths, dates, "\u001B[32m"); + addBackupNamesToLists(file, entryOwners, filePaths, dates, "\u001B[32m"); - HashMap properMapping = new HashMap<>(); + HashMap properMapping = new HashMap<>(); for (String date : dates.keySet()) { properMapping.put( date + " " + dates.get(date), @@ -621,28 +646,48 @@ private static void restorePartialIncremental(int index, File worldFile) { ); } - Path select = getFileToRestore(properMapping, "", properMapping); - Path input = select; + Object select = getFileToRestore(properMapping, ""); + if (select instanceof Path) { + Path input = (Path) select; - if (select.toString().replace("\\", "/").contains("-full/")) { - select = new File( - select.toString().replace("\\", "/") - .split("-full/")[1] - ).toPath(); - } - if (select.toString().replace("\\", "/").contains("-partial/")) { - select = new File( - select.toString().replace("\\", "/") - .split("-partial/")[1] - ).toPath(); + + if (select.toString().replace("\\", "/").contains("-full/")) { + select = new File( + select.toString().replace("\\", "/") + .split("-full/")[1] + ).toPath(); + } + if (select.toString().replace("\\", "/").contains("-partial/")) { + select = new File( + select.toString().replace("\\", "/") + .split("-partial/")[1] + ).toPath(); + } + + File outputFile = new File(worldFile, select.toString()); + if (!outputFile.getParentFile().exists()) { + outputFile.getParentFile().mkdirs(); + } + info("\n\nRestoring file : " + select); + Files.copy(input, outputFile.toPath(), StandardCopyOption.REPLACE_EXISTING); } + else if (select instanceof ZipEntry) { + ZipEntry entry = (ZipEntry) select; - File outputFile = new File(worldFile, select.toString()); - if (!outputFile.getParentFile().exists()) { - outputFile.getParentFile().mkdirs(); + File outputFile = new File(worldFile, entry.toString()); + FileOutputStream outputStream = new FileOutputStream(outputFile); + + info("Restoring " + entry.toString() + "..."); + + byte[] buffer = new byte[1028]; + InputStream inputSteam = entryOwners.get(entry.toString()).getInputStream(entry); + int length; + while ((length = inputSteam.read(buffer, 0, buffer.length)) > 0) { + outputStream.write(buffer, 0, length); + } + outputStream.flush(); + outputStream.close(); } - info("\n\nRestoring file : " + select); - Files.copy(input, outputFile.toPath(), StandardCopyOption.REPLACE_EXISTING); } @@ -701,7 +746,7 @@ public FileVisitResult postVisitDirectory(Path file, java.io.IOException arg1) { } - private static T getFileToRestore(HashMap files, String directory, HashMap original) { + private static T getFileToRestore(HashMap files, String directory) { ArrayList toDisplay = new ArrayList<>(); HashMap keyMap = new HashMap<>(); int index = 1; @@ -742,17 +787,17 @@ private static T getFileToRestore(HashMap files, String directory String line = input.nextLine(); if (line == "") { warn("Please enter a number!"); - return getFileToRestore(files, directory, original); + return getFileToRestore(files, directory); } userInput = Integer.parseInt(line); } catch (InputMismatchException | NumberFormatException e) { warn("That was not a number. Please enter a number."); - return getFileToRestore(files, directory, original); + return getFileToRestore(files, directory); } if (userInput <= 0 || userInput > (directory.equals("") ? toDisplay.size() : toDisplay.size() + 1)) { warn("Please enter a number in the specified range!"); - return getFileToRestore(files, directory, original); + return getFileToRestore(files, directory); } else if (userInput > toDisplay.size()) { return null; @@ -761,12 +806,12 @@ else if (!toDisplay.get(userInput - 1).contains("\u001B[33m directory\u001B[0m return files.get(keyMap.get(toDisplay.get(userInput -1))); } - T result = getFileToRestore(files, directory + toDisplay.get(userInput -1).replace("\u001B[33m directory\u001B[0m ", "") + "/", original); + T result = getFileToRestore(files, directory + toDisplay.get(userInput -1).replace("\u001B[33m directory\u001B[0m ", "") + "/"); if (result != null) { return result; } else { - return getFileToRestore(files, directory, original); + return getFileToRestore(files, directory); } } @@ -788,28 +833,31 @@ private static ArrayList sortStringsAlphabeticallyWithDirectoryPriority( } - private static void addBackupNamesToLists(File file, HashMap filePaths, HashMap dates, String colour) throws IOException { + private static void addBackupNamesToLists(File file, HashMap entryOwners, HashMap filePaths, + HashMap dates, String colour) throws IOException { if (file.isFile()) { - FileSystem zipFs = FileSystems.newFileSystem(file.toPath(), AdvancedBackupsCLI.class.getClassLoader()); - Path root = zipFs.getPath(""); - Files.walkFileTree(root, new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path path, BasicFileAttributes attributes) throws IOException { - String backupName = file.toString().replace("\\", "/"); - filePaths.put(path.toString(), path); - dates.put(path.toString(), colour - + backupName - .substring(backupName.toString().lastIndexOf("/") + 1) - .replace("backup-", "") - .replace("-full.zip", "") - .replace("-partial.zip", "") - + "\u001B[0m"); - return FileVisitResult.CONTINUE; - } - }); + ZipFile zipFile = new ZipFile(file); + Enumeration entryEnum = zipFile.entries(); + + while (entryEnum.hasMoreElements()) { + ZipEntry entry = entryEnum.nextElement(); + + String backupName = file.toString().replace("\\", "/"); + filePaths.put(entry.toString().replace("\\", "/"), entry); + dates.put(entry.toString().replace("\\", "/"), "\u001b[31m" + + backupName + .substring(backupName.toString().lastIndexOf("/") + 1) + .replace("backup-", "") + .replace("-full.zip", "") + .replace("-partial.zip", "") + + "\u001B[0m"); + entryOwners.put(entry.toString(), zipFile); + } + error("aswdasdsa"); } + else { Files.walkFileTree(file.toPath(), new SimpleFileVisitor() { @Override From f3563c10d5e333476d6a3f7ff3d7b4a228306aa0 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Fri, 19 May 2023 10:20:03 +0000 Subject: [PATCH 027/580] Update core files --- README.md | 1 + .../cli/AdvancedBackupsCLI.java | 203 +++++++++++------- 2 files changed, 132 insertions(+), 72 deletions(-) diff --git a/README.md b/README.md index 607ce2c1..12243020 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ Many Minecraft versions are supported - request more if the one you want isn't y ## Current Versions: - Forge 1.18 - Fabric 1.18 +- Forge 1.16 ## Features: Choose between zip, differential or incremental backups. diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java index f47cca5d..18f8b56a 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java @@ -5,13 +5,27 @@ import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; +import java.io.InputStream; import java.io.PrintWriter; import java.io.StringWriter; -import java.nio.file.*; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.StandardCopyOption; import java.nio.file.attribute.BasicFileAttributes; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.InputMismatchException; +import java.util.Properties; +import java.util.Scanner; import java.util.regex.Pattern; import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; import java.util.zip.ZipInputStream; import org.fusesource.jansi.AnsiConsole; @@ -502,7 +516,7 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) thro } }); - file = getFileToRestore(entries, "", entries); + file = getFileToRestore(entries, ""); info("Restoring " + file.toString() + "..."); Path outputFile = new File(worldFile, file.toString()).toPath(); Files.copy(file, outputFile, StandardCopyOption.REPLACE_EXISTING); @@ -518,8 +532,9 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) thro private static void restorePartialDifferential(int index, File worldFile) { //Do we need to check for past backups? if selected is a full backup, we do not. - HashMap filePaths = new HashMap<>(); + HashMap filePaths = new HashMap<>(); HashMap dates = new HashMap<>(); + HashMap entryOwners = new HashMap<>(); try { File backup = new File(fileNames.get(index)); if (!backup.getName().contains("-full")) { @@ -527,16 +542,16 @@ private static void restorePartialDifferential(int index, File worldFile) { for (int i = index;i>=0;i--) { String name = fileNames.get(i); if (name.contains("-full")) { - addBackupNamesToLists(new File(name), filePaths, dates, "\u001b[31m"); + addBackupNamesToLists(new File(name), entryOwners, filePaths, dates, "\u001b[31m"); break; } } } File file = new File(fileNames.get(index)); - addBackupNamesToLists(file, filePaths, dates, "\u001B[32m"); + addBackupNamesToLists(file, entryOwners, filePaths, dates, "\u001B[32m"); - HashMap properMapping = new HashMap<>(); + HashMap properMapping = new HashMap<>(); for (String date : dates.keySet()) { properMapping.put( date + " " + dates.get(date), @@ -544,28 +559,48 @@ private static void restorePartialDifferential(int index, File worldFile) { ); } - Path select = getFileToRestore(properMapping, "", properMapping); - Path input = select; + Object select = getFileToRestore(properMapping, ""); + if (select instanceof Path) { + Path input = (Path) select; - if (select.toString().replace("\\", "/").contains("-full/")) { - select = new File( - select.toString().replace("\\", "/") - .split("-full/")[1] - ).toPath(); - } - if (select.toString().replace("\\", "/").contains("-partial/")) { - select = new File( - select.toString().replace("\\", "/") - .split("-partial/")[1] - ).toPath(); + + if (select.toString().replace("\\", "/").contains("-full/")) { + select = new File( + select.toString().replace("\\", "/") + .split("-full/")[1] + ).toPath(); + } + if (select.toString().replace("\\", "/").contains("-partial/")) { + select = new File( + select.toString().replace("\\", "/") + .split("-partial/")[1] + ).toPath(); + } + + File outputFile = new File(worldFile, select.toString()); + if (!outputFile.getParentFile().exists()) { + outputFile.getParentFile().mkdirs(); + } + info("\n\nRestoring file : " + select); + Files.copy(input, outputFile.toPath(), StandardCopyOption.REPLACE_EXISTING); } + else if (select instanceof ZipEntry) { + ZipEntry entry = (ZipEntry) select; + + File outputFile = new File(worldFile, entry.toString()); + FileOutputStream outputStream = new FileOutputStream(outputFile); + + info("Restoring " + entry.toString() + "..."); - File outputFile = new File(worldFile, select.toString()); - if (!outputFile.getParentFile().exists()) { - outputFile.getParentFile().mkdirs(); + byte[] buffer = new byte[1028]; + InputStream inputSteam = entryOwners.get(entry.toString()).getInputStream(entry); + int length; + while ((length = inputSteam.read(buffer, 0, buffer.length)) > 0) { + outputStream.write(buffer, 0, length); + } + outputStream.flush(); + outputStream.close(); } - info("\n\nRestoring file : " + select); - Files.copy(input, outputFile.toPath(), StandardCopyOption.REPLACE_EXISTING); } @@ -577,8 +612,9 @@ private static void restorePartialDifferential(int index, File worldFile) { private static void restorePartialIncremental(int index, File worldFile) { //Do we need to check for past backups? if selected is a full backup, we do not. - HashMap filePaths = new HashMap<>(); + HashMap filePaths = new HashMap<>(); HashMap dates = new HashMap<>(); + HashMap entryOwners = new HashMap<>(); try { File backup = new File(fileNames.get(index)); if (!backup.getName().contains("-full")) { @@ -587,22 +623,22 @@ private static void restorePartialIncremental(int index, File worldFile) { for (i = index;i>=0;i--) { String name = fileNames.get(i); if (name.contains("-full")) { - addBackupNamesToLists(new File(name), filePaths, dates, "\u001b[31m"); + addBackupNamesToLists(new File(name), entryOwners, filePaths, dates, "\u001b[31m"); break; } } while (i < index) { String name = fileNames.get(i); - addBackupNamesToLists(new File(name), filePaths, dates, "\u001b[31m"); + addBackupNamesToLists(new File(name), entryOwners, filePaths, dates, "\u001b[31m"); i++; } } File file = new File(fileNames.get(index)); - addBackupNamesToLists(file, filePaths, dates, "\u001B[32m"); + addBackupNamesToLists(file, entryOwners, filePaths, dates, "\u001B[32m"); - HashMap properMapping = new HashMap<>(); + HashMap properMapping = new HashMap<>(); for (String date : dates.keySet()) { properMapping.put( date + " " + dates.get(date), @@ -610,28 +646,48 @@ private static void restorePartialIncremental(int index, File worldFile) { ); } - Path select = getFileToRestore(properMapping, "", properMapping); - Path input = select; + Object select = getFileToRestore(properMapping, ""); + if (select instanceof Path) { + Path input = (Path) select; - if (select.toString().replace("\\", "/").contains("-full/")) { - select = new File( - select.toString().replace("\\", "/") - .split("-full/")[1] - ).toPath(); - } - if (select.toString().replace("\\", "/").contains("-partial/")) { - select = new File( - select.toString().replace("\\", "/") - .split("-partial/")[1] - ).toPath(); + + if (select.toString().replace("\\", "/").contains("-full/")) { + select = new File( + select.toString().replace("\\", "/") + .split("-full/")[1] + ).toPath(); + } + if (select.toString().replace("\\", "/").contains("-partial/")) { + select = new File( + select.toString().replace("\\", "/") + .split("-partial/")[1] + ).toPath(); + } + + File outputFile = new File(worldFile, select.toString()); + if (!outputFile.getParentFile().exists()) { + outputFile.getParentFile().mkdirs(); + } + info("\n\nRestoring file : " + select); + Files.copy(input, outputFile.toPath(), StandardCopyOption.REPLACE_EXISTING); } + else if (select instanceof ZipEntry) { + ZipEntry entry = (ZipEntry) select; - File outputFile = new File(worldFile, select.toString()); - if (!outputFile.getParentFile().exists()) { - outputFile.getParentFile().mkdirs(); + File outputFile = new File(worldFile, entry.toString()); + FileOutputStream outputStream = new FileOutputStream(outputFile); + + info("Restoring " + entry.toString() + "..."); + + byte[] buffer = new byte[1028]; + InputStream inputSteam = entryOwners.get(entry.toString()).getInputStream(entry); + int length; + while ((length = inputSteam.read(buffer, 0, buffer.length)) > 0) { + outputStream.write(buffer, 0, length); + } + outputStream.flush(); + outputStream.close(); } - info("\n\nRestoring file : " + select); - Files.copy(input, outputFile.toPath(), StandardCopyOption.REPLACE_EXISTING); } @@ -690,7 +746,7 @@ public FileVisitResult postVisitDirectory(Path file, java.io.IOException arg1) { } - private static T getFileToRestore(HashMap files, String directory, HashMap original) { + private static T getFileToRestore(HashMap files, String directory) { ArrayList toDisplay = new ArrayList<>(); HashMap keyMap = new HashMap<>(); int index = 1; @@ -731,17 +787,17 @@ private static T getFileToRestore(HashMap files, String directory String line = input.nextLine(); if (line == "") { warn("Please enter a number!"); - return getFileToRestore(files, directory, original); + return getFileToRestore(files, directory); } userInput = Integer.parseInt(line); } catch (InputMismatchException | NumberFormatException e) { warn("That was not a number. Please enter a number."); - return getFileToRestore(files, directory, original); + return getFileToRestore(files, directory); } if (userInput <= 0 || userInput > (directory.equals("") ? toDisplay.size() : toDisplay.size() + 1)) { warn("Please enter a number in the specified range!"); - return getFileToRestore(files, directory, original); + return getFileToRestore(files, directory); } else if (userInput > toDisplay.size()) { return null; @@ -750,12 +806,12 @@ else if (!toDisplay.get(userInput - 1).contains("\u001B[33m directory\u001B[0m return files.get(keyMap.get(toDisplay.get(userInput -1))); } - T result = getFileToRestore(files, directory + toDisplay.get(userInput -1).replace("\u001B[33m directory\u001B[0m ", "") + "/", original); + T result = getFileToRestore(files, directory + toDisplay.get(userInput -1).replace("\u001B[33m directory\u001B[0m ", "") + "/"); if (result != null) { return result; } else { - return getFileToRestore(files, directory, original); + return getFileToRestore(files, directory); } } @@ -777,28 +833,31 @@ private static ArrayList sortStringsAlphabeticallyWithDirectoryPriority( } - private static void addBackupNamesToLists(File file, HashMap filePaths, HashMap dates, String colour) throws IOException { + private static void addBackupNamesToLists(File file, HashMap entryOwners, HashMap filePaths, + HashMap dates, String colour) throws IOException { if (file.isFile()) { - FileSystem zipFs = FileSystems.newFileSystem(file.toPath(), AdvancedBackupsCLI.class.getClassLoader()); - Path root = zipFs.getPath(""); - Files.walkFileTree(root, new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path path, BasicFileAttributes attributes) throws IOException { - String backupName = file.toString().replace("\\", "/"); - filePaths.put(path.toString(), path); - dates.put(path.toString(), colour - + backupName - .substring(backupName.toString().lastIndexOf("/") + 1) - .replace("backup-", "") - .replace("-full.zip", "") - .replace("-partial.zip", "") - + "\u001B[0m"); - return FileVisitResult.CONTINUE; - } - }); + ZipFile zipFile = new ZipFile(file); + Enumeration entryEnum = zipFile.entries(); + + while (entryEnum.hasMoreElements()) { + ZipEntry entry = entryEnum.nextElement(); + + String backupName = file.toString().replace("\\", "/"); + filePaths.put(entry.toString().replace("\\", "/"), entry); + dates.put(entry.toString().replace("\\", "/"), "\u001b[31m" + + backupName + .substring(backupName.toString().lastIndexOf("/") + 1) + .replace("backup-", "") + .replace("-full.zip", "") + .replace("-partial.zip", "") + + "\u001B[0m"); + entryOwners.put(entry.toString(), zipFile); + } + error("aswdasdsa"); } + else { Files.walkFileTree(file.toPath(), new SimpleFileVisitor() { @Override From 4594c37902e7a3ee819d9790cf1f1c11c6df6206 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Fri, 19 May 2023 10:36:31 +0000 Subject: [PATCH 028/580] Update core files --- .../advancedbackups/cli/AdvancedBackupsCLI.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java index 18f8b56a..f9720427 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java @@ -39,8 +39,10 @@ public class AdvancedBackupsCLI { private static ArrayList fileNames = new ArrayList<>(); private static File worldFile; public static void main(String args[]){ - - AnsiConsole.systemInstall(); //this gets ansi escape codes working on windows. this was a FUCKING PAIN IN MY ASS + + if (System.console() != null) { + AnsiConsole.systemInstall(); //this gets ansi escape codes working on windows. this was a FUCKING PAIN IN MY ASS + } info("Advanced Backups - Version " + AdvancedBackupsCLI.class.getPackage().getImplementationVersion()); From 4b24db86241c9a5a45e5801f0e5416ddcca6581b Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Fri, 19 May 2023 10:36:32 +0000 Subject: [PATCH 029/580] Update core files --- .../advancedbackups/cli/AdvancedBackupsCLI.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java index 18f8b56a..f9720427 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java @@ -39,8 +39,10 @@ public class AdvancedBackupsCLI { private static ArrayList fileNames = new ArrayList<>(); private static File worldFile; public static void main(String args[]){ - - AnsiConsole.systemInstall(); //this gets ansi escape codes working on windows. this was a FUCKING PAIN IN MY ASS + + if (System.console() != null) { + AnsiConsole.systemInstall(); //this gets ansi escape codes working on windows. this was a FUCKING PAIN IN MY ASS + } info("Advanced Backups - Version " + AdvancedBackupsCLI.class.getPackage().getImplementationVersion()); From 9434c043fc8543f3bd935895ab9abfc27bf246fe Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Fri, 19 May 2023 10:36:33 +0000 Subject: [PATCH 030/580] Update core files --- .../advancedbackups/cli/AdvancedBackupsCLI.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java index 18f8b56a..f9720427 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java @@ -39,8 +39,10 @@ public class AdvancedBackupsCLI { private static ArrayList fileNames = new ArrayList<>(); private static File worldFile; public static void main(String args[]){ - - AnsiConsole.systemInstall(); //this gets ansi escape codes working on windows. this was a FUCKING PAIN IN MY ASS + + if (System.console() != null) { + AnsiConsole.systemInstall(); //this gets ansi escape codes working on windows. this was a FUCKING PAIN IN MY ASS + } info("Advanced Backups - Version " + AdvancedBackupsCLI.class.getPackage().getImplementationVersion()); From a483af902d607a52da1a96ee6a0259ae0325f4d9 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Fri, 19 May 2023 10:36:34 +0000 Subject: [PATCH 031/580] Update core files --- .../advancedbackups/cli/AdvancedBackupsCLI.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java index 18f8b56a..f9720427 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java @@ -39,8 +39,10 @@ public class AdvancedBackupsCLI { private static ArrayList fileNames = new ArrayList<>(); private static File worldFile; public static void main(String args[]){ - - AnsiConsole.systemInstall(); //this gets ansi escape codes working on windows. this was a FUCKING PAIN IN MY ASS + + if (System.console() != null) { + AnsiConsole.systemInstall(); //this gets ansi escape codes working on windows. this was a FUCKING PAIN IN MY ASS + } info("Advanced Backups - Version " + AdvancedBackupsCLI.class.getPackage().getImplementationVersion()); From c6e8e81c35e98e7b0e780ecb7e630efd638d1dbf Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Fri, 19 May 2023 10:53:28 +0000 Subject: [PATCH 032/580] Update core files --- .../advancedbackups/cli/AdvancedBackupsCLI.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java index f9720427..a0bc2b23 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java @@ -760,7 +760,7 @@ private static T getFileToRestore(HashMap files, String directory name2 = name2.replace(worldFile.getName() + "/", ""); } if (name2.contains("/")) { - name2 = "\u001B[33m directory\u001B[0m " + name2.split("/")[0]; + name2 = "\u001B[33mdirectory\u001B[0m " + name2.split("/")[0]; } if (!toDisplay.contains(name2)) { toDisplay.add(name2); @@ -804,11 +804,11 @@ private static T getFileToRestore(HashMap files, String directory else if (userInput > toDisplay.size()) { return null; } - else if (!toDisplay.get(userInput - 1).contains("\u001B[33m directory\u001B[0m ")) { + else if (!toDisplay.get(userInput - 1).contains("\u001B[33mdirectory\u001B[0m ")) { return files.get(keyMap.get(toDisplay.get(userInput -1))); } - T result = getFileToRestore(files, directory + toDisplay.get(userInput -1).replace("\u001B[33m directory\u001B[0m ", "") + "/"); + T result = getFileToRestore(files, directory + toDisplay.get(userInput -1).replace("\u001B[33mdirectory\u001B[0m ", "") + "/"); if (result != null) { return result; } @@ -822,12 +822,12 @@ private static ArrayList sortStringsAlphabeticallyWithDirectoryPriority( ArrayList out = new ArrayList<>(); Collections.sort(in); for (String string : in) { - if (string.contains("\u001B[33m directory\u001B[0m")) { + if (string.contains("\u001B[33mdirectory\u001B[0m")) { out.add(string); } } for (String string : in) { - if (!string.contains("\u001B[33m directory\u001B[0m")) { + if (!string.contains("\u001B[33mdirectory\u001B[0m")) { out.add(string); } } @@ -857,7 +857,6 @@ private static void addBackupNamesToLists(File file, HashMap en + "\u001B[0m"); entryOwners.put(entry.toString(), zipFile); } - error("aswdasdsa"); } else { From 9426f51f149ba535863cb101c9777e94c605ebfc Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Fri, 19 May 2023 10:53:29 +0000 Subject: [PATCH 033/580] Update core files --- .../advancedbackups/cli/AdvancedBackupsCLI.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java index f9720427..a0bc2b23 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java @@ -760,7 +760,7 @@ private static T getFileToRestore(HashMap files, String directory name2 = name2.replace(worldFile.getName() + "/", ""); } if (name2.contains("/")) { - name2 = "\u001B[33m directory\u001B[0m " + name2.split("/")[0]; + name2 = "\u001B[33mdirectory\u001B[0m " + name2.split("/")[0]; } if (!toDisplay.contains(name2)) { toDisplay.add(name2); @@ -804,11 +804,11 @@ private static T getFileToRestore(HashMap files, String directory else if (userInput > toDisplay.size()) { return null; } - else if (!toDisplay.get(userInput - 1).contains("\u001B[33m directory\u001B[0m ")) { + else if (!toDisplay.get(userInput - 1).contains("\u001B[33mdirectory\u001B[0m ")) { return files.get(keyMap.get(toDisplay.get(userInput -1))); } - T result = getFileToRestore(files, directory + toDisplay.get(userInput -1).replace("\u001B[33m directory\u001B[0m ", "") + "/"); + T result = getFileToRestore(files, directory + toDisplay.get(userInput -1).replace("\u001B[33mdirectory\u001B[0m ", "") + "/"); if (result != null) { return result; } @@ -822,12 +822,12 @@ private static ArrayList sortStringsAlphabeticallyWithDirectoryPriority( ArrayList out = new ArrayList<>(); Collections.sort(in); for (String string : in) { - if (string.contains("\u001B[33m directory\u001B[0m")) { + if (string.contains("\u001B[33mdirectory\u001B[0m")) { out.add(string); } } for (String string : in) { - if (!string.contains("\u001B[33m directory\u001B[0m")) { + if (!string.contains("\u001B[33mdirectory\u001B[0m")) { out.add(string); } } @@ -857,7 +857,6 @@ private static void addBackupNamesToLists(File file, HashMap en + "\u001B[0m"); entryOwners.put(entry.toString(), zipFile); } - error("aswdasdsa"); } else { From b9509ee1ef453f8e3f25cbf8a49674381d17b1e6 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Fri, 19 May 2023 10:53:30 +0000 Subject: [PATCH 034/580] Update core files --- .../advancedbackups/cli/AdvancedBackupsCLI.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java index f9720427..a0bc2b23 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java @@ -760,7 +760,7 @@ private static T getFileToRestore(HashMap files, String directory name2 = name2.replace(worldFile.getName() + "/", ""); } if (name2.contains("/")) { - name2 = "\u001B[33m directory\u001B[0m " + name2.split("/")[0]; + name2 = "\u001B[33mdirectory\u001B[0m " + name2.split("/")[0]; } if (!toDisplay.contains(name2)) { toDisplay.add(name2); @@ -804,11 +804,11 @@ private static T getFileToRestore(HashMap files, String directory else if (userInput > toDisplay.size()) { return null; } - else if (!toDisplay.get(userInput - 1).contains("\u001B[33m directory\u001B[0m ")) { + else if (!toDisplay.get(userInput - 1).contains("\u001B[33mdirectory\u001B[0m ")) { return files.get(keyMap.get(toDisplay.get(userInput -1))); } - T result = getFileToRestore(files, directory + toDisplay.get(userInput -1).replace("\u001B[33m directory\u001B[0m ", "") + "/"); + T result = getFileToRestore(files, directory + toDisplay.get(userInput -1).replace("\u001B[33mdirectory\u001B[0m ", "") + "/"); if (result != null) { return result; } @@ -822,12 +822,12 @@ private static ArrayList sortStringsAlphabeticallyWithDirectoryPriority( ArrayList out = new ArrayList<>(); Collections.sort(in); for (String string : in) { - if (string.contains("\u001B[33m directory\u001B[0m")) { + if (string.contains("\u001B[33mdirectory\u001B[0m")) { out.add(string); } } for (String string : in) { - if (!string.contains("\u001B[33m directory\u001B[0m")) { + if (!string.contains("\u001B[33mdirectory\u001B[0m")) { out.add(string); } } @@ -857,7 +857,6 @@ private static void addBackupNamesToLists(File file, HashMap en + "\u001B[0m"); entryOwners.put(entry.toString(), zipFile); } - error("aswdasdsa"); } else { From fafd819fff3601ed66ab36c6d0f2f715cd2a0a14 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Fri, 19 May 2023 10:53:31 +0000 Subject: [PATCH 035/580] Update core files --- .../advancedbackups/cli/AdvancedBackupsCLI.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java index f9720427..a0bc2b23 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java @@ -760,7 +760,7 @@ private static T getFileToRestore(HashMap files, String directory name2 = name2.replace(worldFile.getName() + "/", ""); } if (name2.contains("/")) { - name2 = "\u001B[33m directory\u001B[0m " + name2.split("/")[0]; + name2 = "\u001B[33mdirectory\u001B[0m " + name2.split("/")[0]; } if (!toDisplay.contains(name2)) { toDisplay.add(name2); @@ -804,11 +804,11 @@ private static T getFileToRestore(HashMap files, String directory else if (userInput > toDisplay.size()) { return null; } - else if (!toDisplay.get(userInput - 1).contains("\u001B[33m directory\u001B[0m ")) { + else if (!toDisplay.get(userInput - 1).contains("\u001B[33mdirectory\u001B[0m ")) { return files.get(keyMap.get(toDisplay.get(userInput -1))); } - T result = getFileToRestore(files, directory + toDisplay.get(userInput -1).replace("\u001B[33m directory\u001B[0m ", "") + "/"); + T result = getFileToRestore(files, directory + toDisplay.get(userInput -1).replace("\u001B[33mdirectory\u001B[0m ", "") + "/"); if (result != null) { return result; } @@ -822,12 +822,12 @@ private static ArrayList sortStringsAlphabeticallyWithDirectoryPriority( ArrayList out = new ArrayList<>(); Collections.sort(in); for (String string : in) { - if (string.contains("\u001B[33m directory\u001B[0m")) { + if (string.contains("\u001B[33mdirectory\u001B[0m")) { out.add(string); } } for (String string : in) { - if (!string.contains("\u001B[33m directory\u001B[0m")) { + if (!string.contains("\u001B[33mdirectory\u001B[0m")) { out.add(string); } } @@ -857,7 +857,6 @@ private static void addBackupNamesToLists(File file, HashMap en + "\u001B[0m"); entryOwners.put(entry.toString(), zipFile); } - error("aswdasdsa"); } else { From 69094e15a508cc0470f37d67fd5885cb014e0085 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Fri, 19 May 2023 11:59:46 +0100 Subject: [PATCH 036/580] Version bump. 0.3 time --- build.gradle | 119 ++++++++++++++++++++++++++++++++++++++++++++++ gradle.properties | 7 +++ 2 files changed, 126 insertions(+) create mode 100644 build.gradle create mode 100644 gradle.properties diff --git a/build.gradle b/build.gradle new file mode 100644 index 00000000..fb0a56d0 --- /dev/null +++ b/build.gradle @@ -0,0 +1,119 @@ +plugins { + id 'eclipse' + id 'maven-publish' + id 'net.minecraftforge.gradle' version '5.1.+' +} + + +version = '0.3' +group = 'co.uk.mommyheather.advancedbackups' // http://maven.apache.org/guides/mini/guide-naming-conventions.html +archivesBaseName = 'AdvancedBackups-' + modloaderName + "-" + minecraftVersion + +sourceCompatibility = targetCompatibility = compileJava.sourceCompatibility = compileJava.targetCompatibility = '1.8' // Need this here so eclipse task generates correctly. + +minecraft { + // The mappings can be changed at any time, and must be in the following format. + // snapshot_YYYYMMDD Snapshot are built nightly. + // stable_# Stables are built at the discretion of the MCP team. + // Use non-default mappings at your own risk. they may not always work. + // Simply re-run your setup task after changing the mappings to update your workspace. + //mappings channel: 'snapshot', version: '20171003-1.12' + mappings channel: 'snapshot', version: '20171003-1.12' + // makeObfSourceJar = false // an Srg named sources jar is made by default. uncomment this to disable. + + // accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg') + + // Default run configurations. + // These can be tweaked, removed, or duplicated as needed. + runs { + client { + workingDirectory project.file('run') + + // Recommended logging data for a userdev environment + property 'forge.logging.markers', 'SCAN,REGISTRIES,REGISTRYDUMP' + + // Recommended logging level for the console + property 'forge.logging.console.level', 'debug' + } + + server { + + // Recommended logging data for a userdev environment + property 'forge.logging.markers', 'SCAN,REGISTRIES,REGISTRYDUMP' + + // Recommended logging level for the console + property 'forge.logging.console.level', 'debug' + } + } +} + +configurations { + // configuration that holds jars to include in the jar + extraLibs +} + +dependencies { + // Specify the version of Minecraft to use, If this is any group other then 'net.minecraft' it is assumed + // that the dep is a ForgeGradle 'patcher' dependency. And it's patches will be applied. + // The userdev artifact is a special name and will get all sorts of transformations applied to it. + minecraft 'net.minecraftforge:forge:1.12.2-14.23.5.2855' + implementation files('dependencies/jansi-2.4.0.jar') + extraLibs files('dependencies/jansi-2.4.0.jar') + + // You may put jars on which you depend on in ./libs or you may define them like so.. + // compile "some.group:artifact:version:classifier" + // compile "some.group:artifact:version" + + // Real examples + // compile 'com.mod-buildcraft:buildcraft:6.0.8:dev' // adds buildcraft to the dev env + // compile 'com.googlecode.efficient-java-matrix-library:ejml:0.24' // adds ejml to the dev env + + // The 'provided' configuration is for optional dependencies that exist at compile-time but might not at runtime. + // provided 'com.mod-buildcraft:buildcraft:6.0.8:dev' + + // These dependencies get remapped to your current MCP mappings + // deobf 'com.mod-buildcraft:buildcraft:6.0.8:dev' + + // For more info... + // http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html + // http://www.gradle.org/docs/current/userguide/dependency_management.html + +} + +// Example for how to get properties into the manifest for reading by the runtime.. +jar { + manifest { + attributes([ + "Main-Class" : "co.uk.mommyheather.advancedbackups.cli.AdvancedBackupsCLI", + "Specification-Title" : "advancedbackups", + "Specification-Vendor" : "raveninthedark", + "Specification-Version" : "1", // We are version 1 of ourselves + "Implementation-Title" : project.name, + "Implementation-Version": "${version}", + "Implementation-Vendor" :"raveninthedark", + "Implementation-Vendor" : "raveninthedark", + "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ") + ]) + } + from { + configurations.extraLibs.collect { it.isDirectory() ? it : zipTree(it) } + } +} +// Example configuration to allow publishing using the maven-publish task +// This is the preferred method to reobfuscate your jar file +jar.finalizedBy('reobfJar') +// However if you are in a multi-project build, dev time needs unobfed jar files, so you can delay the obfuscation until publishing by doing +//publish.dependsOn('reobfJar') + +publishing { + publications { + mavenJava(MavenPublication) { + artifact jar + } + } + repositories { + maven { + url "file:///${project.projectDir}/mcmodsrepo" + } + } +} diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 00000000..1587f7a0 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,7 @@ +# Sets default memory used for gradle commands. Can be overridden by user or command line properties. +# This is required to provide enough memory for the Minecraft decompilation process. +org.gradle.jvmargs=-Xmx3G +org.gradle.daemon=false + +modloaderName =forge +minecraftVersion =1.12 \ No newline at end of file From 90610a4388a2b8bd676774259c4f144d8817c336 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Fri, 19 May 2023 12:01:28 +0100 Subject: [PATCH 037/580] Version bump for 0.3 release --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 4d1a8051..0ea30f82 100644 --- a/build.gradle +++ b/build.gradle @@ -12,7 +12,7 @@ apply plugin: 'net.minecraftforge.gradle' apply plugin: 'eclipse' apply plugin: 'maven-publish' -version = '0.2' +version = '0.3' group = 'com.github.raveninthedark.advancedbackups' // http://maven.apache.org/guides/mini/guide-naming-conventions.html archivesBaseName = 'AdvancedBackups-' + modloaderName + "-" + minecraftVersion @@ -156,7 +156,7 @@ jar { "Specification-Version" : "1", // We are version 1 of ourselves "Implementation-Title" : project.name, "Implementation-Version": "${version}", - "Implementation-Vendor" :"examplemodsareus", + "Implementation-Vendor" :"raveninthedark", "Implementation-Vendor" : "raveninthedark", "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ") ]) From 1051d02502159d4299753f2a46fd1ee80b527170 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Fri, 19 May 2023 12:18:56 +0100 Subject: [PATCH 038/580] Version bump to 0.3 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index bc7acb09..b83fab1f 100644 --- a/build.gradle +++ b/build.gradle @@ -16,7 +16,7 @@ plugins { apply plugin: 'net.minecraftforge.gradle' -version = '0.2' +version = '0.3' group = 'co.uk.mommyheather.advancedbackups' // http://maven.apache.org/guides/mini/guide-naming-conventions.html archivesBaseName = 'AdvancedBackups-' + modloaderName + "-" + minecraftVersion From 08ce366bd27e33dd535f9196ea943b173580e2f1 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Fri, 19 May 2023 12:21:34 +0100 Subject: [PATCH 039/580] Version bump to 0.3 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 17272aec..f5d7702d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,7 @@ yarn_mappings=1.18.2+build.4 loader_version=0.14.19 # Mod Properties -mod_version=0.2 +mod_version=0.3 maven_group=co.uk.mommyheather.advancedbackups archives_base_name=advanced-backups modloaderName =fabric From 4a027220c3bd3221fba54e2761a4c8c1526d4ecd Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Fri, 19 May 2023 17:48:09 +0100 Subject: [PATCH 040/580] Fix a mod rejection when clients without the mod try to connect to a server that has it. --- build.gradle | 2 +- .../co/uk/mommyheather/advancedbackups/AdvancedBackups.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index fb0a56d0..15563c95 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ plugins { } -version = '0.3' +version = '0.3.1' group = 'co.uk.mommyheather.advancedbackups' // http://maven.apache.org/guides/mini/guide-naming-conventions.html archivesBaseName = 'AdvancedBackups-' + modloaderName + "-" + minecraftVersion diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 3a834bf8..941b36d0 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -22,7 +22,7 @@ import java.util.function.Consumer; -@Mod(modid = AdvancedBackups.MODID, name = AdvancedBackups.NAME, version = AdvancedBackups.VERSION) +@Mod(modid = AdvancedBackups.MODID, name = AdvancedBackups.NAME, version = AdvancedBackups.VERSION, acceptableRemoteVersions = "*") public class AdvancedBackups { public static final String MODID = "advancedbackups"; From 34c4bd5d1b0085fa3b9b9a42bc4b95c836037130 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Wed, 24 May 2023 11:26:55 +0100 Subject: [PATCH 041/580] Initial 1.7.10 commit. Time to start fixing shit! --- build.gradle.kts | 203 ++++++++++++++++++ settings.gradle.kts | 24 +++ .../java/rfg/examplemod/RfgExampleMod.java | 20 ++ src/main/resources/mcmod.info | 13 ++ 4 files changed, 260 insertions(+) create mode 100644 build.gradle.kts create mode 100644 settings.gradle.kts create mode 100644 src/main/java/rfg/examplemod/RfgExampleMod.java create mode 100644 src/main/resources/mcmod.info diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 00000000..5b384775 --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,203 @@ +import org.jetbrains.gradle.ext.Application +import org.jetbrains.gradle.ext.Gradle +import org.jetbrains.gradle.ext.RunConfigurationContainer + +plugins { + id("java-library") + id("maven-publish") + id("org.jetbrains.gradle.plugin.idea-ext") version "1.1.7" + id("eclipse") + id("com.gtnewhorizons.retrofuturagradle") version "1.2.5" +} + +// Project properties +group = "rfg.examplemod" +version = "1.0.0" + +// Set the toolchain version to decouple the Java we run Gradle with from the Java used to compile and run the mod +java { + toolchain { + languageVersion.set(JavaLanguageVersion.of(8)) + // Azul covers the most platforms for Java 8 toolchains, crucially including MacOS arm64 + vendor.set(org.gradle.jvm.toolchain.JvmVendorSpec.AZUL) + } + // Generate sources and javadocs jars when building and publishing + withSourcesJar() + withJavadocJar() +} + +// Most RFG configuration lives here, see the JavaDoc for com.gtnewhorizons.retrofuturagradle.MinecraftExtension +minecraft { + mcVersion.set("1.7.10") + + // Username for client run configurations + username.set("Developer") + + // Generate a field named VERSION with the mod version in the injected Tags class + injectedTags.put("VERSION", project.version) + + // If you need the old replaceIn mechanism, prefer the injectTags task because it doesn't inject a javac plugin. + // tagReplacementFiles.add("RfgExampleMod.java") + + // Enable assertions in the mod's package when running the client or server + extraRunJvmArguments.add("-ea:${project.group}") + + // If needed, add extra tweaker classes like for mixins. + // extraTweakClasses.add("org.spongepowered.asm.launch.MixinTweaker") + + // Exclude some Maven dependency groups from being automatically included in the reobfuscated runs + groupsToExcludeFromAutoReobfMapping.addAll("com.diffplug", "com.diffplug.durian", "net.industrial-craft") +} + +// Generates a class named rfg.examplemod.Tags with the mod version in it, you can find it at +tasks.injectTags.configure { + outputClassName.set("${project.group}.Tags") +} + +// Put the version from gradle into mcmod.info +tasks.processResources.configure { + inputs.property("version", project.version) + + filesMatching("mcmod.info") { + expand(mapOf("modVersion" to project.version)) + } +} + +// Create a new dependency type for runtime-only dependencies that don't get included in the maven publication +val runtimeOnlyNonPublishable: Configuration by configurations.creating { + description = "Runtime only dependencies that are not published alongside the jar" + isCanBeConsumed = false + isCanBeResolved = false +} +listOf(configurations.runtimeClasspath, configurations.testRuntimeClasspath).forEach { + it.configure { + extendsFrom( + runtimeOnlyNonPublishable + ) + } +} + +// Add an access tranformer +// tasks.deobfuscateMergedJarToSrg.configure {accessTransformerFiles.from("src/main/resources/META-INF/mymod_at.cfg")} + +// Dependencies +repositories { + maven { + name = "OvermindDL1 Maven" + url = uri("https://gregtech.overminddl1.com/") + mavenContent { + excludeGroup("net.minecraftforge") // missing the `universal` artefact + } + } + maven { + name = "GTNH Maven" + url = uri("http://jenkins.usrv.eu:8081/nexus/content/groups/public/") + isAllowInsecureProtocol = true + } +} + +dependencies { + // Adds NotEnoughItems and its dependencies (CCL&CCC) to runClient/runServer + runtimeOnlyNonPublishable("com.github.GTNewHorizons:NotEnoughItems:2.3.39-GTNH:dev") + // Example: grab the ic2 jar from curse maven and deobfuscate + // api(rfg.deobf("curse.maven:ic2-242638:2353971")) + // Example: grab the ic2 jar from libs/ in the workspace and deobfuscate + // api(rfg.deobf(project.files("libs/ic2.jar"))) +} + +// Publishing to a Maven repository +publishing { + publications { + create("maven") { + from(components["java"]) + } + } + repositories { + // Example: publishing to the GTNH Maven repository + maven { + url = uri("http://jenkins.usrv.eu:8081/nexus/content/repositories/releases") + isAllowInsecureProtocol = true + credentials { + username = System.getenv("MAVEN_USER") ?: "NONE" + password = System.getenv("MAVEN_PASSWORD") ?: "NONE" + } + } + } +} + +// IDE Settings +eclipse { + classpath { + isDownloadSources = true + isDownloadJavadoc = true + } +} + +idea { + module { + isDownloadJavadoc = true + isDownloadSources = true + inheritOutputDirs = true // Fix resources in IJ-Native runs + } + project { + this.withGroovyBuilder { + "settings" { + "runConfigurations" { + val self = this.delegate as RunConfigurationContainer + self.add(Gradle("1. Run Client").apply { + setProperty("taskNames", listOf("runClient")) + }) + self.add(Gradle("2. Run Server").apply { + setProperty("taskNames", listOf("runServer")) + }) + self.add(Gradle("3. Run Obfuscated Client").apply { + setProperty("taskNames", listOf("runObfClient")) + }) + self.add(Gradle("4. Run Obfuscated Server").apply { + setProperty("taskNames", listOf("runObfServer")) + }) + /* + These require extra configuration in IntelliJ, so are not enabled by default + self.add(Application("Run Client (IJ Native, Deprecated)", project).apply { + mainClass = "GradleStart" + moduleName = project.name + ".ideVirtualMain" + afterEvaluate { + val runClient = tasks.runClient.get() + workingDirectory = runClient.workingDir.absolutePath + programParameters = runClient.calculateArgs(project).map { '"' + it + '"' }.joinToString(" ") + jvmArgs = runClient.calculateJvmArgs(project).map { '"' + it + '"' }.joinToString(" ") + + ' ' + runClient.systemProperties.map { "\"-D" + it.key + '=' + it.value.toString() + '"' } + .joinToString(" ") + } + }) + self.add(Application("Run Server (IJ Native, Deprecated)", project).apply { + mainClass = "GradleStartServer" + moduleName = project.name + ".ideVirtualMain" + afterEvaluate { + val runServer = tasks.runServer.get() + workingDirectory = runServer.workingDir.absolutePath + programParameters = runServer.calculateArgs(project).map { '"' + it + '"' }.joinToString(" ") + jvmArgs = runServer.calculateJvmArgs(project).map { '"' + it + '"' }.joinToString(" ") + + ' ' + runServer.systemProperties.map { "\"-D" + it.key + '=' + it.value.toString() + '"' } + .joinToString(" ") + } + }) + */ + } + "compiler" { + val self = this.delegate as org.jetbrains.gradle.ext.IdeaCompilerConfiguration + afterEvaluate { + self.javac.moduleJavacAdditionalOptions = mapOf( + (project.name + ".main") to + tasks.compileJava.get().options.compilerArgs.map { '"' + it + '"' }.joinToString(" ") + ) + } + } + } + } + } +} + +tasks.processIdeaSettings.configure { + dependsOn(tasks.injectTags) +} diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 00000000..f26f07d3 --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1,24 @@ +rootProject.name = "RFGExampleMod" + +pluginManagement { + repositories { + maven { + // RetroFuturaGradle + name = "GTNH Maven" + url = uri("http://jenkins.usrv.eu:8081/nexus/content/groups/public/") + isAllowInsecureProtocol = true + mavenContent { + includeGroup("com.gtnewhorizons") + includeGroup("com.gtnewhorizons.retrofuturagradle") + } + } + gradlePluginPortal() + mavenCentral() + mavenLocal() + } +} + +plugins { + // Automatic toolchain provisioning + id("org.gradle.toolchains.foojay-resolver-convention") version "0.4.0" +} diff --git a/src/main/java/rfg/examplemod/RfgExampleMod.java b/src/main/java/rfg/examplemod/RfgExampleMod.java new file mode 100644 index 00000000..54faf8d9 --- /dev/null +++ b/src/main/java/rfg/examplemod/RfgExampleMod.java @@ -0,0 +1,20 @@ +package rfg.examplemod; + +import cpw.mods.fml.common.Mod; +import cpw.mods.fml.common.event.FMLInitializationEvent; +import net.minecraft.item.crafting.CraftingManager; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +@Mod(modid = "RFGExampleMod", name = "RFG Example mod", version = Tags.VERSION) +public class RfgExampleMod { + + public static final Logger LOGGER = LogManager.getLogger("RFGExampleMod"); + + @Mod.EventHandler + @SuppressWarnings("unused") + public void init(FMLInitializationEvent ev) { + LOGGER.info("Hello, RFG example mod!"); + LOGGER.info("Recipe count now: {}", CraftingManager.getInstance().getRecipeList().size()); + } +} diff --git a/src/main/resources/mcmod.info b/src/main/resources/mcmod.info new file mode 100644 index 00000000..fd1ac583 --- /dev/null +++ b/src/main/resources/mcmod.info @@ -0,0 +1,13 @@ +[ + { + "modid": "RFGExampleMod", + "name": "RFG Example mod", + "version": "${modVersion}", + "mcversion": "1.7.10", + "description": "An example mod for Minecraft 1.7.10 with Forge built using RetroFuturaGradle.", + "url": "https://github.com/GTNewHorizons/RetroFuturaGradle/", + "credits": "", + "authorList": ["eigenraven"], + "dependencies": [] + } +] From f7a72e883c31acaa76d621fa3efc542b29aab71b Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Wed, 24 May 2023 15:04:24 +0100 Subject: [PATCH 042/580] It compiles. finally. fuck kotlin. now to make it *work*. --- build.gradle.kts | 50 ++++++++--- settings.gradle.kts | 2 +- .../advancedbackups/AdvancedBackups.java | 84 +++++++++++++++++++ .../PlatformMethodWrapper.java | 49 +++++++++++ .../java/rfg/examplemod/RfgExampleMod.java | 20 ----- 5 files changed, 173 insertions(+), 32 deletions(-) create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/PlatformMethodWrapper.java delete mode 100644 src/main/java/rfg/examplemod/RfgExampleMod.java diff --git a/build.gradle.kts b/build.gradle.kts index 5b384775..b4dcd6b2 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,6 +1,6 @@ -import org.jetbrains.gradle.ext.Application +/*import org.jetbrains.gradle.ext.Application import org.jetbrains.gradle.ext.Gradle -import org.jetbrains.gradle.ext.RunConfigurationContainer +import org.jetbrains.gradle.ext.RunConfigurationContainer*/ plugins { id("java-library") @@ -10,9 +10,13 @@ plugins { id("com.gtnewhorizons.retrofuturagradle") version "1.2.5" } -// Project properties -group = "rfg.examplemod" -version = "1.0.0" + + + +version = "0.3" +group = "co.uk.mommyheather.advancedbackups" // http://maven.apache.org/guides/mini/guide-naming-conventions.html +//archivesBaseName = "AdvancedBackups-forge-1.7.10" + // Set the toolchain version to decouple the Java we run Gradle with from the Java used to compile and run the mod java { @@ -22,8 +26,8 @@ java { vendor.set(org.gradle.jvm.toolchain.JvmVendorSpec.AZUL) } // Generate sources and javadocs jars when building and publishing - withSourcesJar() - withJavadocJar() + //withSourcesJar() + //withJavadocJar() } // Most RFG configuration lives here, see the JavaDoc for com.gtnewhorizons.retrofuturagradle.MinecraftExtension @@ -96,9 +100,17 @@ repositories { } } + +val extraLibs by configurations.creating +//stick the dependency in the jar + + dependencies { // Adds NotEnoughItems and its dependencies (CCL&CCC) to runClient/runServer runtimeOnlyNonPublishable("com.github.GTNewHorizons:NotEnoughItems:2.3.39-GTNH:dev") + + implementation (files("/dependencies/jansi-2.4.0.jar")) + extraLibs (files("/dependencies/jansi-2.4.0.jar")) // Example: grab the ic2 jar from curse maven and deobfuscate // api(rfg.deobf("curse.maven:ic2-242638:2353971")) // Example: grab the ic2 jar from libs/ in the workspace and deobfuscate @@ -125,6 +137,22 @@ publishing { } } +tasks.withType { + from(zipTree("dependencies/jansi-2.4.0.jar")) + into("/") + duplicatesStrategy = DuplicatesStrategy.EXCLUDE + from(zipTree("dependencies/jna-platform-5.13.0.jar")) + into("/") + duplicatesStrategy = DuplicatesStrategy.EXCLUDE + manifest { + attributes["Main-Class"] = "co.uk.mommyheather.advancedbackups.cli.AdvancedBackupsCLI" + } +} + + + + + // IDE Settings eclipse { classpath { @@ -133,7 +161,7 @@ eclipse { } } -idea { +/*idea { module { isDownloadJavadoc = true isDownloadSources = true @@ -155,7 +183,7 @@ idea { }) self.add(Gradle("4. Run Obfuscated Server").apply { setProperty("taskNames", listOf("runObfServer")) - }) + })*/ /* These require extra configuration in IntelliJ, so are not enabled by default self.add(Application("Run Client (IJ Native, Deprecated)", project).apply { @@ -182,7 +210,7 @@ idea { .joinToString(" ") } }) - */ + *//* } "compiler" { val self = this.delegate as org.jetbrains.gradle.ext.IdeaCompilerConfiguration @@ -196,7 +224,7 @@ idea { } } } -} +}*/ tasks.processIdeaSettings.configure { dependsOn(tasks.injectTags) diff --git a/settings.gradle.kts b/settings.gradle.kts index f26f07d3..6456ce87 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,4 +1,4 @@ -rootProject.name = "RFGExampleMod" +rootProject.name = "AdvancedBackups-forge-1.7.10" pluginManagement { repositories { diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java new file mode 100644 index 00000000..093b8625 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -0,0 +1,84 @@ +package co.uk.mommyheather.advancedbackups; + +import cpw.mods.fml.common.Mod; +import cpw.mods.fml.common.Mod.EventHandler; +import cpw.mods.fml.common.event.FMLInitializationEvent; +import cpw.mods.fml.common.event.FMLServerStartedEvent; +import cpw.mods.fml.common.event.FMLServerStartingEvent; +import cpw.mods.fml.common.event.FMLServerStoppingEvent; +import cpw.mods.fml.relauncher.Side; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import net.minecraft.server.MinecraftServer; + + +import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; +import co.uk.mommyheather.advancedbackups.core.config.AVConfig; +import net.minecraftforge.common.MinecraftForge; + +import java.io.File; +import java.util.function.Consumer; + + +@Mod(modid = AdvancedBackups.MODID, name = AdvancedBackups.NAME, version = AdvancedBackups.VERSION, acceptableRemoteVersions = "*") +public class AdvancedBackups +{ + public static final String MODID = "advancedbackups"; + public static final String NAME = "Advanced Backups"; + public static final String VERSION = "0.3"; + + private static Logger LOGGER = LogManager.getLogger("AdvancedBackups"); + public static Consumer infoLogger; + public static Consumer warningLogger; + public static Consumer errorLogger; + + public static MinecraftServer server; + + + @Mod.EventHandler + @SuppressWarnings("unused") + public void init(FMLInitializationEvent ev) { + infoLogger = LOGGER::info; + warningLogger = LOGGER::warn; + errorLogger = LOGGER::error; + } + + + + public AdvancedBackups() + { + // Register ourselves for server and other game events we are interested in + MinecraftForge.EVENT_BUS.register(this); + } + + @EventHandler + public void onServerStarting(FMLServerStartingEvent event) + { + // Do something when the server starts + AVConfig.loadOrCreateConfig(); + LOGGER.info("Config loaded!!"); + PlatformMethodWrapper.worldName = event.getServer().worldServers[0].getWorldInfo().getWorldName(); + if (event.getSide() == Side.SERVER) { + PlatformMethodWrapper.worldDir = new File(event.getServer().getFolderName()).toPath(); + } + else { + PlatformMethodWrapper.worldDir = new File("saves/" + event.getServer().getFolderName()).toPath(); + } + + server = event.getServer(); + + } + + @EventHandler + public void onServerStarted(FMLServerStartedEvent event) { + BackupWrapper.checkStartupBackups(); + } + + @EventHandler + public void onServerStopping(FMLServerStoppingEvent event) { + BackupWrapper.checkShutdownBackups(); + } + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/PlatformMethodWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/PlatformMethodWrapper.java new file mode 100644 index 00000000..a206b65b --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/PlatformMethodWrapper.java @@ -0,0 +1,49 @@ +package co.uk.mommyheather.advancedbackups; + +import java.nio.file.Path; +import java.util.function.Consumer; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.world.World; +import net.minecraft.world.WorldServer; + +public class PlatformMethodWrapper { + + public static String worldName = ""; + public static Path worldDir = null; + public static Boolean activity = false; + public static final Consumer infoLogger = AdvancedBackups.infoLogger; + public static final Consumer warningLogger = AdvancedBackups.warningLogger; + public static final Consumer errorLogger = AdvancedBackups.errorLogger; + + public static final String savesDisabledMessage = "\n\n\n***************************************\nSAVING DISABLED - PREPARING FOR BACKUP!\n***************************************"; + public static final String savesEnabledMessage = "\n\n\n*********************************\nSAVING ENABLED - BACKUP COMPLETE!\n*********************************"; + public static final String saveCompleteMessage = "\n\n\n*************************************\nSAVE COMPLETE - PREPARING FOR BACKUP!\n*************************************"; + + + public static void disableSaving() { + /*MinecraftServer server = AdvancedBackups.server; + for (WorldServer level : server.worldServers) { + if (level != null && !level.disableLevelSaving) { + level.disableLevelSaving = true; + } + } + warningLogger.accept(savesDisabledMessage);*/ + } + + public static void enableSaving() { + /*MinecraftServer server = AdvancedBackups.server; + for (WorldServer level : server.worlds) { + if (level != null && !level.disableLevelSaving) { + level.disableLevelSaving = false; + } + } + warningLogger.accept(savesEnabledMessage);*/ + } + + public static void saveOnce() { + /*MinecraftServer server = AdvancedBackups.server; + server.saveAllWorlds(false); + warningLogger.accept(saveCompleteMessage);*/ + } +} diff --git a/src/main/java/rfg/examplemod/RfgExampleMod.java b/src/main/java/rfg/examplemod/RfgExampleMod.java deleted file mode 100644 index 54faf8d9..00000000 --- a/src/main/java/rfg/examplemod/RfgExampleMod.java +++ /dev/null @@ -1,20 +0,0 @@ -package rfg.examplemod; - -import cpw.mods.fml.common.Mod; -import cpw.mods.fml.common.event.FMLInitializationEvent; -import net.minecraft.item.crafting.CraftingManager; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -@Mod(modid = "RFGExampleMod", name = "RFG Example mod", version = Tags.VERSION) -public class RfgExampleMod { - - public static final Logger LOGGER = LogManager.getLogger("RFGExampleMod"); - - @Mod.EventHandler - @SuppressWarnings("unused") - public void init(FMLInitializationEvent ev) { - LOGGER.info("Hello, RFG example mod!"); - LOGGER.info("Recipe count now: {}", CraftingManager.getInstance().getRecipeList().size()); - } -} From db76c714196e5ce70bbdea52d30eebbfb757c9d5 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Wed, 24 May 2023 14:11:47 +0000 Subject: [PATCH 043/580] Update core files --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 12243020..8e2acc42 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ Many Minecraft versions are supported - request more if the one you want isn't y - Forge 1.18 - Fabric 1.18 - Forge 1.16 +- Forge 1.12 ## Features: Choose between zip, differential or incremental backups. From 9147c199ab240114c1a16bec5c8be3444fccca35 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Wed, 24 May 2023 14:11:48 +0000 Subject: [PATCH 044/580] Update core files --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 12243020..8e2acc42 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ Many Minecraft versions are supported - request more if the one you want isn't y - Forge 1.18 - Fabric 1.18 - Forge 1.16 +- Forge 1.12 ## Features: Choose between zip, differential or incremental backups. From 498f3ec50f9d388ad38fa259459f9ad382ddddef Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Wed, 24 May 2023 14:11:49 +0000 Subject: [PATCH 045/580] Update core files --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 12243020..8e2acc42 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ Many Minecraft versions are supported - request more if the one you want isn't y - Forge 1.18 - Fabric 1.18 - Forge 1.16 +- Forge 1.12 ## Features: Choose between zip, differential or incremental backups. From b45d00df73e70d246a53365c9b5066f1faf80f27 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Wed, 24 May 2023 14:11:51 +0000 Subject: [PATCH 046/580] Update core files --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 12243020..8e2acc42 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ Many Minecraft versions are supported - request more if the one you want isn't y - Forge 1.18 - Fabric 1.18 - Forge 1.16 +- Forge 1.12 ## Features: Choose between zip, differential or incremental backups. From 5fdd6224462ab85ab94b66ef645e0baf5e443823 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Wed, 31 May 2023 18:33:39 +0100 Subject: [PATCH 047/580] Fuck kotlin. --- build.gradle.kts | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index b4dcd6b2..569c2b8e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,6 +1,3 @@ -/*import org.jetbrains.gradle.ext.Application -import org.jetbrains.gradle.ext.Gradle -import org.jetbrains.gradle.ext.RunConfigurationContainer*/ plugins { id("java-library") @@ -141,11 +138,12 @@ tasks.withType { from(zipTree("dependencies/jansi-2.4.0.jar")) into("/") duplicatesStrategy = DuplicatesStrategy.EXCLUDE - from(zipTree("dependencies/jna-platform-5.13.0.jar")) - into("/") - duplicatesStrategy = DuplicatesStrategy.EXCLUDE + //from(zipTree("dependencies/jna-platform-5.13.0.jar")) + //into("/") + //duplicatesStrategy = DuplicatesStrategy.EXCLUDE manifest { attributes["Main-Class"] = "co.uk.mommyheather.advancedbackups.cli.AdvancedBackupsCLI" + attributes["Implementation-Version"] = "${version}" } } From 9c1619cc2d42d1e5fa79c5a3399ac1dcc8b84947 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Wed, 31 May 2023 18:36:43 +0100 Subject: [PATCH 048/580] This brings it in line with the other versions. I'll build a jar then work on config. --- .../advancedbackups/AdvancedBackups.java | 3 ++- .../PlatformMethodWrapper.java | 23 ++++++++++--------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 093b8625..0b111806 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -43,6 +43,7 @@ public void init(FMLInitializationEvent ev) { infoLogger = LOGGER::info; warningLogger = LOGGER::warn; errorLogger = LOGGER::error; + AVConfig.loadOrCreateConfig(); //doing this in init is better } @@ -57,7 +58,7 @@ public AdvancedBackups() public void onServerStarting(FMLServerStartingEvent event) { // Do something when the server starts - AVConfig.loadOrCreateConfig(); + AVConfig.loadConfig(); //and a reload upon server start LOGGER.info("Config loaded!!"); PlatformMethodWrapper.worldName = event.getServer().worldServers[0].getWorldInfo().getWorldName(); if (event.getSide() == Side.SERVER) { diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/PlatformMethodWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/PlatformMethodWrapper.java index a206b65b..ba458320 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/PlatformMethodWrapper.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/PlatformMethodWrapper.java @@ -3,6 +3,7 @@ import java.nio.file.Path; import java.util.function.Consumer; +import net.minecraft.command.server.CommandSaveOff; import net.minecraft.server.MinecraftServer; import net.minecraft.world.World; import net.minecraft.world.WorldServer; @@ -15,35 +16,35 @@ public class PlatformMethodWrapper { public static final Consumer infoLogger = AdvancedBackups.infoLogger; public static final Consumer warningLogger = AdvancedBackups.warningLogger; public static final Consumer errorLogger = AdvancedBackups.errorLogger; - + public static final String savesDisabledMessage = "\n\n\n***************************************\nSAVING DISABLED - PREPARING FOR BACKUP!\n***************************************"; public static final String savesEnabledMessage = "\n\n\n*********************************\nSAVING ENABLED - BACKUP COMPLETE!\n*********************************"; public static final String saveCompleteMessage = "\n\n\n*************************************\nSAVE COMPLETE - PREPARING FOR BACKUP!\n*************************************"; public static void disableSaving() { - /*MinecraftServer server = AdvancedBackups.server; + MinecraftServer server = AdvancedBackups.server; for (WorldServer level : server.worldServers) { - if (level != null && !level.disableLevelSaving) { - level.disableLevelSaving = true; + if (level != null && !level.levelSaving) { + level.levelSaving = true; } } - warningLogger.accept(savesDisabledMessage);*/ + warningLogger.accept(savesDisabledMessage); } public static void enableSaving() { - /*MinecraftServer server = AdvancedBackups.server; + MinecraftServer server = AdvancedBackups.server; for (WorldServer level : server.worlds) { - if (level != null && !level.disableLevelSaving) { - level.disableLevelSaving = false; + if (level != null && !level.levelSaving) { + level.levelSaving = false; } } - warningLogger.accept(savesEnabledMessage);*/ + warningLogger.accept(savesEnabledMessage); } public static void saveOnce() { - /*MinecraftServer server = AdvancedBackups.server; + MinecraftServer server = AdvancedBackups.server; server.saveAllWorlds(false); - warningLogger.accept(saveCompleteMessage);*/ + warningLogger.accept(saveCompleteMessage); } } From af97f9e585cf6498ca0ce553ede3036fbc03dc8d Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Wed, 31 May 2023 17:49:20 +0000 Subject: [PATCH 049/580] Update core files --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 12243020..8e2acc42 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ Many Minecraft versions are supported - request more if the one you want isn't y - Forge 1.18 - Fabric 1.18 - Forge 1.16 +- Forge 1.12 ## Features: Choose between zip, differential or incremental backups. From 006ad37db8ad96d9e4be2aeadfb243472490af40 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Wed, 31 May 2023 19:24:37 +0100 Subject: [PATCH 050/580] Okay, NOW it should be up to date. --- .../advancedbackups/PlatformMethodWrapper.java | 18 ++++++++++++++---- src/main/resources/mcmod.info | 10 +++++----- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/PlatformMethodWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/PlatformMethodWrapper.java index ba458320..191bf443 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/PlatformMethodWrapper.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/PlatformMethodWrapper.java @@ -1,5 +1,7 @@ package co.uk.mommyheather.advancedbackups; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.nio.file.Path; import java.util.function.Consumer; @@ -34,7 +36,7 @@ public static void disableSaving() { public static void enableSaving() { MinecraftServer server = AdvancedBackups.server; - for (WorldServer level : server.worlds) { + for (WorldServer level : server.worldServers) { if (level != null && !level.levelSaving) { level.levelSaving = false; } @@ -43,8 +45,16 @@ public static void enableSaving() { } public static void saveOnce() { - MinecraftServer server = AdvancedBackups.server; - server.saveAllWorlds(false); - warningLogger.accept(saveCompleteMessage); + try { + MinecraftServer server = AdvancedBackups.server; + Class[] classes = {Boolean.class}; + Method saveMethod = MinecraftServer.class.getMethod("saveAllWorlds", classes); + saveMethod.invoke(server, false); + warningLogger.accept(saveCompleteMessage); + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException e) { + // TODO Scream at user + errorLogger.accept("FAILED TO SAVE WORLD!"); + e.printStackTrace(); + } } } diff --git a/src/main/resources/mcmod.info b/src/main/resources/mcmod.info index fd1ac583..20d03144 100644 --- a/src/main/resources/mcmod.info +++ b/src/main/resources/mcmod.info @@ -1,13 +1,13 @@ [ { - "modid": "RFGExampleMod", - "name": "RFG Example mod", + "modid": "advancedbackups", + "name": "Advanced Backups", "version": "${modVersion}", "mcversion": "1.7.10", - "description": "An example mod for Minecraft 1.7.10 with Forge built using RetroFuturaGradle.", - "url": "https://github.com/GTNewHorizons/RetroFuturaGradle/", + "description": "A highly advanced backup mod.", + "url": "https://github.com/MommyHeather/AdvancedBackups", "credits": "", - "authorList": ["eigenraven"], + "authorList": ["mommyheather"], "dependencies": [] } ] From a2b865323ee10ec5e98f0224fd9e0a584157cfe0 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Thu, 1 Jun 2023 15:07:27 +0000 Subject: [PATCH 051/580] Update core files --- README.md | 81 +++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 67 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 8e2acc42..d4321826 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ Many Minecraft versions are supported - request more if the one you want isn't y - Fabric 1.18 - Forge 1.16 - Forge 1.12 +- Forge 1.7.10 ## Features: Choose between zip, differential or incremental backups. @@ -35,17 +36,69 @@ Customisable compression level. \- Upon first boot, an `AdvancedBackups.properties` file will be created in your server or client root directory. \- Adjust this to suit your needs, then restart the server or use `/AdvancedBackups reload` to reload the config. A small description of each config entry is below. -| Config | Description | Default Value | -| ----------- | ----------- | ------------- | -| config.advancedbackups.enabled | Enable or disable backups entirely. | true | -| config.advancedbackups.activity | Enable or disable player activity requirements. | false | -| config.advancedbackups.type | Whether to use zip, differential or incremental backups. | zip | -| config.advancedbackups.path | The relative or absolute location where backups are stored. | ./backups | -| config.advancedbackups.size | The maximum backup size to keep, in GB. Oldest backups are deleted if this is exceeded. | 50 | -| config.advancedbackups.frequency.min | The minimum time between backups. Command backups bypass this. | 0.5 | -| config.advancedbackups.frequency.shutdown | Whether to make a backup on server shutdown. | false | -| config.advancedbackups.frequency.startup | Whether to make a backup on server startup. | false | -| config.advancedbackups.logging.silent | Whether to disable chat and console logging. Does not affect debug.log or error messages. | false | -| config.advancedbackups.zips.compression | The attempted compression level for all zip files. | 4 | -| config.advancedbackups.chains.length | The maximum chain length for incremental and differential backups. | 50 | -| config.advancedbackups.chains.compress | Whether to compress incremental and differential backups into zip files. | true | +| Config | Description | Default Value | Supported From | +| ----------- | ----------- | ------------- | -------------- | +| config.advancedbackups.enabled | Enable or disable backups entirely. | true | 0.3 | +| config.advancedbackups.activity | Enable or disable player activity requirements. | false | N/A | +| config.advancedbackups.save | Whether to save before making a backup. | false | 0.3 | +| config.advancedbackups.type | Whether to use zip, differential or incremental backups. | differential | 0.3 | +| config.advancedbackups.path | The relative or absolute location where backups are stored. | ./backups | 0.3 | +| config.advancedbackups.size | The maximum backup size to keep, in GB. Oldest backups are deleted if this is exceeded. | 50 | 0.3 | +| config.advancedbackups.frequency.min | The minimum time between backups. Command backups bypass this. | 0.5 | 0.3 | +| config.advancedbackups.frequency.max | If this time has passed since a backup was last made, one **will** be made. | 24 | 0.3 | +| config.advancedbackups.frequency.uptime| Whether the schedule is based on uptime. If not. it uses real-time instead. | true | 0.3 | +| config.advancedbackups.frequency.schedule | Uptime based : a looping uptime-based schedule. Real-time based : A strict schedule, following real-world time. | 12:00 | 0.3 | +| config.advancedbackups.frequency.shutdown | Whether to make a backup on server shutdown. | false | 0.0 | +| config.advancedbackups.frequency.startup | Whether to make a backup on server startup. | false | 0.3 | +| config.advancedbackups.frequency.delay | The delay in seconds before making a startup backup. Always at least 5 seconds. | 5 | 0.3 | +| config.advancedbackups.logging.silent | Whether to disable chat and console logging. Does not affect debug.log or error messages. | false | N/A | +| config.advancedbackups.zips.compression | The attempted compression level for all zip files. | 4 | 0.3 | +| config.advancedbackups.chains.length | The maximum chain length for incremental and differential backups. | 50 | 0.3 | +| config.advancedbackups.chains.compress | Whether to compress incremental and differential backups into zip files. | true | 0.3 | +| config.advancedbackups.chains.smart | For differential and incremental backups. Resets the chain length if every file is being backed up. | true | 0.3 | + +#### Commands: + +None currently implemented. + + +### Commandline: +TODO - export option for backups. + +\- Run the jar directly from the mods folder. `java -jar AdvancedBackups-modloader-mcversion-modversion` for example, replacing the filename with the correct one for your installation. + +\- It will read your config. Then, it will ask you which backup type to restore. + +\- Afterwards, it will ask you if you are on a client or server. If you run the forge/fabric server software, choose server, otherwise it's a client. + +\- Then it will ask for your world name. It will verify this, and will not proceed if it can't find the name. + +\- Then it will prompt you to choose a backup to restore. The most recent are listed last. With differential and incremental upgrades, the backups will be labelled as partial or fill. + +- This is only for your information, and will not affect the restoration process. + +\- The below image shows this for a differential backup. + + +![image](https://github.com/MommyHeather/AdvancedBackups/assets/66441550/ba73af5f-1bca-4ec7-9a3e-a21f6b7350ab) + +\- Next you choose whether you're restoring the entire backup, or a singular file. + +- This restores the **ENTIRE WORLD STATE** at the time of the backups. Partial backups will have the relevant previous backups also restored to make this happen. + + +Finally, you can accept the warning prompt it gives you. + +If you chose to restore the entire backup, the program will exit when it is complete. +If you chose to restore a singular file, you'll be presented with a rudimentary file browser. The below example is for differential backups: + +![image](https://github.com/MommyHeather/AdvancedBackups/assets/66441550/d5f771f5-32d4-435f-aa82-a1da52e3996c) + +Directories are marked, and `../` will traverse up a directory. + +If your selected backup type is differential or incremental, files will be marked with the date they're from. This is purely for your information, the file's state will match that of when the selected backup was made. + +Once you select a file, it will be restored. The program will then exit. + +![image](https://github.com/MommyHeather/AdvancedBackups/assets/66441550/7a2c5d4c-e8db-48c3-8353-46486b9f86b3) + From ab6465586f114af6c42a666e8965ba4f8d62895d Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Thu, 1 Jun 2023 15:07:30 +0000 Subject: [PATCH 052/580] Update core files --- README.md | 81 +++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 67 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 8e2acc42..d4321826 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ Many Minecraft versions are supported - request more if the one you want isn't y - Fabric 1.18 - Forge 1.16 - Forge 1.12 +- Forge 1.7.10 ## Features: Choose between zip, differential or incremental backups. @@ -35,17 +36,69 @@ Customisable compression level. \- Upon first boot, an `AdvancedBackups.properties` file will be created in your server or client root directory. \- Adjust this to suit your needs, then restart the server or use `/AdvancedBackups reload` to reload the config. A small description of each config entry is below. -| Config | Description | Default Value | -| ----------- | ----------- | ------------- | -| config.advancedbackups.enabled | Enable or disable backups entirely. | true | -| config.advancedbackups.activity | Enable or disable player activity requirements. | false | -| config.advancedbackups.type | Whether to use zip, differential or incremental backups. | zip | -| config.advancedbackups.path | The relative or absolute location where backups are stored. | ./backups | -| config.advancedbackups.size | The maximum backup size to keep, in GB. Oldest backups are deleted if this is exceeded. | 50 | -| config.advancedbackups.frequency.min | The minimum time between backups. Command backups bypass this. | 0.5 | -| config.advancedbackups.frequency.shutdown | Whether to make a backup on server shutdown. | false | -| config.advancedbackups.frequency.startup | Whether to make a backup on server startup. | false | -| config.advancedbackups.logging.silent | Whether to disable chat and console logging. Does not affect debug.log or error messages. | false | -| config.advancedbackups.zips.compression | The attempted compression level for all zip files. | 4 | -| config.advancedbackups.chains.length | The maximum chain length for incremental and differential backups. | 50 | -| config.advancedbackups.chains.compress | Whether to compress incremental and differential backups into zip files. | true | +| Config | Description | Default Value | Supported From | +| ----------- | ----------- | ------------- | -------------- | +| config.advancedbackups.enabled | Enable or disable backups entirely. | true | 0.3 | +| config.advancedbackups.activity | Enable or disable player activity requirements. | false | N/A | +| config.advancedbackups.save | Whether to save before making a backup. | false | 0.3 | +| config.advancedbackups.type | Whether to use zip, differential or incremental backups. | differential | 0.3 | +| config.advancedbackups.path | The relative or absolute location where backups are stored. | ./backups | 0.3 | +| config.advancedbackups.size | The maximum backup size to keep, in GB. Oldest backups are deleted if this is exceeded. | 50 | 0.3 | +| config.advancedbackups.frequency.min | The minimum time between backups. Command backups bypass this. | 0.5 | 0.3 | +| config.advancedbackups.frequency.max | If this time has passed since a backup was last made, one **will** be made. | 24 | 0.3 | +| config.advancedbackups.frequency.uptime| Whether the schedule is based on uptime. If not. it uses real-time instead. | true | 0.3 | +| config.advancedbackups.frequency.schedule | Uptime based : a looping uptime-based schedule. Real-time based : A strict schedule, following real-world time. | 12:00 | 0.3 | +| config.advancedbackups.frequency.shutdown | Whether to make a backup on server shutdown. | false | 0.0 | +| config.advancedbackups.frequency.startup | Whether to make a backup on server startup. | false | 0.3 | +| config.advancedbackups.frequency.delay | The delay in seconds before making a startup backup. Always at least 5 seconds. | 5 | 0.3 | +| config.advancedbackups.logging.silent | Whether to disable chat and console logging. Does not affect debug.log or error messages. | false | N/A | +| config.advancedbackups.zips.compression | The attempted compression level for all zip files. | 4 | 0.3 | +| config.advancedbackups.chains.length | The maximum chain length for incremental and differential backups. | 50 | 0.3 | +| config.advancedbackups.chains.compress | Whether to compress incremental and differential backups into zip files. | true | 0.3 | +| config.advancedbackups.chains.smart | For differential and incremental backups. Resets the chain length if every file is being backed up. | true | 0.3 | + +#### Commands: + +None currently implemented. + + +### Commandline: +TODO - export option for backups. + +\- Run the jar directly from the mods folder. `java -jar AdvancedBackups-modloader-mcversion-modversion` for example, replacing the filename with the correct one for your installation. + +\- It will read your config. Then, it will ask you which backup type to restore. + +\- Afterwards, it will ask you if you are on a client or server. If you run the forge/fabric server software, choose server, otherwise it's a client. + +\- Then it will ask for your world name. It will verify this, and will not proceed if it can't find the name. + +\- Then it will prompt you to choose a backup to restore. The most recent are listed last. With differential and incremental upgrades, the backups will be labelled as partial or fill. + +- This is only for your information, and will not affect the restoration process. + +\- The below image shows this for a differential backup. + + +![image](https://github.com/MommyHeather/AdvancedBackups/assets/66441550/ba73af5f-1bca-4ec7-9a3e-a21f6b7350ab) + +\- Next you choose whether you're restoring the entire backup, or a singular file. + +- This restores the **ENTIRE WORLD STATE** at the time of the backups. Partial backups will have the relevant previous backups also restored to make this happen. + + +Finally, you can accept the warning prompt it gives you. + +If you chose to restore the entire backup, the program will exit when it is complete. +If you chose to restore a singular file, you'll be presented with a rudimentary file browser. The below example is for differential backups: + +![image](https://github.com/MommyHeather/AdvancedBackups/assets/66441550/d5f771f5-32d4-435f-aa82-a1da52e3996c) + +Directories are marked, and `../` will traverse up a directory. + +If your selected backup type is differential or incremental, files will be marked with the date they're from. This is purely for your information, the file's state will match that of when the selected backup was made. + +Once you select a file, it will be restored. The program will then exit. + +![image](https://github.com/MommyHeather/AdvancedBackups/assets/66441550/7a2c5d4c-e8db-48c3-8353-46486b9f86b3) + From 9e74e618df03a2febf29808d3ea6d0a9543678dd Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Thu, 1 Jun 2023 15:07:33 +0000 Subject: [PATCH 053/580] Update core files --- README.md | 81 +++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 67 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 8e2acc42..d4321826 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ Many Minecraft versions are supported - request more if the one you want isn't y - Fabric 1.18 - Forge 1.16 - Forge 1.12 +- Forge 1.7.10 ## Features: Choose between zip, differential or incremental backups. @@ -35,17 +36,69 @@ Customisable compression level. \- Upon first boot, an `AdvancedBackups.properties` file will be created in your server or client root directory. \- Adjust this to suit your needs, then restart the server or use `/AdvancedBackups reload` to reload the config. A small description of each config entry is below. -| Config | Description | Default Value | -| ----------- | ----------- | ------------- | -| config.advancedbackups.enabled | Enable or disable backups entirely. | true | -| config.advancedbackups.activity | Enable or disable player activity requirements. | false | -| config.advancedbackups.type | Whether to use zip, differential or incremental backups. | zip | -| config.advancedbackups.path | The relative or absolute location where backups are stored. | ./backups | -| config.advancedbackups.size | The maximum backup size to keep, in GB. Oldest backups are deleted if this is exceeded. | 50 | -| config.advancedbackups.frequency.min | The minimum time between backups. Command backups bypass this. | 0.5 | -| config.advancedbackups.frequency.shutdown | Whether to make a backup on server shutdown. | false | -| config.advancedbackups.frequency.startup | Whether to make a backup on server startup. | false | -| config.advancedbackups.logging.silent | Whether to disable chat and console logging. Does not affect debug.log or error messages. | false | -| config.advancedbackups.zips.compression | The attempted compression level for all zip files. | 4 | -| config.advancedbackups.chains.length | The maximum chain length for incremental and differential backups. | 50 | -| config.advancedbackups.chains.compress | Whether to compress incremental and differential backups into zip files. | true | +| Config | Description | Default Value | Supported From | +| ----------- | ----------- | ------------- | -------------- | +| config.advancedbackups.enabled | Enable or disable backups entirely. | true | 0.3 | +| config.advancedbackups.activity | Enable or disable player activity requirements. | false | N/A | +| config.advancedbackups.save | Whether to save before making a backup. | false | 0.3 | +| config.advancedbackups.type | Whether to use zip, differential or incremental backups. | differential | 0.3 | +| config.advancedbackups.path | The relative or absolute location where backups are stored. | ./backups | 0.3 | +| config.advancedbackups.size | The maximum backup size to keep, in GB. Oldest backups are deleted if this is exceeded. | 50 | 0.3 | +| config.advancedbackups.frequency.min | The minimum time between backups. Command backups bypass this. | 0.5 | 0.3 | +| config.advancedbackups.frequency.max | If this time has passed since a backup was last made, one **will** be made. | 24 | 0.3 | +| config.advancedbackups.frequency.uptime| Whether the schedule is based on uptime. If not. it uses real-time instead. | true | 0.3 | +| config.advancedbackups.frequency.schedule | Uptime based : a looping uptime-based schedule. Real-time based : A strict schedule, following real-world time. | 12:00 | 0.3 | +| config.advancedbackups.frequency.shutdown | Whether to make a backup on server shutdown. | false | 0.0 | +| config.advancedbackups.frequency.startup | Whether to make a backup on server startup. | false | 0.3 | +| config.advancedbackups.frequency.delay | The delay in seconds before making a startup backup. Always at least 5 seconds. | 5 | 0.3 | +| config.advancedbackups.logging.silent | Whether to disable chat and console logging. Does not affect debug.log or error messages. | false | N/A | +| config.advancedbackups.zips.compression | The attempted compression level for all zip files. | 4 | 0.3 | +| config.advancedbackups.chains.length | The maximum chain length for incremental and differential backups. | 50 | 0.3 | +| config.advancedbackups.chains.compress | Whether to compress incremental and differential backups into zip files. | true | 0.3 | +| config.advancedbackups.chains.smart | For differential and incremental backups. Resets the chain length if every file is being backed up. | true | 0.3 | + +#### Commands: + +None currently implemented. + + +### Commandline: +TODO - export option for backups. + +\- Run the jar directly from the mods folder. `java -jar AdvancedBackups-modloader-mcversion-modversion` for example, replacing the filename with the correct one for your installation. + +\- It will read your config. Then, it will ask you which backup type to restore. + +\- Afterwards, it will ask you if you are on a client or server. If you run the forge/fabric server software, choose server, otherwise it's a client. + +\- Then it will ask for your world name. It will verify this, and will not proceed if it can't find the name. + +\- Then it will prompt you to choose a backup to restore. The most recent are listed last. With differential and incremental upgrades, the backups will be labelled as partial or fill. + +- This is only for your information, and will not affect the restoration process. + +\- The below image shows this for a differential backup. + + +![image](https://github.com/MommyHeather/AdvancedBackups/assets/66441550/ba73af5f-1bca-4ec7-9a3e-a21f6b7350ab) + +\- Next you choose whether you're restoring the entire backup, or a singular file. + +- This restores the **ENTIRE WORLD STATE** at the time of the backups. Partial backups will have the relevant previous backups also restored to make this happen. + + +Finally, you can accept the warning prompt it gives you. + +If you chose to restore the entire backup, the program will exit when it is complete. +If you chose to restore a singular file, you'll be presented with a rudimentary file browser. The below example is for differential backups: + +![image](https://github.com/MommyHeather/AdvancedBackups/assets/66441550/d5f771f5-32d4-435f-aa82-a1da52e3996c) + +Directories are marked, and `../` will traverse up a directory. + +If your selected backup type is differential or incremental, files will be marked with the date they're from. This is purely for your information, the file's state will match that of when the selected backup was made. + +Once you select a file, it will be restored. The program will then exit. + +![image](https://github.com/MommyHeather/AdvancedBackups/assets/66441550/7a2c5d4c-e8db-48c3-8353-46486b9f86b3) + From 4ae1cabd175e737ef1616bcc4d973eab0b5e9ef9 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Thu, 1 Jun 2023 15:07:34 +0000 Subject: [PATCH 054/580] Update core files --- README.md | 81 +++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 67 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 8e2acc42..d4321826 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ Many Minecraft versions are supported - request more if the one you want isn't y - Fabric 1.18 - Forge 1.16 - Forge 1.12 +- Forge 1.7.10 ## Features: Choose between zip, differential or incremental backups. @@ -35,17 +36,69 @@ Customisable compression level. \- Upon first boot, an `AdvancedBackups.properties` file will be created in your server or client root directory. \- Adjust this to suit your needs, then restart the server or use `/AdvancedBackups reload` to reload the config. A small description of each config entry is below. -| Config | Description | Default Value | -| ----------- | ----------- | ------------- | -| config.advancedbackups.enabled | Enable or disable backups entirely. | true | -| config.advancedbackups.activity | Enable or disable player activity requirements. | false | -| config.advancedbackups.type | Whether to use zip, differential or incremental backups. | zip | -| config.advancedbackups.path | The relative or absolute location where backups are stored. | ./backups | -| config.advancedbackups.size | The maximum backup size to keep, in GB. Oldest backups are deleted if this is exceeded. | 50 | -| config.advancedbackups.frequency.min | The minimum time between backups. Command backups bypass this. | 0.5 | -| config.advancedbackups.frequency.shutdown | Whether to make a backup on server shutdown. | false | -| config.advancedbackups.frequency.startup | Whether to make a backup on server startup. | false | -| config.advancedbackups.logging.silent | Whether to disable chat and console logging. Does not affect debug.log or error messages. | false | -| config.advancedbackups.zips.compression | The attempted compression level for all zip files. | 4 | -| config.advancedbackups.chains.length | The maximum chain length for incremental and differential backups. | 50 | -| config.advancedbackups.chains.compress | Whether to compress incremental and differential backups into zip files. | true | +| Config | Description | Default Value | Supported From | +| ----------- | ----------- | ------------- | -------------- | +| config.advancedbackups.enabled | Enable or disable backups entirely. | true | 0.3 | +| config.advancedbackups.activity | Enable or disable player activity requirements. | false | N/A | +| config.advancedbackups.save | Whether to save before making a backup. | false | 0.3 | +| config.advancedbackups.type | Whether to use zip, differential or incremental backups. | differential | 0.3 | +| config.advancedbackups.path | The relative or absolute location where backups are stored. | ./backups | 0.3 | +| config.advancedbackups.size | The maximum backup size to keep, in GB. Oldest backups are deleted if this is exceeded. | 50 | 0.3 | +| config.advancedbackups.frequency.min | The minimum time between backups. Command backups bypass this. | 0.5 | 0.3 | +| config.advancedbackups.frequency.max | If this time has passed since a backup was last made, one **will** be made. | 24 | 0.3 | +| config.advancedbackups.frequency.uptime| Whether the schedule is based on uptime. If not. it uses real-time instead. | true | 0.3 | +| config.advancedbackups.frequency.schedule | Uptime based : a looping uptime-based schedule. Real-time based : A strict schedule, following real-world time. | 12:00 | 0.3 | +| config.advancedbackups.frequency.shutdown | Whether to make a backup on server shutdown. | false | 0.0 | +| config.advancedbackups.frequency.startup | Whether to make a backup on server startup. | false | 0.3 | +| config.advancedbackups.frequency.delay | The delay in seconds before making a startup backup. Always at least 5 seconds. | 5 | 0.3 | +| config.advancedbackups.logging.silent | Whether to disable chat and console logging. Does not affect debug.log or error messages. | false | N/A | +| config.advancedbackups.zips.compression | The attempted compression level for all zip files. | 4 | 0.3 | +| config.advancedbackups.chains.length | The maximum chain length for incremental and differential backups. | 50 | 0.3 | +| config.advancedbackups.chains.compress | Whether to compress incremental and differential backups into zip files. | true | 0.3 | +| config.advancedbackups.chains.smart | For differential and incremental backups. Resets the chain length if every file is being backed up. | true | 0.3 | + +#### Commands: + +None currently implemented. + + +### Commandline: +TODO - export option for backups. + +\- Run the jar directly from the mods folder. `java -jar AdvancedBackups-modloader-mcversion-modversion` for example, replacing the filename with the correct one for your installation. + +\- It will read your config. Then, it will ask you which backup type to restore. + +\- Afterwards, it will ask you if you are on a client or server. If you run the forge/fabric server software, choose server, otherwise it's a client. + +\- Then it will ask for your world name. It will verify this, and will not proceed if it can't find the name. + +\- Then it will prompt you to choose a backup to restore. The most recent are listed last. With differential and incremental upgrades, the backups will be labelled as partial or fill. + +- This is only for your information, and will not affect the restoration process. + +\- The below image shows this for a differential backup. + + +![image](https://github.com/MommyHeather/AdvancedBackups/assets/66441550/ba73af5f-1bca-4ec7-9a3e-a21f6b7350ab) + +\- Next you choose whether you're restoring the entire backup, or a singular file. + +- This restores the **ENTIRE WORLD STATE** at the time of the backups. Partial backups will have the relevant previous backups also restored to make this happen. + + +Finally, you can accept the warning prompt it gives you. + +If you chose to restore the entire backup, the program will exit when it is complete. +If you chose to restore a singular file, you'll be presented with a rudimentary file browser. The below example is for differential backups: + +![image](https://github.com/MommyHeather/AdvancedBackups/assets/66441550/d5f771f5-32d4-435f-aa82-a1da52e3996c) + +Directories are marked, and `../` will traverse up a directory. + +If your selected backup type is differential or incremental, files will be marked with the date they're from. This is purely for your information, the file's state will match that of when the selected backup was made. + +Once you select a file, it will be restored. The program will then exit. + +![image](https://github.com/MommyHeather/AdvancedBackups/assets/66441550/7a2c5d4c-e8db-48c3-8353-46486b9f86b3) + From b119fe4d32e54cf2970faac7dc1798e9780157b8 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Thu, 1 Jun 2023 15:07:35 +0000 Subject: [PATCH 055/580] Update core files --- README.md | 81 +++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 67 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 8e2acc42..d4321826 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ Many Minecraft versions are supported - request more if the one you want isn't y - Fabric 1.18 - Forge 1.16 - Forge 1.12 +- Forge 1.7.10 ## Features: Choose between zip, differential or incremental backups. @@ -35,17 +36,69 @@ Customisable compression level. \- Upon first boot, an `AdvancedBackups.properties` file will be created in your server or client root directory. \- Adjust this to suit your needs, then restart the server or use `/AdvancedBackups reload` to reload the config. A small description of each config entry is below. -| Config | Description | Default Value | -| ----------- | ----------- | ------------- | -| config.advancedbackups.enabled | Enable or disable backups entirely. | true | -| config.advancedbackups.activity | Enable or disable player activity requirements. | false | -| config.advancedbackups.type | Whether to use zip, differential or incremental backups. | zip | -| config.advancedbackups.path | The relative or absolute location where backups are stored. | ./backups | -| config.advancedbackups.size | The maximum backup size to keep, in GB. Oldest backups are deleted if this is exceeded. | 50 | -| config.advancedbackups.frequency.min | The minimum time between backups. Command backups bypass this. | 0.5 | -| config.advancedbackups.frequency.shutdown | Whether to make a backup on server shutdown. | false | -| config.advancedbackups.frequency.startup | Whether to make a backup on server startup. | false | -| config.advancedbackups.logging.silent | Whether to disable chat and console logging. Does not affect debug.log or error messages. | false | -| config.advancedbackups.zips.compression | The attempted compression level for all zip files. | 4 | -| config.advancedbackups.chains.length | The maximum chain length for incremental and differential backups. | 50 | -| config.advancedbackups.chains.compress | Whether to compress incremental and differential backups into zip files. | true | +| Config | Description | Default Value | Supported From | +| ----------- | ----------- | ------------- | -------------- | +| config.advancedbackups.enabled | Enable or disable backups entirely. | true | 0.3 | +| config.advancedbackups.activity | Enable or disable player activity requirements. | false | N/A | +| config.advancedbackups.save | Whether to save before making a backup. | false | 0.3 | +| config.advancedbackups.type | Whether to use zip, differential or incremental backups. | differential | 0.3 | +| config.advancedbackups.path | The relative or absolute location where backups are stored. | ./backups | 0.3 | +| config.advancedbackups.size | The maximum backup size to keep, in GB. Oldest backups are deleted if this is exceeded. | 50 | 0.3 | +| config.advancedbackups.frequency.min | The minimum time between backups. Command backups bypass this. | 0.5 | 0.3 | +| config.advancedbackups.frequency.max | If this time has passed since a backup was last made, one **will** be made. | 24 | 0.3 | +| config.advancedbackups.frequency.uptime| Whether the schedule is based on uptime. If not. it uses real-time instead. | true | 0.3 | +| config.advancedbackups.frequency.schedule | Uptime based : a looping uptime-based schedule. Real-time based : A strict schedule, following real-world time. | 12:00 | 0.3 | +| config.advancedbackups.frequency.shutdown | Whether to make a backup on server shutdown. | false | 0.0 | +| config.advancedbackups.frequency.startup | Whether to make a backup on server startup. | false | 0.3 | +| config.advancedbackups.frequency.delay | The delay in seconds before making a startup backup. Always at least 5 seconds. | 5 | 0.3 | +| config.advancedbackups.logging.silent | Whether to disable chat and console logging. Does not affect debug.log or error messages. | false | N/A | +| config.advancedbackups.zips.compression | The attempted compression level for all zip files. | 4 | 0.3 | +| config.advancedbackups.chains.length | The maximum chain length for incremental and differential backups. | 50 | 0.3 | +| config.advancedbackups.chains.compress | Whether to compress incremental and differential backups into zip files. | true | 0.3 | +| config.advancedbackups.chains.smart | For differential and incremental backups. Resets the chain length if every file is being backed up. | true | 0.3 | + +#### Commands: + +None currently implemented. + + +### Commandline: +TODO - export option for backups. + +\- Run the jar directly from the mods folder. `java -jar AdvancedBackups-modloader-mcversion-modversion` for example, replacing the filename with the correct one for your installation. + +\- It will read your config. Then, it will ask you which backup type to restore. + +\- Afterwards, it will ask you if you are on a client or server. If you run the forge/fabric server software, choose server, otherwise it's a client. + +\- Then it will ask for your world name. It will verify this, and will not proceed if it can't find the name. + +\- Then it will prompt you to choose a backup to restore. The most recent are listed last. With differential and incremental upgrades, the backups will be labelled as partial or fill. + +- This is only for your information, and will not affect the restoration process. + +\- The below image shows this for a differential backup. + + +![image](https://github.com/MommyHeather/AdvancedBackups/assets/66441550/ba73af5f-1bca-4ec7-9a3e-a21f6b7350ab) + +\- Next you choose whether you're restoring the entire backup, or a singular file. + +- This restores the **ENTIRE WORLD STATE** at the time of the backups. Partial backups will have the relevant previous backups also restored to make this happen. + + +Finally, you can accept the warning prompt it gives you. + +If you chose to restore the entire backup, the program will exit when it is complete. +If you chose to restore a singular file, you'll be presented with a rudimentary file browser. The below example is for differential backups: + +![image](https://github.com/MommyHeather/AdvancedBackups/assets/66441550/d5f771f5-32d4-435f-aa82-a1da52e3996c) + +Directories are marked, and `../` will traverse up a directory. + +If your selected backup type is differential or incremental, files will be marked with the date they're from. This is purely for your information, the file's state will match that of when the selected backup was made. + +Once you select a file, it will be restored. The program will then exit. + +![image](https://github.com/MommyHeather/AdvancedBackups/assets/66441550/7a2c5d4c-e8db-48c3-8353-46486b9f86b3) + From 22dd861d3fbc5fd89f01f84da0bcaa760530e042 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Thu, 1 Jun 2023 15:08:03 +0000 Subject: [PATCH 056/580] Update core files --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index d4321826..5c14edf5 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,7 @@ Customisable compression level. ### Ingame: \- Upon first boot, an `AdvancedBackups.properties` file will be created in your server or client root directory. + \- Adjust this to suit your needs, then restart the server or use `/AdvancedBackups reload` to reload the config. A small description of each config entry is below. | Config | Description | Default Value | Supported From | From 0d5f8cf58ab0dfb12551e708b945bdeaa73e16e7 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Thu, 1 Jun 2023 15:08:04 +0000 Subject: [PATCH 057/580] Update core files --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index d4321826..5c14edf5 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,7 @@ Customisable compression level. ### Ingame: \- Upon first boot, an `AdvancedBackups.properties` file will be created in your server or client root directory. + \- Adjust this to suit your needs, then restart the server or use `/AdvancedBackups reload` to reload the config. A small description of each config entry is below. | Config | Description | Default Value | Supported From | From 306d779ffea6425c6219ed86aaf6302128c38efa Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Thu, 1 Jun 2023 15:08:05 +0000 Subject: [PATCH 058/580] Update core files --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index d4321826..5c14edf5 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,7 @@ Customisable compression level. ### Ingame: \- Upon first boot, an `AdvancedBackups.properties` file will be created in your server or client root directory. + \- Adjust this to suit your needs, then restart the server or use `/AdvancedBackups reload` to reload the config. A small description of each config entry is below. | Config | Description | Default Value | Supported From | From 86063b2003582b1927eb7dad7e2ff6895bda424c Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Thu, 1 Jun 2023 15:08:08 +0000 Subject: [PATCH 059/580] Update core files --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index d4321826..5c14edf5 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,7 @@ Customisable compression level. ### Ingame: \- Upon first boot, an `AdvancedBackups.properties` file will be created in your server or client root directory. + \- Adjust this to suit your needs, then restart the server or use `/AdvancedBackups reload` to reload the config. A small description of each config entry is below. | Config | Description | Default Value | Supported From | From 6ce31f92bf4bacb038c4305b2af98b937ffbf65e Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Thu, 1 Jun 2023 15:08:09 +0000 Subject: [PATCH 060/580] Update core files --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index d4321826..5c14edf5 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,7 @@ Customisable compression level. ### Ingame: \- Upon first boot, an `AdvancedBackups.properties` file will be created in your server or client root directory. + \- Adjust this to suit your needs, then restart the server or use `/AdvancedBackups reload` to reload the config. A small description of each config entry is below. | Config | Description | Default Value | Supported From | From 391245347949572bc3b70764215d6c4d02118e91 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Tue, 6 Jun 2023 15:17:35 +0100 Subject: [PATCH 061/580] Support player activity config --- .../uk/mommyheather/advancedbackups/AdvancedBackups.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index cfbda984..af6e53bf 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -8,6 +8,7 @@ import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.event.entity.player.PlayerEvent; import net.minecraftforge.event.server.ServerStartedEvent; import net.minecraftforge.event.server.ServerStartingEvent; import net.minecraftforge.event.server.ServerStoppingEvent; @@ -54,4 +55,10 @@ public void onServerStopping(ServerStoppingEvent event) { BackupWrapper.checkShutdownBackups(); } + + @SubscribeEvent + public void onPlayerJoined(PlayerEvent.PlayerLoggedInEvent event) { + PlatformMethodWrapper.activity = true; + } + } From 259a4ea366c2c64e57d49ba59b20877fb0301c9c Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Tue, 6 Jun 2023 15:49:16 +0100 Subject: [PATCH 062/580] Support player activity config requirement --- .../co/uk/mommyheather/advancedbackups/AdvancedBackups.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index b9d74ca8..d6909c26 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -2,6 +2,7 @@ import net.fabricmc.api.ModInitializer; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; +import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; import net.minecraft.server.MinecraftServer; import net.minecraft.util.WorldSavePath; @@ -42,5 +43,9 @@ public void onInitialize() { ServerLifecycleEvents.SERVER_STOPPING.register((server) -> { BackupWrapper.checkShutdownBackups(); }); + + ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> { + PlatformMethodWrapper.activity = true; + }); } } \ No newline at end of file From e55470716705437ab3f325b283f134668a23eb08 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Tue, 6 Jun 2023 16:38:41 +0100 Subject: [PATCH 063/580] Support player activity requirements, and fix a launch issue... --- .../advancedbackups/AdvancedBackups.java | 6 +++++ src/main/resources/META-INF/mods.toml | 22 ++++++++----------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index e6ec8d6f..d97b2e3b 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -4,6 +4,7 @@ import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; import co.uk.mommyheather.advancedbackups.core.config.AVConfig; import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.entity.player.PlayerEvent.PlayerLoggedInEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.event.server.FMLServerStartedEvent; @@ -52,4 +53,9 @@ public void onServerStopping(FMLServerStoppingEvent event) { BackupWrapper.checkShutdownBackups(); } + @SubscribeEvent + public void onPlayerConneccted(PlayerLoggedInEvent event) { + PlatformMethodWrapper.activity = true; + } + } diff --git a/src/main/resources/META-INF/mods.toml b/src/main/resources/META-INF/mods.toml index aabc446e..ce017df3 100644 --- a/src/main/resources/META-INF/mods.toml +++ b/src/main/resources/META-INF/mods.toml @@ -9,39 +9,35 @@ modLoader="javafml" #mandatory loaderVersion="[36,)" #mandatory This is typically bumped every Minecraft version by Forge. See our download page for lists of versions. # The license for you mod. This is mandatory metadata and allows for easier comprehension of your redistributive properties. # Review your options at https://choosealicense.com/. All rights reserved is the default copyright stance, and is thus the default here. -license="All rights reserved" +license="MIT" # A URL to refer people to when problems occur with this mod #issueTrackerURL="https://change.me.to.your.issue.tracker.example.invalid/" #optional # A list of mods - how many allowed here is determined by the individual mod loader [[mods]] #mandatory # The modid of the mod -modId="examplemod" #mandatory +modId="advancedbackups" #mandatory # The version number of the mod - there's a few well known ${} variables useable here or just hardcode it # ${file.jarVersion} will substitute the value of the Implementation-Version as read from the mod's JAR file metadata # see the associated build.gradle script for how to populate this completely automatically during a build version="${file.jarVersion}" #mandatory # A display name for the mod -displayName="Example Mod" #mandatory +displayName="Advanced Backups" #mandatory # A URL to query for updates for this mod. See the JSON update specification https://mcforge.readthedocs.io/en/latest/gettingstarted/autoupdate/ #updateJSONURL="https://change.me.example.invalid/updates.json" #optional # A URL for the "homepage" for this mod, displayed in the mod UI #displayURL="https://change.me.to.your.mods.homepage.example.invalid/" #optional # A file name (in the root of the mod JAR) containing a logo for display -logoFile="examplemod.png" #optional +#logoFile="examplemod.png" #optional # A text field displayed in the mod UI -credits="Thanks for this example mod goes to Java" #optional +#credits="Thanks for this example mod goes to Java" #optional # A text field displayed in the mod UI -authors="Love, Cheese and small house plants" #optional +authors="Mommy Heather" #optional # The description text for the mod (multi line!) (#mandatory) description=''' -This is a long form description of the mod. You can write whatever you want here - -Have some lorem ipsum. - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed mollis lacinia magna. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Sed sagittis luctus odio eu tempus. Interdum et malesuada fames ac ante ipsum primis in faucibus. Pellentesque volutpat ligula eget lacus auctor sagittis. In hac habitasse platea dictumst. Nunc gravida elit vitae sem vehicula efficitur. Donec mattis ipsum et arcu lobortis, eleifend sagittis sem rutrum. Cras pharetra quam eget posuere fermentum. Sed id tincidunt justo. Lorem ipsum dolor sit amet, consectetur adipiscing elit. +A powerful and highly configurable backup mod. Visit https://github.com/MommyHeather/AdvancedBackups for more info. ''' # A dependency - use the . to indicate dependency for a specific modid. Dependencies are optional. -[[dependencies.examplemod]] #optional +[[dependencies.advancedbackups]] #optional # the modid of the dependency modId="forge" #mandatory # Does this dependency have to exist - if not, ordering below must be specified @@ -53,7 +49,7 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed mollis lacinia magn # Side this dependency is applied on - BOTH, CLIENT or SERVER side="BOTH" # Here's another dependency -[[dependencies.examplemod]] +[[dependencies.advancedbackups]] modId="minecraft" mandatory=true # This version range declares a minimum of the current minecraft version up to but not including the next major version From e8da6908e93bc4154fa1748cb20a1c7018b7ec1c Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Tue, 6 Jun 2023 17:12:43 +0100 Subject: [PATCH 064/580] Support player activity requirements. --- .../mommyheather/advancedbackups/AdvancedBackups.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 941b36d0..b1a2f4ae 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -3,6 +3,7 @@ import net.minecraft.init.Blocks; import net.minecraft.server.MinecraftServer; import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.Mod.EventBusSubscriber; import net.minecraftforge.fml.common.Mod.EventHandler; import net.minecraftforge.fml.common.event.FMLInitializationEvent; import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; @@ -10,6 +11,7 @@ import net.minecraftforge.fml.common.event.FMLServerStartingEvent; import net.minecraftforge.fml.common.event.FMLServerStoppingEvent; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.PlayerEvent; import net.minecraftforge.fml.relauncher.Side; import org.apache.logging.log4j.Logger; @@ -23,11 +25,12 @@ @Mod(modid = AdvancedBackups.MODID, name = AdvancedBackups.NAME, version = AdvancedBackups.VERSION, acceptableRemoteVersions = "*") +@EventBusSubscriber public class AdvancedBackups { public static final String MODID = "advancedbackups"; public static final String NAME = "Advanced Backups"; - public static final String VERSION = "0.1"; + public static final String VERSION = "0.3"; private static Logger LOGGER; public static Consumer infoLogger; @@ -81,4 +84,9 @@ public void onServerStopping(FMLServerStoppingEvent event) { BackupWrapper.checkShutdownBackups(); } + @SubscribeEvent + public void onPlayerConnect(PlayerEvent.PlayerLoggedInEvent event) { + PlatformMethodWrapper.activity = true; + } + } From d080bcaa5455a59dc0b867d4e1b2e3f4c8175026 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Tue, 6 Jun 2023 18:00:33 +0100 Subject: [PATCH 065/580] Support player activity requirements --- .../mommyheather/advancedbackups/AdvancedBackups.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 0b111806..f1f64d69 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -1,11 +1,14 @@ package co.uk.mommyheather.advancedbackups; +import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.common.Mod; import cpw.mods.fml.common.Mod.EventHandler; import cpw.mods.fml.common.event.FMLInitializationEvent; import cpw.mods.fml.common.event.FMLServerStartedEvent; import cpw.mods.fml.common.event.FMLServerStartingEvent; import cpw.mods.fml.common.event.FMLServerStoppingEvent; +import cpw.mods.fml.common.eventhandler.SubscribeEvent; +import cpw.mods.fml.common.gameevent.PlayerEvent; import cpw.mods.fml.relauncher.Side; import org.apache.logging.log4j.LogManager; @@ -37,7 +40,7 @@ public class AdvancedBackups public static MinecraftServer server; - @Mod.EventHandler + @EventHandler @SuppressWarnings("unused") public void init(FMLInitializationEvent ev) { infoLogger = LOGGER::info; @@ -52,6 +55,7 @@ public AdvancedBackups() { // Register ourselves for server and other game events we are interested in MinecraftForge.EVENT_BUS.register(this); + FMLCommonHandler.instance().bus().register(this); } @EventHandler @@ -82,4 +86,9 @@ public void onServerStopping(FMLServerStoppingEvent event) { BackupWrapper.checkShutdownBackups(); } + @SubscribeEvent + public void onPlayerConnected(PlayerEvent.PlayerLoggedInEvent event) { + PlatformMethodWrapper.activity = true; + } + } From 194351767d54be9a9908e794702afcfc2901a369 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Tue, 6 Jun 2023 17:10:33 +0000 Subject: [PATCH 066/580] Update core files --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5c14edf5..0b56679c 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ Customisable compression level. | Config | Description | Default Value | Supported From | | ----------- | ----------- | ------------- | -------------- | | config.advancedbackups.enabled | Enable or disable backups entirely. | true | 0.3 | -| config.advancedbackups.activity | Enable or disable player activity requirements. | false | N/A | +| config.advancedbackups.activity | Enable or disable player activity requirements. | false | next release | | config.advancedbackups.save | Whether to save before making a backup. | false | 0.3 | | config.advancedbackups.type | Whether to use zip, differential or incremental backups. | differential | 0.3 | | config.advancedbackups.path | The relative or absolute location where backups are stored. | ./backups | 0.3 | From 7e2350c5665e3882ff1432a0b438666589693951 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Tue, 6 Jun 2023 17:10:34 +0000 Subject: [PATCH 067/580] Update core files --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5c14edf5..0b56679c 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ Customisable compression level. | Config | Description | Default Value | Supported From | | ----------- | ----------- | ------------- | -------------- | | config.advancedbackups.enabled | Enable or disable backups entirely. | true | 0.3 | -| config.advancedbackups.activity | Enable or disable player activity requirements. | false | N/A | +| config.advancedbackups.activity | Enable or disable player activity requirements. | false | next release | | config.advancedbackups.save | Whether to save before making a backup. | false | 0.3 | | config.advancedbackups.type | Whether to use zip, differential or incremental backups. | differential | 0.3 | | config.advancedbackups.path | The relative or absolute location where backups are stored. | ./backups | 0.3 | From d42aed1cdd75a8982e37e70fe623f7d21ef856c6 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Tue, 6 Jun 2023 17:10:35 +0000 Subject: [PATCH 068/580] Update core files --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5c14edf5..0b56679c 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ Customisable compression level. | Config | Description | Default Value | Supported From | | ----------- | ----------- | ------------- | -------------- | | config.advancedbackups.enabled | Enable or disable backups entirely. | true | 0.3 | -| config.advancedbackups.activity | Enable or disable player activity requirements. | false | N/A | +| config.advancedbackups.activity | Enable or disable player activity requirements. | false | next release | | config.advancedbackups.save | Whether to save before making a backup. | false | 0.3 | | config.advancedbackups.type | Whether to use zip, differential or incremental backups. | differential | 0.3 | | config.advancedbackups.path | The relative or absolute location where backups are stored. | ./backups | 0.3 | From a235cc2d2037e638501df5f822a5c0a05fa6cb1f Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Tue, 6 Jun 2023 17:10:38 +0000 Subject: [PATCH 069/580] Update core files --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5c14edf5..0b56679c 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ Customisable compression level. | Config | Description | Default Value | Supported From | | ----------- | ----------- | ------------- | -------------- | | config.advancedbackups.enabled | Enable or disable backups entirely. | true | 0.3 | -| config.advancedbackups.activity | Enable or disable player activity requirements. | false | N/A | +| config.advancedbackups.activity | Enable or disable player activity requirements. | false | next release | | config.advancedbackups.save | Whether to save before making a backup. | false | 0.3 | | config.advancedbackups.type | Whether to use zip, differential or incremental backups. | differential | 0.3 | | config.advancedbackups.path | The relative or absolute location where backups are stored. | ./backups | 0.3 | From f17e094a6395c047705e4c8ea42811d4b7066457 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Tue, 6 Jun 2023 17:16:52 +0000 Subject: [PATCH 070/580] Update core files --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0b56679c..d23fd3a9 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ Customisable compression level. | config.advancedbackups.frequency.max | If this time has passed since a backup was last made, one **will** be made. | 24 | 0.3 | | config.advancedbackups.frequency.uptime| Whether the schedule is based on uptime. If not. it uses real-time instead. | true | 0.3 | | config.advancedbackups.frequency.schedule | Uptime based : a looping uptime-based schedule. Real-time based : A strict schedule, following real-world time. | 12:00 | 0.3 | -| config.advancedbackups.frequency.shutdown | Whether to make a backup on server shutdown. | false | 0.0 | +| config.advancedbackups.frequency.shutdown | Whether to make a backup on server shutdown. | false | 0.3 | | config.advancedbackups.frequency.startup | Whether to make a backup on server startup. | false | 0.3 | | config.advancedbackups.frequency.delay | The delay in seconds before making a startup backup. Always at least 5 seconds. | 5 | 0.3 | | config.advancedbackups.logging.silent | Whether to disable chat and console logging. Does not affect debug.log or error messages. | false | N/A | From 1246c1342e0bc095b9e5336c0c96729639525a23 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Tue, 6 Jun 2023 17:16:54 +0000 Subject: [PATCH 071/580] Update core files --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0b56679c..d23fd3a9 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ Customisable compression level. | config.advancedbackups.frequency.max | If this time has passed since a backup was last made, one **will** be made. | 24 | 0.3 | | config.advancedbackups.frequency.uptime| Whether the schedule is based on uptime. If not. it uses real-time instead. | true | 0.3 | | config.advancedbackups.frequency.schedule | Uptime based : a looping uptime-based schedule. Real-time based : A strict schedule, following real-world time. | 12:00 | 0.3 | -| config.advancedbackups.frequency.shutdown | Whether to make a backup on server shutdown. | false | 0.0 | +| config.advancedbackups.frequency.shutdown | Whether to make a backup on server shutdown. | false | 0.3 | | config.advancedbackups.frequency.startup | Whether to make a backup on server startup. | false | 0.3 | | config.advancedbackups.frequency.delay | The delay in seconds before making a startup backup. Always at least 5 seconds. | 5 | 0.3 | | config.advancedbackups.logging.silent | Whether to disable chat and console logging. Does not affect debug.log or error messages. | false | N/A | From c4d493ca92d75b16e3108a7a0f53cfca3a55bfc4 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Tue, 6 Jun 2023 17:20:08 +0000 Subject: [PATCH 072/580] Update core files --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5c14edf5..d23fd3a9 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ Customisable compression level. | Config | Description | Default Value | Supported From | | ----------- | ----------- | ------------- | -------------- | | config.advancedbackups.enabled | Enable or disable backups entirely. | true | 0.3 | -| config.advancedbackups.activity | Enable or disable player activity requirements. | false | N/A | +| config.advancedbackups.activity | Enable or disable player activity requirements. | false | next release | | config.advancedbackups.save | Whether to save before making a backup. | false | 0.3 | | config.advancedbackups.type | Whether to use zip, differential or incremental backups. | differential | 0.3 | | config.advancedbackups.path | The relative or absolute location where backups are stored. | ./backups | 0.3 | @@ -49,7 +49,7 @@ Customisable compression level. | config.advancedbackups.frequency.max | If this time has passed since a backup was last made, one **will** be made. | 24 | 0.3 | | config.advancedbackups.frequency.uptime| Whether the schedule is based on uptime. If not. it uses real-time instead. | true | 0.3 | | config.advancedbackups.frequency.schedule | Uptime based : a looping uptime-based schedule. Real-time based : A strict schedule, following real-world time. | 12:00 | 0.3 | -| config.advancedbackups.frequency.shutdown | Whether to make a backup on server shutdown. | false | 0.0 | +| config.advancedbackups.frequency.shutdown | Whether to make a backup on server shutdown. | false | 0.3 | | config.advancedbackups.frequency.startup | Whether to make a backup on server startup. | false | 0.3 | | config.advancedbackups.frequency.delay | The delay in seconds before making a startup backup. Always at least 5 seconds. | 5 | 0.3 | | config.advancedbackups.logging.silent | Whether to disable chat and console logging. Does not affect debug.log or error messages. | false | N/A | From 0f072e2f81b90846d011f8613322558f90a53b00 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Tue, 6 Jun 2023 17:20:09 +0000 Subject: [PATCH 073/580] Update core files --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0b56679c..d23fd3a9 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ Customisable compression level. | config.advancedbackups.frequency.max | If this time has passed since a backup was last made, one **will** be made. | 24 | 0.3 | | config.advancedbackups.frequency.uptime| Whether the schedule is based on uptime. If not. it uses real-time instead. | true | 0.3 | | config.advancedbackups.frequency.schedule | Uptime based : a looping uptime-based schedule. Real-time based : A strict schedule, following real-world time. | 12:00 | 0.3 | -| config.advancedbackups.frequency.shutdown | Whether to make a backup on server shutdown. | false | 0.0 | +| config.advancedbackups.frequency.shutdown | Whether to make a backup on server shutdown. | false | 0.3 | | config.advancedbackups.frequency.startup | Whether to make a backup on server startup. | false | 0.3 | | config.advancedbackups.frequency.delay | The delay in seconds before making a startup backup. Always at least 5 seconds. | 5 | 0.3 | | config.advancedbackups.logging.silent | Whether to disable chat and console logging. Does not affect debug.log or error messages. | false | N/A | From 9360501bee263a6a9f3f526b2552048a9f3254c3 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Tue, 6 Jun 2023 17:20:10 +0000 Subject: [PATCH 074/580] Update core files --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0b56679c..d23fd3a9 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ Customisable compression level. | config.advancedbackups.frequency.max | If this time has passed since a backup was last made, one **will** be made. | 24 | 0.3 | | config.advancedbackups.frequency.uptime| Whether the schedule is based on uptime. If not. it uses real-time instead. | true | 0.3 | | config.advancedbackups.frequency.schedule | Uptime based : a looping uptime-based schedule. Real-time based : A strict schedule, following real-world time. | 12:00 | 0.3 | -| config.advancedbackups.frequency.shutdown | Whether to make a backup on server shutdown. | false | 0.0 | +| config.advancedbackups.frequency.shutdown | Whether to make a backup on server shutdown. | false | 0.3 | | config.advancedbackups.frequency.startup | Whether to make a backup on server startup. | false | 0.3 | | config.advancedbackups.frequency.delay | The delay in seconds before making a startup backup. Always at least 5 seconds. | 5 | 0.3 | | config.advancedbackups.logging.silent | Whether to disable chat and console logging. Does not affect debug.log or error messages. | false | N/A | From 358e384a13d9fc41596abaa6b098f939cf841f5d Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Wed, 7 Jun 2023 14:32:51 +0000 Subject: [PATCH 075/580] Update core files --- .../core/CoreCommandSystem.java | 36 ++++++++++++++++++ .../core/backups/BackupCheckEnum.java | 38 +++++++++++++++++++ .../core/backups/BackupWrapper.java | 22 +++++++---- 3 files changed, 88 insertions(+), 8 deletions(-) create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupCheckEnum.java diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java new file mode 100644 index 00000000..ae8a2fef --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java @@ -0,0 +1,36 @@ +package co.uk.mommyheather.advancedbackups.core; + +import java.util.function.Consumer; + +import co.uk.mommyheather.advancedbackups.core.backups.BackupCheckEnum; +import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; +import co.uk.mommyheather.advancedbackups.core.config.AVConfig; + +public class CoreCommandSystem { + + //These methods are all called by relevant command classes in version specific code + public static void checkBackups(Consumer chat) { + BackupCheckEnum check = BackupWrapper.checkBackups(); + chat.accept(check.getCheckMessage()); + } + + public static void startBackup(Consumer chat) { + BackupCheckEnum check = BackupWrapper.checkBackups(); + chat.accept(check.getCheckMessage()); + if (check.success()) { + chat.accept("Starting backup..."); + BackupWrapper.makeSingleBackup(0); + } + } + + public static void forceBackup(Consumer chat) { + chat.accept("Forcing a backup..."); + BackupWrapper.makeSingleBackup(0); + } + + public static void reloadConfig(Consumer chat) { + chat.accept("Reloading config..."); + AVConfig.loadConfig(); + chat.accept("Done!"); + } +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupCheckEnum.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupCheckEnum.java new file mode 100644 index 00000000..06e00e14 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupCheckEnum.java @@ -0,0 +1,38 @@ +package co.uk.mommyheather.advancedbackups.core.backups; + +public enum BackupCheckEnum { + SUCCESS, + DISABLED, + NOACTIVITY, + TOORECENT; + + public boolean success() { + switch (this) { + case SUCCESS: { + return true; + } + default : return false; + } + } + + + public String getCheckMessage() { + switch(this) { + case SUCCESS : { + return "Checks successful!"; + } + case DISABLED : { + return "Backups are disabled!"; + } + case NOACTIVITY : { + return "Player activity is required, but none have been active!"; + } + case TOORECENT : { + return "The time since the last backup is less than the minimum time specified in config!"; + } + default : { + return "You should not see this message, report a bug!"; + } + } + } +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java index d089bfbe..59b9f97f 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java @@ -29,19 +29,25 @@ public static void checkShutdownBackups() { public static void checkAndMakeBackups(long delay) { prepareBackupDestination(); - - if (!AVConfig.config.getEnabled()) return; - if (AVConfig.config.getRequireActivity() && !PlatformMethodWrapper.activity) return; - if (checkMostRecentBackup()) return; - - // Finally : - makeSingleBackup(delay); + BackupCheckEnum e = checkBackups(); + if (e.success()) { + makeSingleBackup(delay); + } } public static void checkAndMakeBackups() { checkAndMakeBackups(0); } - + + + public static BackupCheckEnum checkBackups() { + if (!AVConfig.config.getEnabled()) return BackupCheckEnum.DISABLED; + if (AVConfig.config.getRequireActivity() && !PlatformMethodWrapper.activity) return BackupCheckEnum.NOACTIVITY; + if (checkMostRecentBackup()) return BackupCheckEnum.TOORECENT; + + return BackupCheckEnum.SUCCESS; + + } private static void prepareBackupDestination() { File file = new File(AVConfig.config.getPath()); From 0b7b9be515cee70c0578d81fcea1b231dac4815b Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Wed, 7 Jun 2023 14:32:52 +0000 Subject: [PATCH 076/580] Update core files --- .../core/CoreCommandSystem.java | 36 ++++++++++++++++++ .../core/backups/BackupCheckEnum.java | 38 +++++++++++++++++++ .../core/backups/BackupWrapper.java | 22 +++++++---- 3 files changed, 88 insertions(+), 8 deletions(-) create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupCheckEnum.java diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java new file mode 100644 index 00000000..ae8a2fef --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java @@ -0,0 +1,36 @@ +package co.uk.mommyheather.advancedbackups.core; + +import java.util.function.Consumer; + +import co.uk.mommyheather.advancedbackups.core.backups.BackupCheckEnum; +import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; +import co.uk.mommyheather.advancedbackups.core.config.AVConfig; + +public class CoreCommandSystem { + + //These methods are all called by relevant command classes in version specific code + public static void checkBackups(Consumer chat) { + BackupCheckEnum check = BackupWrapper.checkBackups(); + chat.accept(check.getCheckMessage()); + } + + public static void startBackup(Consumer chat) { + BackupCheckEnum check = BackupWrapper.checkBackups(); + chat.accept(check.getCheckMessage()); + if (check.success()) { + chat.accept("Starting backup..."); + BackupWrapper.makeSingleBackup(0); + } + } + + public static void forceBackup(Consumer chat) { + chat.accept("Forcing a backup..."); + BackupWrapper.makeSingleBackup(0); + } + + public static void reloadConfig(Consumer chat) { + chat.accept("Reloading config..."); + AVConfig.loadConfig(); + chat.accept("Done!"); + } +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupCheckEnum.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupCheckEnum.java new file mode 100644 index 00000000..06e00e14 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupCheckEnum.java @@ -0,0 +1,38 @@ +package co.uk.mommyheather.advancedbackups.core.backups; + +public enum BackupCheckEnum { + SUCCESS, + DISABLED, + NOACTIVITY, + TOORECENT; + + public boolean success() { + switch (this) { + case SUCCESS: { + return true; + } + default : return false; + } + } + + + public String getCheckMessage() { + switch(this) { + case SUCCESS : { + return "Checks successful!"; + } + case DISABLED : { + return "Backups are disabled!"; + } + case NOACTIVITY : { + return "Player activity is required, but none have been active!"; + } + case TOORECENT : { + return "The time since the last backup is less than the minimum time specified in config!"; + } + default : { + return "You should not see this message, report a bug!"; + } + } + } +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java index d089bfbe..59b9f97f 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java @@ -29,19 +29,25 @@ public static void checkShutdownBackups() { public static void checkAndMakeBackups(long delay) { prepareBackupDestination(); - - if (!AVConfig.config.getEnabled()) return; - if (AVConfig.config.getRequireActivity() && !PlatformMethodWrapper.activity) return; - if (checkMostRecentBackup()) return; - - // Finally : - makeSingleBackup(delay); + BackupCheckEnum e = checkBackups(); + if (e.success()) { + makeSingleBackup(delay); + } } public static void checkAndMakeBackups() { checkAndMakeBackups(0); } - + + + public static BackupCheckEnum checkBackups() { + if (!AVConfig.config.getEnabled()) return BackupCheckEnum.DISABLED; + if (AVConfig.config.getRequireActivity() && !PlatformMethodWrapper.activity) return BackupCheckEnum.NOACTIVITY; + if (checkMostRecentBackup()) return BackupCheckEnum.TOORECENT; + + return BackupCheckEnum.SUCCESS; + + } private static void prepareBackupDestination() { File file = new File(AVConfig.config.getPath()); From c584b9647883b04f3d4aceeedd76806b5fad524b Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Wed, 7 Jun 2023 14:32:53 +0000 Subject: [PATCH 077/580] Update core files --- .../core/CoreCommandSystem.java | 36 ++++++++++++++++++ .../core/backups/BackupCheckEnum.java | 38 +++++++++++++++++++ .../core/backups/BackupWrapper.java | 22 +++++++---- 3 files changed, 88 insertions(+), 8 deletions(-) create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupCheckEnum.java diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java new file mode 100644 index 00000000..ae8a2fef --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java @@ -0,0 +1,36 @@ +package co.uk.mommyheather.advancedbackups.core; + +import java.util.function.Consumer; + +import co.uk.mommyheather.advancedbackups.core.backups.BackupCheckEnum; +import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; +import co.uk.mommyheather.advancedbackups.core.config.AVConfig; + +public class CoreCommandSystem { + + //These methods are all called by relevant command classes in version specific code + public static void checkBackups(Consumer chat) { + BackupCheckEnum check = BackupWrapper.checkBackups(); + chat.accept(check.getCheckMessage()); + } + + public static void startBackup(Consumer chat) { + BackupCheckEnum check = BackupWrapper.checkBackups(); + chat.accept(check.getCheckMessage()); + if (check.success()) { + chat.accept("Starting backup..."); + BackupWrapper.makeSingleBackup(0); + } + } + + public static void forceBackup(Consumer chat) { + chat.accept("Forcing a backup..."); + BackupWrapper.makeSingleBackup(0); + } + + public static void reloadConfig(Consumer chat) { + chat.accept("Reloading config..."); + AVConfig.loadConfig(); + chat.accept("Done!"); + } +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupCheckEnum.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupCheckEnum.java new file mode 100644 index 00000000..06e00e14 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupCheckEnum.java @@ -0,0 +1,38 @@ +package co.uk.mommyheather.advancedbackups.core.backups; + +public enum BackupCheckEnum { + SUCCESS, + DISABLED, + NOACTIVITY, + TOORECENT; + + public boolean success() { + switch (this) { + case SUCCESS: { + return true; + } + default : return false; + } + } + + + public String getCheckMessage() { + switch(this) { + case SUCCESS : { + return "Checks successful!"; + } + case DISABLED : { + return "Backups are disabled!"; + } + case NOACTIVITY : { + return "Player activity is required, but none have been active!"; + } + case TOORECENT : { + return "The time since the last backup is less than the minimum time specified in config!"; + } + default : { + return "You should not see this message, report a bug!"; + } + } + } +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java index d089bfbe..59b9f97f 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java @@ -29,19 +29,25 @@ public static void checkShutdownBackups() { public static void checkAndMakeBackups(long delay) { prepareBackupDestination(); - - if (!AVConfig.config.getEnabled()) return; - if (AVConfig.config.getRequireActivity() && !PlatformMethodWrapper.activity) return; - if (checkMostRecentBackup()) return; - - // Finally : - makeSingleBackup(delay); + BackupCheckEnum e = checkBackups(); + if (e.success()) { + makeSingleBackup(delay); + } } public static void checkAndMakeBackups() { checkAndMakeBackups(0); } - + + + public static BackupCheckEnum checkBackups() { + if (!AVConfig.config.getEnabled()) return BackupCheckEnum.DISABLED; + if (AVConfig.config.getRequireActivity() && !PlatformMethodWrapper.activity) return BackupCheckEnum.NOACTIVITY; + if (checkMostRecentBackup()) return BackupCheckEnum.TOORECENT; + + return BackupCheckEnum.SUCCESS; + + } private static void prepareBackupDestination() { File file = new File(AVConfig.config.getPath()); From 3c902251738c240f11e4d96e00e08729fb5218b4 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Wed, 7 Jun 2023 14:32:54 +0000 Subject: [PATCH 078/580] Update core files --- .../core/CoreCommandSystem.java | 36 ++++++++++++++++++ .../core/backups/BackupCheckEnum.java | 38 +++++++++++++++++++ .../core/backups/BackupWrapper.java | 22 +++++++---- 3 files changed, 88 insertions(+), 8 deletions(-) create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupCheckEnum.java diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java new file mode 100644 index 00000000..ae8a2fef --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java @@ -0,0 +1,36 @@ +package co.uk.mommyheather.advancedbackups.core; + +import java.util.function.Consumer; + +import co.uk.mommyheather.advancedbackups.core.backups.BackupCheckEnum; +import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; +import co.uk.mommyheather.advancedbackups.core.config.AVConfig; + +public class CoreCommandSystem { + + //These methods are all called by relevant command classes in version specific code + public static void checkBackups(Consumer chat) { + BackupCheckEnum check = BackupWrapper.checkBackups(); + chat.accept(check.getCheckMessage()); + } + + public static void startBackup(Consumer chat) { + BackupCheckEnum check = BackupWrapper.checkBackups(); + chat.accept(check.getCheckMessage()); + if (check.success()) { + chat.accept("Starting backup..."); + BackupWrapper.makeSingleBackup(0); + } + } + + public static void forceBackup(Consumer chat) { + chat.accept("Forcing a backup..."); + BackupWrapper.makeSingleBackup(0); + } + + public static void reloadConfig(Consumer chat) { + chat.accept("Reloading config..."); + AVConfig.loadConfig(); + chat.accept("Done!"); + } +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupCheckEnum.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupCheckEnum.java new file mode 100644 index 00000000..06e00e14 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupCheckEnum.java @@ -0,0 +1,38 @@ +package co.uk.mommyheather.advancedbackups.core.backups; + +public enum BackupCheckEnum { + SUCCESS, + DISABLED, + NOACTIVITY, + TOORECENT; + + public boolean success() { + switch (this) { + case SUCCESS: { + return true; + } + default : return false; + } + } + + + public String getCheckMessage() { + switch(this) { + case SUCCESS : { + return "Checks successful!"; + } + case DISABLED : { + return "Backups are disabled!"; + } + case NOACTIVITY : { + return "Player activity is required, but none have been active!"; + } + case TOORECENT : { + return "The time since the last backup is less than the minimum time specified in config!"; + } + default : { + return "You should not see this message, report a bug!"; + } + } + } +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java index d089bfbe..59b9f97f 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java @@ -29,19 +29,25 @@ public static void checkShutdownBackups() { public static void checkAndMakeBackups(long delay) { prepareBackupDestination(); - - if (!AVConfig.config.getEnabled()) return; - if (AVConfig.config.getRequireActivity() && !PlatformMethodWrapper.activity) return; - if (checkMostRecentBackup()) return; - - // Finally : - makeSingleBackup(delay); + BackupCheckEnum e = checkBackups(); + if (e.success()) { + makeSingleBackup(delay); + } } public static void checkAndMakeBackups() { checkAndMakeBackups(0); } - + + + public static BackupCheckEnum checkBackups() { + if (!AVConfig.config.getEnabled()) return BackupCheckEnum.DISABLED; + if (AVConfig.config.getRequireActivity() && !PlatformMethodWrapper.activity) return BackupCheckEnum.NOACTIVITY; + if (checkMostRecentBackup()) return BackupCheckEnum.TOORECENT; + + return BackupCheckEnum.SUCCESS; + + } private static void prepareBackupDestination() { File file = new File(AVConfig.config.getPath()); From 95cf888721e7f168b7e53614e3986a8b4d9a373a Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Wed, 7 Jun 2023 14:32:55 +0000 Subject: [PATCH 079/580] Update core files --- .../core/CoreCommandSystem.java | 36 ++++++++++++++++++ .../core/backups/BackupCheckEnum.java | 38 +++++++++++++++++++ .../core/backups/BackupWrapper.java | 22 +++++++---- 3 files changed, 88 insertions(+), 8 deletions(-) create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupCheckEnum.java diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java new file mode 100644 index 00000000..ae8a2fef --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java @@ -0,0 +1,36 @@ +package co.uk.mommyheather.advancedbackups.core; + +import java.util.function.Consumer; + +import co.uk.mommyheather.advancedbackups.core.backups.BackupCheckEnum; +import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; +import co.uk.mommyheather.advancedbackups.core.config.AVConfig; + +public class CoreCommandSystem { + + //These methods are all called by relevant command classes in version specific code + public static void checkBackups(Consumer chat) { + BackupCheckEnum check = BackupWrapper.checkBackups(); + chat.accept(check.getCheckMessage()); + } + + public static void startBackup(Consumer chat) { + BackupCheckEnum check = BackupWrapper.checkBackups(); + chat.accept(check.getCheckMessage()); + if (check.success()) { + chat.accept("Starting backup..."); + BackupWrapper.makeSingleBackup(0); + } + } + + public static void forceBackup(Consumer chat) { + chat.accept("Forcing a backup..."); + BackupWrapper.makeSingleBackup(0); + } + + public static void reloadConfig(Consumer chat) { + chat.accept("Reloading config..."); + AVConfig.loadConfig(); + chat.accept("Done!"); + } +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupCheckEnum.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupCheckEnum.java new file mode 100644 index 00000000..06e00e14 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupCheckEnum.java @@ -0,0 +1,38 @@ +package co.uk.mommyheather.advancedbackups.core.backups; + +public enum BackupCheckEnum { + SUCCESS, + DISABLED, + NOACTIVITY, + TOORECENT; + + public boolean success() { + switch (this) { + case SUCCESS: { + return true; + } + default : return false; + } + } + + + public String getCheckMessage() { + switch(this) { + case SUCCESS : { + return "Checks successful!"; + } + case DISABLED : { + return "Backups are disabled!"; + } + case NOACTIVITY : { + return "Player activity is required, but none have been active!"; + } + case TOORECENT : { + return "The time since the last backup is less than the minimum time specified in config!"; + } + default : { + return "You should not see this message, report a bug!"; + } + } + } +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java index d089bfbe..59b9f97f 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java @@ -29,19 +29,25 @@ public static void checkShutdownBackups() { public static void checkAndMakeBackups(long delay) { prepareBackupDestination(); - - if (!AVConfig.config.getEnabled()) return; - if (AVConfig.config.getRequireActivity() && !PlatformMethodWrapper.activity) return; - if (checkMostRecentBackup()) return; - - // Finally : - makeSingleBackup(delay); + BackupCheckEnum e = checkBackups(); + if (e.success()) { + makeSingleBackup(delay); + } } public static void checkAndMakeBackups() { checkAndMakeBackups(0); } - + + + public static BackupCheckEnum checkBackups() { + if (!AVConfig.config.getEnabled()) return BackupCheckEnum.DISABLED; + if (AVConfig.config.getRequireActivity() && !PlatformMethodWrapper.activity) return BackupCheckEnum.NOACTIVITY; + if (checkMostRecentBackup()) return BackupCheckEnum.TOORECENT; + + return BackupCheckEnum.SUCCESS; + + } private static void prepareBackupDestination() { File file = new File(AVConfig.config.getPath()); From 49c0eea798b95e291acc48c9ce7b574ffa4e1c86 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Wed, 7 Jun 2023 14:50:01 +0000 Subject: [PATCH 080/580] Update core files --- .../mommyheather/advancedbackups/core/backups/BackupWrapper.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java index 59b9f97f..7ed5e08a 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java @@ -7,6 +7,7 @@ import co.uk.mommyheather.advancedbackups.PlatformMethodWrapper; import co.uk.mommyheather.advancedbackups.core.config.AVConfig; +import co.uk.mommyheather.advancedbackups.core.backups.BackupCheckEnum; public class BackupWrapper { From c9b75b02a2d4195b4f93220f14da3c5f74a7df97 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Wed, 7 Jun 2023 14:50:03 +0000 Subject: [PATCH 081/580] Update core files --- .../mommyheather/advancedbackups/core/backups/BackupWrapper.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java index 59b9f97f..7ed5e08a 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java @@ -7,6 +7,7 @@ import co.uk.mommyheather.advancedbackups.PlatformMethodWrapper; import co.uk.mommyheather.advancedbackups.core.config.AVConfig; +import co.uk.mommyheather.advancedbackups.core.backups.BackupCheckEnum; public class BackupWrapper { From 4ccc3609997a30dc432aacf7daa26eb21ee940db Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Wed, 7 Jun 2023 14:50:05 +0000 Subject: [PATCH 082/580] Update core files --- .../mommyheather/advancedbackups/core/backups/BackupWrapper.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java index 59b9f97f..7ed5e08a 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java @@ -7,6 +7,7 @@ import co.uk.mommyheather.advancedbackups.PlatformMethodWrapper; import co.uk.mommyheather.advancedbackups.core.config.AVConfig; +import co.uk.mommyheather.advancedbackups.core.backups.BackupCheckEnum; public class BackupWrapper { From bd959c1eef36bf0db42db16caa816601d0c334ff Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Wed, 7 Jun 2023 14:50:06 +0000 Subject: [PATCH 083/580] Update core files --- .../mommyheather/advancedbackups/core/backups/BackupWrapper.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java index 59b9f97f..7ed5e08a 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java @@ -7,6 +7,7 @@ import co.uk.mommyheather.advancedbackups.PlatformMethodWrapper; import co.uk.mommyheather.advancedbackups.core.config.AVConfig; +import co.uk.mommyheather.advancedbackups.core.backups.BackupCheckEnum; public class BackupWrapper { From da03b29d8d0f0a367d5de7e11e1c25344a8ff89e Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Wed, 7 Jun 2023 14:50:07 +0000 Subject: [PATCH 084/580] Update core files --- .../mommyheather/advancedbackups/core/backups/BackupWrapper.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java index 59b9f97f..7ed5e08a 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java @@ -7,6 +7,7 @@ import co.uk.mommyheather.advancedbackups.PlatformMethodWrapper; import co.uk.mommyheather.advancedbackups.core.config.AVConfig; +import co.uk.mommyheather.advancedbackups.core.backups.BackupCheckEnum; public class BackupWrapper { From fdffebf2062d34ba5a46233020269b9407ca28b1 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Wed, 7 Jun 2023 14:51:00 +0000 Subject: [PATCH 085/580] Update core files --- .../mommyheather/advancedbackups/core/backups/BackupWrapper.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java index 7ed5e08a..59b9f97f 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java @@ -7,7 +7,6 @@ import co.uk.mommyheather.advancedbackups.PlatformMethodWrapper; import co.uk.mommyheather.advancedbackups.core.config.AVConfig; -import co.uk.mommyheather.advancedbackups.core.backups.BackupCheckEnum; public class BackupWrapper { From a7fc55fa1ac4bff740eec1a91c829f1cfe436eef Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Wed, 7 Jun 2023 14:51:01 +0000 Subject: [PATCH 086/580] Update core files --- .../mommyheather/advancedbackups/core/backups/BackupWrapper.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java index 7ed5e08a..59b9f97f 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java @@ -7,7 +7,6 @@ import co.uk.mommyheather.advancedbackups.PlatformMethodWrapper; import co.uk.mommyheather.advancedbackups.core.config.AVConfig; -import co.uk.mommyheather.advancedbackups.core.backups.BackupCheckEnum; public class BackupWrapper { From fdcbcd504787b6f806922e819329300edafaab8c Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Wed, 7 Jun 2023 14:51:03 +0000 Subject: [PATCH 087/580] Update core files --- .../mommyheather/advancedbackups/core/backups/BackupWrapper.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java index 7ed5e08a..59b9f97f 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java @@ -7,7 +7,6 @@ import co.uk.mommyheather.advancedbackups.PlatformMethodWrapper; import co.uk.mommyheather.advancedbackups.core.config.AVConfig; -import co.uk.mommyheather.advancedbackups.core.backups.BackupCheckEnum; public class BackupWrapper { From 3de1428c17cc1ebd878239e6579855d438386a72 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Wed, 7 Jun 2023 14:51:04 +0000 Subject: [PATCH 088/580] Update core files --- .../mommyheather/advancedbackups/core/backups/BackupWrapper.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java index 7ed5e08a..59b9f97f 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java @@ -7,7 +7,6 @@ import co.uk.mommyheather.advancedbackups.PlatformMethodWrapper; import co.uk.mommyheather.advancedbackups.core.config.AVConfig; -import co.uk.mommyheather.advancedbackups.core.backups.BackupCheckEnum; public class BackupWrapper { From 9cc64a41daf9025acf7349ce2b3e347c418db792 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Wed, 7 Jun 2023 14:51:05 +0000 Subject: [PATCH 089/580] Update core files --- .../mommyheather/advancedbackups/core/backups/BackupWrapper.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java index 7ed5e08a..59b9f97f 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java @@ -7,7 +7,6 @@ import co.uk.mommyheather.advancedbackups.PlatformMethodWrapper; import co.uk.mommyheather.advancedbackups.core.config.AVConfig; -import co.uk.mommyheather.advancedbackups.core.backups.BackupCheckEnum; public class BackupWrapper { From ad06e6f5f8e11809f6804988986779c64d20914f Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Wed, 7 Jun 2023 16:40:08 +0100 Subject: [PATCH 090/580] Commands! All work as expected. --- .../advancedbackups/AdvancedBackups.java | 6 +++ .../AdvancedBackupsCommand.java | 46 +++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index af6e53bf..9d35e69e 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -8,6 +8,7 @@ import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.event.RegisterCommandsEvent; import net.minecraftforge.event.entity.player.PlayerEvent; import net.minecraftforge.event.server.ServerStartedEvent; import net.minecraftforge.event.server.ServerStartingEvent; @@ -61,4 +62,9 @@ public void onPlayerJoined(PlayerEvent.PlayerLoggedInEvent event) { PlatformMethodWrapper.activity = true; } + @SubscribeEvent + public void registerCommands(RegisterCommandsEvent event){ + AdvancedBackupsCommand.register(event.getDispatcher()); + } + } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java new file mode 100644 index 00000000..b8a6c961 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -0,0 +1,46 @@ +package co.uk.mommyheather.advancedbackups; + +import com.mojang.brigadier.CommandDispatcher; + +import co.uk.mommyheather.advancedbackups.core.CoreCommandSystem; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.commands.Commands; +import net.minecraft.network.chat.TextComponent; + +public class AdvancedBackupsCommand { + public static void register(CommandDispatcher stack) { + stack.register(Commands.literal("advancedbackups").requires((runner) -> { + return runner.hasPermission(3); + }).then(Commands.literal("check").executes((runner) -> { + CoreCommandSystem.checkBackups((response) -> { + runner.getSource().sendSuccess(new TextComponent(response), true); + }); + return 1; + })) + + .then(Commands.literal("start").executes((runner) -> { + CoreCommandSystem.startBackup((response) -> { + runner.getSource().sendSuccess(new TextComponent(response), true); + }); + return 1; + })) + + .then(Commands.literal("force-backup").executes((runner) -> { + CoreCommandSystem.forceBackup((response) -> { + runner.getSource().sendSuccess(new TextComponent(response), true); + }); + return 1; + })) + + .then(Commands.literal("reload").executes((runner) -> { + CoreCommandSystem.reloadConfig((response) -> { + runner.getSource().sendSuccess(new TextComponent(response), true); + }); + return 1; + })) + + ); + } + + +} From 739a42808edb146fd8641443b5cfcab8131c5b17 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Wed, 7 Jun 2023 16:00:21 +0000 Subject: [PATCH 091/580] Update core files --- README.md | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index d23fd3a9..deda8c86 100644 --- a/README.md +++ b/README.md @@ -21,13 +21,14 @@ Many Minecraft versions are supported - request more if the one you want isn't y - Forge 1.7.10 ## Features: -Choose between zip, differential or incremental backups. -Set a schedule to backup as and when you want. -Optionally force a minimum time between backups to avoid doing so too frequently. -Backup on server startup and / or shutdown, or neither. -Set a cap to max backup sizes. -Save anywhere on disk, including network locations. -Customisable compression level. +- Choose between zip, differential or incremental backups. +- Set a schedule to backup as and when you want. +- Optionally force a minimum time between backups to avoid doing so too frequently. +- Backup on server startup and / or shutdown, or neither. +- Set a cap to max backup sizes. +- Save anywhere on disk, including network locations. +- Customisable compression level. +- Commandline restoration tool built into the jar. ## Usage: @@ -35,7 +36,7 @@ Customisable compression level. ### Ingame: \- Upon first boot, an `AdvancedBackups.properties` file will be created in your server or client root directory. -\- Adjust this to suit your needs, then restart the server or use `/AdvancedBackups reload` to reload the config. A small description of each config entry is below. +\- Adjust this to suit your needs, then restart the server or use `/advancedbackups reload` to reload the config. A small description of each config entry is below. | Config | Description | Default Value | Supported From | | ----------- | ----------- | ------------- | -------------- | @@ -60,7 +61,17 @@ Customisable compression level. #### Commands: -None currently implemented. +\- All entries in the table below must be prefixed with `/advancedbackups`. + +- Example : `/advancedbackups force-backup` + + +| Command | Description | Supported From | +| ----------- | ----------- | -------------- | +| check | Checks if a backup would be made at this point in time, and tells you the result. Does not make a backup.| next release | +| start | Starts a backup if all checks pass. Tells you check results.| next release | +| reload | Reloads the config.| next release | +| force-backup | Forces a backup without running any checks.| next release | ### Commandline: From e45ee66ae9678d50b462164da6b88a307e7300dd Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Wed, 7 Jun 2023 16:00:22 +0000 Subject: [PATCH 092/580] Update core files --- README.md | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index d23fd3a9..deda8c86 100644 --- a/README.md +++ b/README.md @@ -21,13 +21,14 @@ Many Minecraft versions are supported - request more if the one you want isn't y - Forge 1.7.10 ## Features: -Choose between zip, differential or incremental backups. -Set a schedule to backup as and when you want. -Optionally force a minimum time between backups to avoid doing so too frequently. -Backup on server startup and / or shutdown, or neither. -Set a cap to max backup sizes. -Save anywhere on disk, including network locations. -Customisable compression level. +- Choose between zip, differential or incremental backups. +- Set a schedule to backup as and when you want. +- Optionally force a minimum time between backups to avoid doing so too frequently. +- Backup on server startup and / or shutdown, or neither. +- Set a cap to max backup sizes. +- Save anywhere on disk, including network locations. +- Customisable compression level. +- Commandline restoration tool built into the jar. ## Usage: @@ -35,7 +36,7 @@ Customisable compression level. ### Ingame: \- Upon first boot, an `AdvancedBackups.properties` file will be created in your server or client root directory. -\- Adjust this to suit your needs, then restart the server or use `/AdvancedBackups reload` to reload the config. A small description of each config entry is below. +\- Adjust this to suit your needs, then restart the server or use `/advancedbackups reload` to reload the config. A small description of each config entry is below. | Config | Description | Default Value | Supported From | | ----------- | ----------- | ------------- | -------------- | @@ -60,7 +61,17 @@ Customisable compression level. #### Commands: -None currently implemented. +\- All entries in the table below must be prefixed with `/advancedbackups`. + +- Example : `/advancedbackups force-backup` + + +| Command | Description | Supported From | +| ----------- | ----------- | -------------- | +| check | Checks if a backup would be made at this point in time, and tells you the result. Does not make a backup.| next release | +| start | Starts a backup if all checks pass. Tells you check results.| next release | +| reload | Reloads the config.| next release | +| force-backup | Forces a backup without running any checks.| next release | ### Commandline: From b32e48142d6c1cb241ee3f3bf8b739bb619935a1 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Wed, 7 Jun 2023 16:00:23 +0000 Subject: [PATCH 093/580] Update core files --- README.md | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index d23fd3a9..deda8c86 100644 --- a/README.md +++ b/README.md @@ -21,13 +21,14 @@ Many Minecraft versions are supported - request more if the one you want isn't y - Forge 1.7.10 ## Features: -Choose between zip, differential or incremental backups. -Set a schedule to backup as and when you want. -Optionally force a minimum time between backups to avoid doing so too frequently. -Backup on server startup and / or shutdown, or neither. -Set a cap to max backup sizes. -Save anywhere on disk, including network locations. -Customisable compression level. +- Choose between zip, differential or incremental backups. +- Set a schedule to backup as and when you want. +- Optionally force a minimum time between backups to avoid doing so too frequently. +- Backup on server startup and / or shutdown, or neither. +- Set a cap to max backup sizes. +- Save anywhere on disk, including network locations. +- Customisable compression level. +- Commandline restoration tool built into the jar. ## Usage: @@ -35,7 +36,7 @@ Customisable compression level. ### Ingame: \- Upon first boot, an `AdvancedBackups.properties` file will be created in your server or client root directory. -\- Adjust this to suit your needs, then restart the server or use `/AdvancedBackups reload` to reload the config. A small description of each config entry is below. +\- Adjust this to suit your needs, then restart the server or use `/advancedbackups reload` to reload the config. A small description of each config entry is below. | Config | Description | Default Value | Supported From | | ----------- | ----------- | ------------- | -------------- | @@ -60,7 +61,17 @@ Customisable compression level. #### Commands: -None currently implemented. +\- All entries in the table below must be prefixed with `/advancedbackups`. + +- Example : `/advancedbackups force-backup` + + +| Command | Description | Supported From | +| ----------- | ----------- | -------------- | +| check | Checks if a backup would be made at this point in time, and tells you the result. Does not make a backup.| next release | +| start | Starts a backup if all checks pass. Tells you check results.| next release | +| reload | Reloads the config.| next release | +| force-backup | Forces a backup without running any checks.| next release | ### Commandline: From 5aa65b0b455d281b7092d071e4201359a9f18f84 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Wed, 7 Jun 2023 16:00:24 +0000 Subject: [PATCH 094/580] Update core files --- README.md | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index d23fd3a9..deda8c86 100644 --- a/README.md +++ b/README.md @@ -21,13 +21,14 @@ Many Minecraft versions are supported - request more if the one you want isn't y - Forge 1.7.10 ## Features: -Choose between zip, differential or incremental backups. -Set a schedule to backup as and when you want. -Optionally force a minimum time between backups to avoid doing so too frequently. -Backup on server startup and / or shutdown, or neither. -Set a cap to max backup sizes. -Save anywhere on disk, including network locations. -Customisable compression level. +- Choose between zip, differential or incremental backups. +- Set a schedule to backup as and when you want. +- Optionally force a minimum time between backups to avoid doing so too frequently. +- Backup on server startup and / or shutdown, or neither. +- Set a cap to max backup sizes. +- Save anywhere on disk, including network locations. +- Customisable compression level. +- Commandline restoration tool built into the jar. ## Usage: @@ -35,7 +36,7 @@ Customisable compression level. ### Ingame: \- Upon first boot, an `AdvancedBackups.properties` file will be created in your server or client root directory. -\- Adjust this to suit your needs, then restart the server or use `/AdvancedBackups reload` to reload the config. A small description of each config entry is below. +\- Adjust this to suit your needs, then restart the server or use `/advancedbackups reload` to reload the config. A small description of each config entry is below. | Config | Description | Default Value | Supported From | | ----------- | ----------- | ------------- | -------------- | @@ -60,7 +61,17 @@ Customisable compression level. #### Commands: -None currently implemented. +\- All entries in the table below must be prefixed with `/advancedbackups`. + +- Example : `/advancedbackups force-backup` + + +| Command | Description | Supported From | +| ----------- | ----------- | -------------- | +| check | Checks if a backup would be made at this point in time, and tells you the result. Does not make a backup.| next release | +| start | Starts a backup if all checks pass. Tells you check results.| next release | +| reload | Reloads the config.| next release | +| force-backup | Forces a backup without running any checks.| next release | ### Commandline: From 708987c332d98cbafa4f6c9047da09473e5e81f8 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Wed, 7 Jun 2023 16:00:26 +0000 Subject: [PATCH 095/580] Update core files --- README.md | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index d23fd3a9..deda8c86 100644 --- a/README.md +++ b/README.md @@ -21,13 +21,14 @@ Many Minecraft versions are supported - request more if the one you want isn't y - Forge 1.7.10 ## Features: -Choose between zip, differential or incremental backups. -Set a schedule to backup as and when you want. -Optionally force a minimum time between backups to avoid doing so too frequently. -Backup on server startup and / or shutdown, or neither. -Set a cap to max backup sizes. -Save anywhere on disk, including network locations. -Customisable compression level. +- Choose between zip, differential or incremental backups. +- Set a schedule to backup as and when you want. +- Optionally force a minimum time between backups to avoid doing so too frequently. +- Backup on server startup and / or shutdown, or neither. +- Set a cap to max backup sizes. +- Save anywhere on disk, including network locations. +- Customisable compression level. +- Commandline restoration tool built into the jar. ## Usage: @@ -35,7 +36,7 @@ Customisable compression level. ### Ingame: \- Upon first boot, an `AdvancedBackups.properties` file will be created in your server or client root directory. -\- Adjust this to suit your needs, then restart the server or use `/AdvancedBackups reload` to reload the config. A small description of each config entry is below. +\- Adjust this to suit your needs, then restart the server or use `/advancedbackups reload` to reload the config. A small description of each config entry is below. | Config | Description | Default Value | Supported From | | ----------- | ----------- | ------------- | -------------- | @@ -60,7 +61,17 @@ Customisable compression level. #### Commands: -None currently implemented. +\- All entries in the table below must be prefixed with `/advancedbackups`. + +- Example : `/advancedbackups force-backup` + + +| Command | Description | Supported From | +| ----------- | ----------- | -------------- | +| check | Checks if a backup would be made at this point in time, and tells you the result. Does not make a backup.| next release | +| start | Starts a backup if all checks pass. Tells you check results.| next release | +| reload | Reloads the config.| next release | +| force-backup | Forces a backup without running any checks.| next release | ### Commandline: From e42cfa4d4ceba957783655bb64af546d92d4fb04 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Thu, 8 Jun 2023 11:02:04 +0100 Subject: [PATCH 096/580] Command support! --- .../advancedbackups/AdvancedBackups.java | 6 +++ .../AdvancedBackupsCommand.java | 46 +++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index d6909c26..917c178f 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -1,6 +1,7 @@ package co.uk.mommyheather.advancedbackups; import net.fabricmc.api.ModInitializer; +import net.fabricmc.fabric.api.command.v1.CommandRegistrationCallback; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; import net.minecraft.server.MinecraftServer; @@ -47,5 +48,10 @@ public void onInitialize() { ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> { PlatformMethodWrapper.activity = true; }); + + CommandRegistrationCallback.EVENT.register((dispatcher, isDedicated) -> { + AdvancedBackupsCommand.register(dispatcher); + }); + } } \ No newline at end of file diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java new file mode 100644 index 00000000..cdd2386b --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -0,0 +1,46 @@ +package co.uk.mommyheather.advancedbackups; + +import com.mojang.brigadier.CommandDispatcher; + +import co.uk.mommyheather.advancedbackups.core.CoreCommandSystem; +import net.minecraft.server.command.CommandManager; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.text.Text; + +public class AdvancedBackupsCommand { + public static void register(CommandDispatcher stack) { + stack.register(CommandManager.literal("advancedbackups").requires((runner) -> { + return runner.hasPermissionLevel(3); + }).then(CommandManager.literal("check").executes((runner) -> { + CoreCommandSystem.checkBackups((response) -> { + runner.getSource().sendFeedback(Text.of(response), true); + }); + return 1; + })) + + .then(CommandManager.literal("start").executes((runner) -> { + CoreCommandSystem.startBackup((response) -> { + runner.getSource().sendFeedback(Text.of(response), true); + }); + return 1; + })) + + .then(CommandManager.literal("force-backup").executes((runner) -> { + CoreCommandSystem.forceBackup((response) -> { + runner.getSource().sendFeedback(Text.of(response), true); + }); + return 1; + })) + + .then(CommandManager.literal("reload").executes((runner) -> { + CoreCommandSystem.reloadConfig((response) -> { + runner.getSource().sendFeedback(Text.of(response), true); + }); + return 1; + })) + + ); + } + + +} From 3698b115cecf1c8633a4f58168dea9c7f0dfd694 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Thu, 8 Jun 2023 11:14:24 +0100 Subject: [PATCH 097/580] Command support! --- .../advancedbackups/AdvancedBackups.java | 6 +++ .../AdvancedBackupsCommand.java | 46 +++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index d97b2e3b..f77c2c0b 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -4,6 +4,7 @@ import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; import co.uk.mommyheather.advancedbackups.core.config.AVConfig; import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.RegisterCommandsEvent; import net.minecraftforge.event.entity.player.PlayerEvent.PlayerLoggedInEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod; @@ -58,4 +59,9 @@ public void onPlayerConneccted(PlayerLoggedInEvent event) { PlatformMethodWrapper.activity = true; } + @SubscribeEvent + public void registerCommands(RegisterCommandsEvent event){ + AdvancedBackupsCommand.register(event.getDispatcher()); + } + } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java new file mode 100644 index 00000000..5b06cf05 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -0,0 +1,46 @@ +package co.uk.mommyheather.advancedbackups; + +import com.mojang.brigadier.CommandDispatcher; + +import co.uk.mommyheather.advancedbackups.core.CoreCommandSystem; +import net.minecraft.command.CommandSource; +import net.minecraft.command.Commands; +import net.minecraft.util.text.StringTextComponent; + +public class AdvancedBackupsCommand { + public static void register(CommandDispatcher stack) { + stack.register(Commands.literal("advancedbackups").requires((runner) -> { + return runner.hasPermission(3); + }).then(Commands.literal("check").executes((runner) -> { + CoreCommandSystem.checkBackups((response) -> { + runner.getSource().sendSuccess(new StringTextComponent(response), true); + }); + return 1; + })) + + .then(Commands.literal("start").executes((runner) -> { + CoreCommandSystem.startBackup((response) -> { + runner.getSource().sendSuccess(new StringTextComponent(response), true); + }); + return 1; + })) + + .then(Commands.literal("force-backup").executes((runner) -> { + CoreCommandSystem.forceBackup((response) -> { + runner.getSource().sendSuccess(new StringTextComponent(response), true); + }); + return 1; + })) + + .then(Commands.literal("reload").executes((runner) -> { + CoreCommandSystem.reloadConfig((response) -> { + runner.getSource().sendSuccess(new StringTextComponent(response), true); + }); + return 1; + })) + + ); + } + + +} From bf62b43a62c611af062680f0089d577fe2517d59 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Thu, 8 Jun 2023 12:01:32 +0100 Subject: [PATCH 098/580] Command support! --- .../advancedbackups/AdvancedBackups.java | 2 + .../AdvancedBackupsCommand.java | 116 ++++++++++++++++++ 2 files changed, 118 insertions(+) create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index b1a2f4ae..8b6b231a 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -71,6 +71,8 @@ public void onServerStarting(FMLServerStartingEvent event) } server = event.getServer(); + + event.registerServerCommand(new AdvancedBackupsCommand()); } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java new file mode 100644 index 00000000..d1670b60 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -0,0 +1,116 @@ +package co.uk.mommyheather.advancedbackups; + +import co.uk.mommyheather.advancedbackups.core.CoreCommandSystem; +import net.minecraft.command.CommandException; +import net.minecraft.command.ICommand; + +import net.minecraft.command.ICommandSender; +import net.minecraft.server.MinecraftServer; +import net.minecraft.util.text.TextComponentString; +import net.minecraftforge.server.command.CommandTreeBase; + +public class AdvancedBackupsCommand extends CommandTreeBase +{ + public AdvancedBackupsCommand() + { + addSubcommand(new Check()); + addSubcommand(new Start()); + addSubcommand(new Force()); + addSubcommand(new Reload()); + } + + @Override + public String getName() + { + return "advancedbackups"; + } + + + @Override + public int getRequiredPermissionLevel() + { + return 3; + } + + @Override + public String getUsage(ICommandSender icommandsender) + { + return "/advancedbackups (check|start|force-backup|reload)"; + } + + public static class Check extends CommandTreeBase { + public Check(){} + @Override + public void execute(MinecraftServer server, ICommandSender sender, String[] args) throws CommandException { + CoreCommandSystem.checkBackups((response) -> { + sender.sendMessage(new TextComponentString(response)); + }); + } + @Override + public String getName() + { + return "check"; + } + @Override + public String getUsage(ICommandSender sender) { + return "commands.advancedbackups.check.usage"; + } + } + + public static class Force extends CommandTreeBase { + public Force(){} + @Override + public void execute(MinecraftServer server, ICommandSender sender, String[] args) throws CommandException { + CoreCommandSystem.forceBackup((response) -> { + sender.sendMessage(new TextComponentString(response)); + }); + } + @Override + public String getName() + { + return "force-backup"; + } + @Override + public String getUsage(ICommandSender sender) { + return "commands.advancedbackups.force.usage"; + } + } + + public static class Reload extends CommandTreeBase { + public Reload(){} + @Override + public void execute(MinecraftServer server, ICommandSender sender, String[] args) throws CommandException { + CoreCommandSystem.reloadConfig((response) -> { + sender.sendMessage(new TextComponentString(response)); + }); + } + @Override + public String getName() + { + return "reload"; + } + @Override + public String getUsage(ICommandSender sender) { + return "commands.advancedbackups.reload.usage"; + } + } + + public static class Start extends CommandTreeBase { + public Start(){} + @Override + public void execute(MinecraftServer server, ICommandSender sender, String[] args) throws CommandException { + CoreCommandSystem.startBackup((response) -> { + sender.sendMessage(new TextComponentString(response)); + }); + } + @Override + public String getName() + { + return "start"; + } + @Override + public String getUsage(ICommandSender sender) { + return "commands.advancedbackups.start.usage"; + } + } +} From 835eedc99e5c78c34cb905596b2701f722be8057 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Thu, 8 Jun 2023 12:24:49 +0100 Subject: [PATCH 099/580] Command support! --- .../advancedbackups/AdvancedBackups.java | 2 + .../AdvancedBackupsCommand.java | 101 ++++++++++++++++++ 2 files changed, 103 insertions(+) create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index f1f64d69..0f514d4c 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -73,6 +73,8 @@ public void onServerStarting(FMLServerStartingEvent event) } server = event.getServer(); + + event.registerServerCommand(new AdvancedBackupsCommand()); } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java new file mode 100644 index 00000000..ad2e513e --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -0,0 +1,101 @@ +package co.uk.mommyheather.advancedbackups; + +import co.uk.mommyheather.advancedbackups.core.CoreCommandSystem; +import net.minecraft.command.CommandBase; +import net.minecraft.command.CommandException; +import net.minecraft.command.ICommand; + +import net.minecraft.command.ICommandSender; +import net.minecraft.command.WrongUsageException; +import net.minecraft.server.MinecraftServer; +import net.minecraft.util.ChatComponentText; + +public class AdvancedBackupsCommand extends CommandBase +{ + public AdvancedBackupsCommand() + { + /*addSubcommand(new Check()); + addSubcommand(new Start()); + addSubcommand(new Force()); + addSubcommand(new Reload());*/ + } + + @Override + public String getCommandName() + { + return "advancedbackups"; + } + + + @Override + public int getRequiredPermissionLevel() + { + return 3; + } + + public String getCommandUsage(ICommandSender icommandsender) + { + return "/advancedbackups (check|start|force-backup|reload)"; + } + + + @Override + public void processCommand(ICommandSender sender, String[] args) throws CommandException { + if (args.length == 0) + { + throw new WrongUsageException(getCommandUsage(sender)); + } + else if ("check".equals(args[0])) + { + Check.execute(sender); + } + else if ("start".equals(args[0])) + { + Start.execute(sender); + } + else if ("force-backup".equals(args[0])) + { + Force.execute(sender); + } + else if ("reload".equals(args[0])) + { + Reload.execute(sender); + } + else + { + throw new WrongUsageException(getCommandUsage(sender)); + } + } + + public static class Check { + static public void execute(ICommandSender sender) { + CoreCommandSystem.checkBackups((response) -> { + sender.addChatMessage(new ChatComponentText(response)); + }); + } + } + public static class Force { + public static void execute(ICommandSender sender) { + CoreCommandSystem.forceBackup((response) -> { + sender.addChatMessage(new ChatComponentText(response)); + }); + } + } + public static class Reload { + public static void execute(ICommandSender sender) { + CoreCommandSystem.reloadConfig((response) -> { + sender.addChatMessage(new ChatComponentText(response)); + }); + } + } + + public static class Start { + public static void execute(ICommandSender sender) { + CoreCommandSystem.startBackup((response) -> { + sender.addChatMessage(new ChatComponentText(response)); + }); + } + } + + +} From a89acface8be26ce2d1c85b0e771a2e6203b5d4c Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Thu, 8 Jun 2023 15:23:17 +0000 Subject: [PATCH 100/580] Update core files --- README.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index deda8c86..378e8a63 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,5 @@ # Advanced Backups -# Note - early release. Some features here aren't implemented yet, and not all features are documented. A powerful backup mod for Minecraft, supporting Forge and Fabric. Many Minecraft versions are supported - request more if the one you want isn't yet supported. @@ -41,7 +40,7 @@ Many Minecraft versions are supported - request more if the one you want isn't y | Config | Description | Default Value | Supported From | | ----------- | ----------- | ------------- | -------------- | | config.advancedbackups.enabled | Enable or disable backups entirely. | true | 0.3 | -| config.advancedbackups.activity | Enable or disable player activity requirements. | false | next release | +| config.advancedbackups.activity | Enable or disable player activity requirements. | false | 1.0 | | config.advancedbackups.save | Whether to save before making a backup. | false | 0.3 | | config.advancedbackups.type | Whether to use zip, differential or incremental backups. | differential | 0.3 | | config.advancedbackups.path | The relative or absolute location where backups are stored. | ./backups | 0.3 | @@ -68,10 +67,10 @@ Many Minecraft versions are supported - request more if the one you want isn't y | Command | Description | Supported From | | ----------- | ----------- | -------------- | -| check | Checks if a backup would be made at this point in time, and tells you the result. Does not make a backup.| next release | -| start | Starts a backup if all checks pass. Tells you check results.| next release | -| reload | Reloads the config.| next release | -| force-backup | Forces a backup without running any checks.| next release | +| check | Checks if a backup would be made at this point in time, and tells you the result. Does not make a backup.| 1.0 | +| start | Starts a backup if all checks pass. Tells you check results.| 1.0 | +| reload | Reloads the config.| 1.0 | +| force-backup | Forces a backup without running any checks.| 1.0 | ### Commandline: From 391bfc51526edcdce20ae2ba61a099cb08463df2 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Thu, 8 Jun 2023 15:23:18 +0000 Subject: [PATCH 101/580] Update core files --- README.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index deda8c86..378e8a63 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,5 @@ # Advanced Backups -# Note - early release. Some features here aren't implemented yet, and not all features are documented. A powerful backup mod for Minecraft, supporting Forge and Fabric. Many Minecraft versions are supported - request more if the one you want isn't yet supported. @@ -41,7 +40,7 @@ Many Minecraft versions are supported - request more if the one you want isn't y | Config | Description | Default Value | Supported From | | ----------- | ----------- | ------------- | -------------- | | config.advancedbackups.enabled | Enable or disable backups entirely. | true | 0.3 | -| config.advancedbackups.activity | Enable or disable player activity requirements. | false | next release | +| config.advancedbackups.activity | Enable or disable player activity requirements. | false | 1.0 | | config.advancedbackups.save | Whether to save before making a backup. | false | 0.3 | | config.advancedbackups.type | Whether to use zip, differential or incremental backups. | differential | 0.3 | | config.advancedbackups.path | The relative or absolute location where backups are stored. | ./backups | 0.3 | @@ -68,10 +67,10 @@ Many Minecraft versions are supported - request more if the one you want isn't y | Command | Description | Supported From | | ----------- | ----------- | -------------- | -| check | Checks if a backup would be made at this point in time, and tells you the result. Does not make a backup.| next release | -| start | Starts a backup if all checks pass. Tells you check results.| next release | -| reload | Reloads the config.| next release | -| force-backup | Forces a backup without running any checks.| next release | +| check | Checks if a backup would be made at this point in time, and tells you the result. Does not make a backup.| 1.0 | +| start | Starts a backup if all checks pass. Tells you check results.| 1.0 | +| reload | Reloads the config.| 1.0 | +| force-backup | Forces a backup without running any checks.| 1.0 | ### Commandline: From 085f35e9313fdffbfa2da66faf5ec04d361d8018 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Thu, 8 Jun 2023 15:23:19 +0000 Subject: [PATCH 102/580] Update core files --- README.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index deda8c86..378e8a63 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,5 @@ # Advanced Backups -# Note - early release. Some features here aren't implemented yet, and not all features are documented. A powerful backup mod for Minecraft, supporting Forge and Fabric. Many Minecraft versions are supported - request more if the one you want isn't yet supported. @@ -41,7 +40,7 @@ Many Minecraft versions are supported - request more if the one you want isn't y | Config | Description | Default Value | Supported From | | ----------- | ----------- | ------------- | -------------- | | config.advancedbackups.enabled | Enable or disable backups entirely. | true | 0.3 | -| config.advancedbackups.activity | Enable or disable player activity requirements. | false | next release | +| config.advancedbackups.activity | Enable or disable player activity requirements. | false | 1.0 | | config.advancedbackups.save | Whether to save before making a backup. | false | 0.3 | | config.advancedbackups.type | Whether to use zip, differential or incremental backups. | differential | 0.3 | | config.advancedbackups.path | The relative or absolute location where backups are stored. | ./backups | 0.3 | @@ -68,10 +67,10 @@ Many Minecraft versions are supported - request more if the one you want isn't y | Command | Description | Supported From | | ----------- | ----------- | -------------- | -| check | Checks if a backup would be made at this point in time, and tells you the result. Does not make a backup.| next release | -| start | Starts a backup if all checks pass. Tells you check results.| next release | -| reload | Reloads the config.| next release | -| force-backup | Forces a backup without running any checks.| next release | +| check | Checks if a backup would be made at this point in time, and tells you the result. Does not make a backup.| 1.0 | +| start | Starts a backup if all checks pass. Tells you check results.| 1.0 | +| reload | Reloads the config.| 1.0 | +| force-backup | Forces a backup without running any checks.| 1.0 | ### Commandline: From ccd1604516d98b26179966197a79a67131bdd2d2 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Thu, 8 Jun 2023 15:23:20 +0000 Subject: [PATCH 103/580] Update core files --- README.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index deda8c86..378e8a63 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,5 @@ # Advanced Backups -# Note - early release. Some features here aren't implemented yet, and not all features are documented. A powerful backup mod for Minecraft, supporting Forge and Fabric. Many Minecraft versions are supported - request more if the one you want isn't yet supported. @@ -41,7 +40,7 @@ Many Minecraft versions are supported - request more if the one you want isn't y | Config | Description | Default Value | Supported From | | ----------- | ----------- | ------------- | -------------- | | config.advancedbackups.enabled | Enable or disable backups entirely. | true | 0.3 | -| config.advancedbackups.activity | Enable or disable player activity requirements. | false | next release | +| config.advancedbackups.activity | Enable or disable player activity requirements. | false | 1.0 | | config.advancedbackups.save | Whether to save before making a backup. | false | 0.3 | | config.advancedbackups.type | Whether to use zip, differential or incremental backups. | differential | 0.3 | | config.advancedbackups.path | The relative or absolute location where backups are stored. | ./backups | 0.3 | @@ -68,10 +67,10 @@ Many Minecraft versions are supported - request more if the one you want isn't y | Command | Description | Supported From | | ----------- | ----------- | -------------- | -| check | Checks if a backup would be made at this point in time, and tells you the result. Does not make a backup.| next release | -| start | Starts a backup if all checks pass. Tells you check results.| next release | -| reload | Reloads the config.| next release | -| force-backup | Forces a backup without running any checks.| next release | +| check | Checks if a backup would be made at this point in time, and tells you the result. Does not make a backup.| 1.0 | +| start | Starts a backup if all checks pass. Tells you check results.| 1.0 | +| reload | Reloads the config.| 1.0 | +| force-backup | Forces a backup without running any checks.| 1.0 | ### Commandline: From 646f16110ef0510904d3b4674690b48d1fc42766 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Thu, 8 Jun 2023 15:23:21 +0000 Subject: [PATCH 104/580] Update core files --- README.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index deda8c86..378e8a63 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,5 @@ # Advanced Backups -# Note - early release. Some features here aren't implemented yet, and not all features are documented. A powerful backup mod for Minecraft, supporting Forge and Fabric. Many Minecraft versions are supported - request more if the one you want isn't yet supported. @@ -41,7 +40,7 @@ Many Minecraft versions are supported - request more if the one you want isn't y | Config | Description | Default Value | Supported From | | ----------- | ----------- | ------------- | -------------- | | config.advancedbackups.enabled | Enable or disable backups entirely. | true | 0.3 | -| config.advancedbackups.activity | Enable or disable player activity requirements. | false | next release | +| config.advancedbackups.activity | Enable or disable player activity requirements. | false | 1.0 | | config.advancedbackups.save | Whether to save before making a backup. | false | 0.3 | | config.advancedbackups.type | Whether to use zip, differential or incremental backups. | differential | 0.3 | | config.advancedbackups.path | The relative or absolute location where backups are stored. | ./backups | 0.3 | @@ -68,10 +67,10 @@ Many Minecraft versions are supported - request more if the one you want isn't y | Command | Description | Supported From | | ----------- | ----------- | -------------- | -| check | Checks if a backup would be made at this point in time, and tells you the result. Does not make a backup.| next release | -| start | Starts a backup if all checks pass. Tells you check results.| next release | -| reload | Reloads the config.| next release | -| force-backup | Forces a backup without running any checks.| next release | +| check | Checks if a backup would be made at this point in time, and tells you the result. Does not make a backup.| 1.0 | +| start | Starts a backup if all checks pass. Tells you check results.| 1.0 | +| reload | Reloads the config.| 1.0 | +| force-backup | Forces a backup without running any checks.| 1.0 | ### Commandline: From d497e266dc2d0f1f00291b22673080a036724910 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Fri, 9 Jun 2023 12:03:20 +0000 Subject: [PATCH 105/580] Update core files --- README.md | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/README.md b/README.md index 378e8a63..ff837637 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,8 @@ Many Minecraft versions are supported - request more if the one you want isn't y [Command Line Usage](#commandline) +[Future Plans](#future-plans) + ## Current Versions: - Forge 1.18 - Fabric 1.18 @@ -113,3 +115,51 @@ Once you select a file, it will be restored. The program will then exit. ![image](https://github.com/MommyHeather/AdvancedBackups/assets/66441550/7a2c5d4c-e8db-48c3-8353-46486b9f86b3) + + +# Future Plans: +- Note : these are in no particular order. +- [Profiles](profiles) +- [More Commands](more-commands) +- [Client Feedback](client-feedback) + +## Profiles + +- Profiles plan to allow one server to have several backup configs active at once. +- Say, take an incremental backup every day, but make sure a zip backup is made at least once a week. +- Or maybe, you want to save a differential backup every hour on a remote drive, but keep a full-world zip backup ready locally every 24 hours. + +### Profiles can do this! + +Essentially, profiles will be an optional set of additional configs. + +These are completely separate - meaning they will not interfere with one another, at all. +- Certain values, such as min and max, may have problems if two profiles use the same location and backup type. I am not sure if I will fix this yet. + +The profile system will not be compatible with versions that predate its release. +- Backups themselves will be unaffected, and any version will be able to restore them. +- The backup location detection however may not work if your restoration cli predates the profile release. + +Upon first load with a version updated to use profiles, a default profile will be made. +- If you have a config present from an older version, the changes you made will be automatically applied to the default profile for you. +- *This means that a user who does not wish to use profiles will not be affected whatsoever. They can edit the default profile as they would with a standard config.* + + +## More commands + +Shortly after release, I wish to add more commands. + +- Config editing on the fly +- One-off backup types + - Currently, the `start` and `force-backup` commands only allow you to make a backup of the type specified in config. This will change. + + +## Client feedback + +Having some client feedback would allow connected clients that have the mod view backup progress. +- This should be toggleable in config. +- A config option to only show progress to ops should exist. + +This might be in the form of either a progress bar, or a simple percentage. + +Clients with the mod should have a way to opt out of this. From f24c79d3daa98f57810ae14b5c0118d8b13eb4ac Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Fri, 9 Jun 2023 12:03:22 +0000 Subject: [PATCH 106/580] Update core files --- README.md | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/README.md b/README.md index 378e8a63..ff837637 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,8 @@ Many Minecraft versions are supported - request more if the one you want isn't y [Command Line Usage](#commandline) +[Future Plans](#future-plans) + ## Current Versions: - Forge 1.18 - Fabric 1.18 @@ -113,3 +115,51 @@ Once you select a file, it will be restored. The program will then exit. ![image](https://github.com/MommyHeather/AdvancedBackups/assets/66441550/7a2c5d4c-e8db-48c3-8353-46486b9f86b3) + + +# Future Plans: +- Note : these are in no particular order. +- [Profiles](profiles) +- [More Commands](more-commands) +- [Client Feedback](client-feedback) + +## Profiles + +- Profiles plan to allow one server to have several backup configs active at once. +- Say, take an incremental backup every day, but make sure a zip backup is made at least once a week. +- Or maybe, you want to save a differential backup every hour on a remote drive, but keep a full-world zip backup ready locally every 24 hours. + +### Profiles can do this! + +Essentially, profiles will be an optional set of additional configs. + +These are completely separate - meaning they will not interfere with one another, at all. +- Certain values, such as min and max, may have problems if two profiles use the same location and backup type. I am not sure if I will fix this yet. + +The profile system will not be compatible with versions that predate its release. +- Backups themselves will be unaffected, and any version will be able to restore them. +- The backup location detection however may not work if your restoration cli predates the profile release. + +Upon first load with a version updated to use profiles, a default profile will be made. +- If you have a config present from an older version, the changes you made will be automatically applied to the default profile for you. +- *This means that a user who does not wish to use profiles will not be affected whatsoever. They can edit the default profile as they would with a standard config.* + + +## More commands + +Shortly after release, I wish to add more commands. + +- Config editing on the fly +- One-off backup types + - Currently, the `start` and `force-backup` commands only allow you to make a backup of the type specified in config. This will change. + + +## Client feedback + +Having some client feedback would allow connected clients that have the mod view backup progress. +- This should be toggleable in config. +- A config option to only show progress to ops should exist. + +This might be in the form of either a progress bar, or a simple percentage. + +Clients with the mod should have a way to opt out of this. From d4cdc0ce0048965f6ef1c92996416bc072d9d299 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Fri, 9 Jun 2023 12:03:23 +0000 Subject: [PATCH 107/580] Update core files --- README.md | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/README.md b/README.md index 378e8a63..ff837637 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,8 @@ Many Minecraft versions are supported - request more if the one you want isn't y [Command Line Usage](#commandline) +[Future Plans](#future-plans) + ## Current Versions: - Forge 1.18 - Fabric 1.18 @@ -113,3 +115,51 @@ Once you select a file, it will be restored. The program will then exit. ![image](https://github.com/MommyHeather/AdvancedBackups/assets/66441550/7a2c5d4c-e8db-48c3-8353-46486b9f86b3) + + +# Future Plans: +- Note : these are in no particular order. +- [Profiles](profiles) +- [More Commands](more-commands) +- [Client Feedback](client-feedback) + +## Profiles + +- Profiles plan to allow one server to have several backup configs active at once. +- Say, take an incremental backup every day, but make sure a zip backup is made at least once a week. +- Or maybe, you want to save a differential backup every hour on a remote drive, but keep a full-world zip backup ready locally every 24 hours. + +### Profiles can do this! + +Essentially, profiles will be an optional set of additional configs. + +These are completely separate - meaning they will not interfere with one another, at all. +- Certain values, such as min and max, may have problems if two profiles use the same location and backup type. I am not sure if I will fix this yet. + +The profile system will not be compatible with versions that predate its release. +- Backups themselves will be unaffected, and any version will be able to restore them. +- The backup location detection however may not work if your restoration cli predates the profile release. + +Upon first load with a version updated to use profiles, a default profile will be made. +- If you have a config present from an older version, the changes you made will be automatically applied to the default profile for you. +- *This means that a user who does not wish to use profiles will not be affected whatsoever. They can edit the default profile as they would with a standard config.* + + +## More commands + +Shortly after release, I wish to add more commands. + +- Config editing on the fly +- One-off backup types + - Currently, the `start` and `force-backup` commands only allow you to make a backup of the type specified in config. This will change. + + +## Client feedback + +Having some client feedback would allow connected clients that have the mod view backup progress. +- This should be toggleable in config. +- A config option to only show progress to ops should exist. + +This might be in the form of either a progress bar, or a simple percentage. + +Clients with the mod should have a way to opt out of this. From 86ee45ea59714c6bf82929c98700c5726a3ff6ee Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Fri, 9 Jun 2023 12:03:24 +0000 Subject: [PATCH 108/580] Update core files --- README.md | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/README.md b/README.md index 378e8a63..ff837637 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,8 @@ Many Minecraft versions are supported - request more if the one you want isn't y [Command Line Usage](#commandline) +[Future Plans](#future-plans) + ## Current Versions: - Forge 1.18 - Fabric 1.18 @@ -113,3 +115,51 @@ Once you select a file, it will be restored. The program will then exit. ![image](https://github.com/MommyHeather/AdvancedBackups/assets/66441550/7a2c5d4c-e8db-48c3-8353-46486b9f86b3) + + +# Future Plans: +- Note : these are in no particular order. +- [Profiles](profiles) +- [More Commands](more-commands) +- [Client Feedback](client-feedback) + +## Profiles + +- Profiles plan to allow one server to have several backup configs active at once. +- Say, take an incremental backup every day, but make sure a zip backup is made at least once a week. +- Or maybe, you want to save a differential backup every hour on a remote drive, but keep a full-world zip backup ready locally every 24 hours. + +### Profiles can do this! + +Essentially, profiles will be an optional set of additional configs. + +These are completely separate - meaning they will not interfere with one another, at all. +- Certain values, such as min and max, may have problems if two profiles use the same location and backup type. I am not sure if I will fix this yet. + +The profile system will not be compatible with versions that predate its release. +- Backups themselves will be unaffected, and any version will be able to restore them. +- The backup location detection however may not work if your restoration cli predates the profile release. + +Upon first load with a version updated to use profiles, a default profile will be made. +- If you have a config present from an older version, the changes you made will be automatically applied to the default profile for you. +- *This means that a user who does not wish to use profiles will not be affected whatsoever. They can edit the default profile as they would with a standard config.* + + +## More commands + +Shortly after release, I wish to add more commands. + +- Config editing on the fly +- One-off backup types + - Currently, the `start` and `force-backup` commands only allow you to make a backup of the type specified in config. This will change. + + +## Client feedback + +Having some client feedback would allow connected clients that have the mod view backup progress. +- This should be toggleable in config. +- A config option to only show progress to ops should exist. + +This might be in the form of either a progress bar, or a simple percentage. + +Clients with the mod should have a way to opt out of this. From c8844f673d8781694a7f9f2b584e275d40e7079e Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Fri, 9 Jun 2023 12:03:25 +0000 Subject: [PATCH 109/580] Update core files --- README.md | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/README.md b/README.md index 378e8a63..ff837637 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,8 @@ Many Minecraft versions are supported - request more if the one you want isn't y [Command Line Usage](#commandline) +[Future Plans](#future-plans) + ## Current Versions: - Forge 1.18 - Fabric 1.18 @@ -113,3 +115,51 @@ Once you select a file, it will be restored. The program will then exit. ![image](https://github.com/MommyHeather/AdvancedBackups/assets/66441550/7a2c5d4c-e8db-48c3-8353-46486b9f86b3) + + +# Future Plans: +- Note : these are in no particular order. +- [Profiles](profiles) +- [More Commands](more-commands) +- [Client Feedback](client-feedback) + +## Profiles + +- Profiles plan to allow one server to have several backup configs active at once. +- Say, take an incremental backup every day, but make sure a zip backup is made at least once a week. +- Or maybe, you want to save a differential backup every hour on a remote drive, but keep a full-world zip backup ready locally every 24 hours. + +### Profiles can do this! + +Essentially, profiles will be an optional set of additional configs. + +These are completely separate - meaning they will not interfere with one another, at all. +- Certain values, such as min and max, may have problems if two profiles use the same location and backup type. I am not sure if I will fix this yet. + +The profile system will not be compatible with versions that predate its release. +- Backups themselves will be unaffected, and any version will be able to restore them. +- The backup location detection however may not work if your restoration cli predates the profile release. + +Upon first load with a version updated to use profiles, a default profile will be made. +- If you have a config present from an older version, the changes you made will be automatically applied to the default profile for you. +- *This means that a user who does not wish to use profiles will not be affected whatsoever. They can edit the default profile as they would with a standard config.* + + +## More commands + +Shortly after release, I wish to add more commands. + +- Config editing on the fly +- One-off backup types + - Currently, the `start` and `force-backup` commands only allow you to make a backup of the type specified in config. This will change. + + +## Client feedback + +Having some client feedback would allow connected clients that have the mod view backup progress. +- This should be toggleable in config. +- A config option to only show progress to ops should exist. + +This might be in the form of either a progress bar, or a simple percentage. + +Clients with the mod should have a way to opt out of this. From 3370a73e4e00472039044637d496d5973f7b6d95 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Thu, 15 Jun 2023 14:34:10 +0000 Subject: [PATCH 110/580] Update core files --- .../advancedbackups/core/config/AVConfig.java | 94 +++++++++++++++---- .../core/config/ConfigData.java | 48 ++++++---- 2 files changed, 106 insertions(+), 36 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java index 71d3f511..5c01cd92 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java @@ -7,10 +7,34 @@ import java.util.ArrayList; import java.util.Properties; +import co.uk.mommyheather.advancedbackups.PlatformMethodWrapper; import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; public class AVConfig { + private static final String[] supportedProps = { + "config.advancedbackups.enabled", + "config.advancedbackups.save", + "config.advancedbackups.activity", + "config.advancedbackups.type", + "config.advancedbackups.path", + "config.advancedbackups.size", + "config.advancedbackups.frequency.min", + "config.advancedbackups.frequency.max", + "config.advancedbackups.frequency.uptime", + "config.advancedbackups.frequency.schedule", + "config.advancedbackups.frequency.shutdown", + "config.advancedbackups.frequency.startup", + "config.advancedbackups.frequency.delay", + "config.advancedbackups.logging.silent", + + "config.advancedbackups.zips.compression", + + "config.advancedbackups.chains.length", + "config.advancedbackups.chains.compress", + "config.advancedbackups.chains.smart" + + }; public static ConfigData config; @@ -61,25 +85,26 @@ public static void loadConfig() { config = new ConfigData(); - config.setEnabled(props.getProperty("config.advancedbackups.enabled")); - config.setSave(props.getProperty("config.advancedbackups.save")); - config.setRequireActivity(props.getProperty("config.advancedbackups.activity")); - config.setBackupType(props.getProperty("config.advancedbackups.type")); - config.setPath(props.getProperty("config.advancedbackups.path")); - config.setMaxSize(props.getProperty("config.advancedbackups.size")); - config.setMinTimer(props.getProperty("config.advancedbackups.frequency.min")); - config.setMaxTimer(props.getProperty("config.advancedbackups.frequency.max")); - config.setUptimeSchedule(props.getProperty("config.advancedbackups.frequency.uptime")); - config.setSchedule(props.getProperty("config.advancedbackups.frequency.schedule")); - config.setForceOnShutdown(props.getProperty("config.advancedbackups.frequency.shutdown")); - config.setForceOnStartup(props.getProperty("config.advancedbackups.frequency.startup")); - config.setStartupDelay(props.getProperty("config.advancedbackups.frequency.delay")); - config.setSilent(props.getProperty("config.advancedbackups.logging.silent")); + config.setEnabled(props.getProperty("config.advancedbackups.enabled", "true")); + config.setSave(props.getProperty("config.advancedbackups.save", "false")); + config.setRequireActivity(props.getProperty("config.advancedbackups.activity", "false")); + config.setBackupType(props.getProperty("config.advancedbackups.type", "differential")); + config.setPath(props.getProperty("config.advancedbackups.path", "./backups")); + config.setMaxSize(props.getProperty("config.advancedbackups.size", "50")); + config.setMinTimer(props.getProperty("config.advancedbackups.frequency.min", "0.5")); + config.setMaxTimer(props.getProperty("config.advancedbackups.frequency.max", "24")); + config.setUptimeSchedule(props.getProperty("config.advancedbackups.frequency.uptime", "true")); + config.setSchedule(props.getProperty("config.advancedbackups.frequency.schedule", "12:00")); + config.setForceOnShutdown(props.getProperty("config.advancedbackups.frequency.shutdown", "false")); + config.setForceOnStartup(props.getProperty("config.advancedbackups.frequency.startup", "false")); + config.setStartupDelay(props.getProperty("config.advancedbackups.frequency.delay", "5")); + config.setSilent(props.getProperty("config.advancedbackups.logging.silent", "false")); - config.setCompressionLevel(props.getProperty("config.advancedbackups.zips.compression")); + config.setCompressionLevel(props.getProperty("config.advancedbackups.zips.compression", "5")); - config.setMaxDepth(props.getProperty("config.advancedbackups.chains.length")); - config.setCompressChains(props.getProperty("config.advancedbackups.chains.compress")); + config.setMaxDepth(props.getProperty("config.advancedbackups.chains.length", "50")); + config.setCompressChains(props.getProperty("config.advancedbackups.chains.compress", "true")); + config.setSmartChains(props.getProperty("config.advancedbackups.chains.smart", "true")); @@ -94,6 +119,41 @@ public static void loadConfig() { } } + boolean flag = false; + + for (String prop : supportedProps) { + if (!props.containsKey(prop)) { + flag = true; + break; + } + } + + if (flag) { + PlatformMethodWrapper.warningLogger.accept("Broken, incomplete or misising config found! Generating new file whilst preserving any existing config values..."); + + File newPropsFile = new File("./AdvancedBackups.properties"); + try { + if (!newPropsFile.exists()) { + newPropsFile.createNewFile(); + } + FileWriter writer = new FileWriter(newPropsFile); + writer.write(String.format(ConfigData.plainConfig, config.getEnabled(), + config.getSave(), config.getRequireActivity(), config.getBackupType(), + config.getPath(), config.getMaxSize(), config.getMinTimer(), + config.getMaxTimer(), config.getUptimeSchedule(), config.getSchedule(), + config.getForceOnShutdown(), config.getStartupDelay(), config.getStartupDelay(), + config.getSilent(), config.getCompressionLevel(), config.getMaxDepth(), + config.getCompressChains(), config.getSmartChains() + )); + writer.close(); + } catch (IOException e) { + // TODO : Scream to user + e.printStackTrace(); + + } + loadConfig(); + } + } } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java index ad9788ad..3b8b8d0e 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java @@ -1,5 +1,7 @@ package co.uk.mommyheather.advancedbackups.core.config; +import org.checkerframework.checker.units.qual.m; + public class ConfigData { private Boolean enabled; @@ -223,43 +225,43 @@ public void setSmartChains(String smartChains) { //default config output - can be ignored - public static final String defaults = String.join("\n", + public static final String plainConfig = String.join("\n", "#Enable or disable automatic backups.", "#Options : true, false #Default : true,", -"config.advancedbackups.enabled=true", +"config.advancedbackups.enabled=%s", "", "#Whether to save before making a backup.", "#Options : true, false #Default : false", -"config.advancedbackups.save=false", +"config.advancedbackups.save=%s", "", "#Whether to require player activity between backups.", "#Options : true, false #Default : false", -"config.advancedbackups.activity=false", +"config.advancedbackups.activity=%s", "", "#The type of backups to use.", "#Options : zip, differential, incremental #Default : differential", -"config.advancedbackups.type=differential", +"config.advancedbackups.type=%s", "", "#The absolute or relative path to the backup location.", "#Options : any file path. Default : ./backups", -"config.advancedbackups.path=./backups", +"config.advancedbackups.path=%s", "", "#The maximum size to keep, in GB. Keep relatively high for zips, tighter space requirements should instead use differential or incremental backups.", "#Range : 5 - 9999 #Default : 50", -"config.advancedbackups.size=50", +"config.advancedbackups.size=%s", "", "#Minimum time between backups, in hours. This can prevent a shutdown backup from triggering immediately after a scheduled backup or similar situations.", "#Range : 0.5 - 500 #Default : 0.5", -"config.advancedbackups.frequency.min=0.5", +"config.advancedbackups.frequency.min=%s", "", "#Triggers a backup if none has already happened within this time. Can be combined with an uptime-based schedule.", "#Range : 0.5 - 500 #Default : 24", -"config.advancedbackups.frequency.max=24", +"config.advancedbackups.frequency.max=%s", "", "#Whether the schedule below uses uptime (true) or real-world time (false).", "#Default : true", -"config.advancedbackups.frequency.uptime=true", +"config.advancedbackups.frequency.uptime=%s", "", "#When using server uptime:", " #A looping comma-separated backup schedule, based off of server uptime, hours:minutes. Examples:", @@ -274,23 +276,23 @@ public void setSmartChains(String smartChains) { " #4:00,8:00,12:00,16:00,17:00,18:00,19:00,20:00,21:00,24:00 - Makes a backup at specific times of day.", "", "#Default : 12:00", -"config.advancedbackups.frequency.schedule=12:00", +"config.advancedbackups.frequency.schedule=%s", "", "#Whether to force a backup on server shutdown. Respects min frequency.", "#Options : true, false #Default : false", -"config.advancedbackups.frequency.shutdown=false", +"config.advancedbackups.frequency.shutdown=%s", "", "#Whether to force a backup on server startup. Respects min frequency.", "#Options : true, false #Default : false", -"config.advancedbackups.frequency.startup=false", +"config.advancedbackups.frequency.startup=%s", "", "#Delay to use after startup, in seconds. Is always at least 5 seconds.", "#Range : 5-9999999999", -"config.advancedbackups.frequency.delay=5", +"config.advancedbackups.frequency.delay=%s", "", "#Whether to disable console and chat logging. Does not affect debug.log, does not affect error messages.", "#Options : true, false #Default : false", -"config.advancedbackups.logging.silent=false", +"config.advancedbackups.logging.silent=%s", "", "", "", @@ -300,7 +302,7 @@ public void setSmartChains(String smartChains) { "", "#The compression level to use for zip files. Higher numbers space usage, but decrease performance.", "#Range : 1-9 #Default : 4", -"config.advancedbackups.zips.compression=4", +"config.advancedbackups.zips.compression=%s", "", "", "", @@ -310,15 +312,23 @@ public void setSmartChains(String smartChains) { "", "#The maximum 'chain' length to keep.", "#Range : 5-500 #Default : 50", -"config.advancedbackups.chains.length=50", +"config.advancedbackups.chains.length=%s", "", "#Whether to compress 'chains'. This compresses the base backup and all sequential backups. Reduces space usage, but decreases performance.", "#Options : true, false #Default : true", -"config.advancedbackups.chains.compress=true", +"config.advancedbackups.chains.compress=%s", "", "#Whether to enable \"smart\" reset for chains - if every file is being backed up, mark the backup as complete and reset chain length regardless of intended backup type.", "#Options : true, false #Default : true", -"config.advancedbackups.chains.smart=true" +"config.advancedbackups.chains.smart=%s" ); + public static final String defaults = String.format(plainConfig, + "true", "false", "false", + "differential", "./backups", "50", + "0.5", "24", "true", + "12:00", "false", "false", + "5", "false", "4", + "50", "true", "true"); + } From 51d7bd54ab870569fb6700bfc41fd6fb567be90d Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Thu, 15 Jun 2023 14:34:11 +0000 Subject: [PATCH 111/580] Update core files --- .../advancedbackups/core/config/AVConfig.java | 94 +++++++++++++++---- .../core/config/ConfigData.java | 48 ++++++---- 2 files changed, 106 insertions(+), 36 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java index 71d3f511..5c01cd92 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java @@ -7,10 +7,34 @@ import java.util.ArrayList; import java.util.Properties; +import co.uk.mommyheather.advancedbackups.PlatformMethodWrapper; import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; public class AVConfig { + private static final String[] supportedProps = { + "config.advancedbackups.enabled", + "config.advancedbackups.save", + "config.advancedbackups.activity", + "config.advancedbackups.type", + "config.advancedbackups.path", + "config.advancedbackups.size", + "config.advancedbackups.frequency.min", + "config.advancedbackups.frequency.max", + "config.advancedbackups.frequency.uptime", + "config.advancedbackups.frequency.schedule", + "config.advancedbackups.frequency.shutdown", + "config.advancedbackups.frequency.startup", + "config.advancedbackups.frequency.delay", + "config.advancedbackups.logging.silent", + + "config.advancedbackups.zips.compression", + + "config.advancedbackups.chains.length", + "config.advancedbackups.chains.compress", + "config.advancedbackups.chains.smart" + + }; public static ConfigData config; @@ -61,25 +85,26 @@ public static void loadConfig() { config = new ConfigData(); - config.setEnabled(props.getProperty("config.advancedbackups.enabled")); - config.setSave(props.getProperty("config.advancedbackups.save")); - config.setRequireActivity(props.getProperty("config.advancedbackups.activity")); - config.setBackupType(props.getProperty("config.advancedbackups.type")); - config.setPath(props.getProperty("config.advancedbackups.path")); - config.setMaxSize(props.getProperty("config.advancedbackups.size")); - config.setMinTimer(props.getProperty("config.advancedbackups.frequency.min")); - config.setMaxTimer(props.getProperty("config.advancedbackups.frequency.max")); - config.setUptimeSchedule(props.getProperty("config.advancedbackups.frequency.uptime")); - config.setSchedule(props.getProperty("config.advancedbackups.frequency.schedule")); - config.setForceOnShutdown(props.getProperty("config.advancedbackups.frequency.shutdown")); - config.setForceOnStartup(props.getProperty("config.advancedbackups.frequency.startup")); - config.setStartupDelay(props.getProperty("config.advancedbackups.frequency.delay")); - config.setSilent(props.getProperty("config.advancedbackups.logging.silent")); + config.setEnabled(props.getProperty("config.advancedbackups.enabled", "true")); + config.setSave(props.getProperty("config.advancedbackups.save", "false")); + config.setRequireActivity(props.getProperty("config.advancedbackups.activity", "false")); + config.setBackupType(props.getProperty("config.advancedbackups.type", "differential")); + config.setPath(props.getProperty("config.advancedbackups.path", "./backups")); + config.setMaxSize(props.getProperty("config.advancedbackups.size", "50")); + config.setMinTimer(props.getProperty("config.advancedbackups.frequency.min", "0.5")); + config.setMaxTimer(props.getProperty("config.advancedbackups.frequency.max", "24")); + config.setUptimeSchedule(props.getProperty("config.advancedbackups.frequency.uptime", "true")); + config.setSchedule(props.getProperty("config.advancedbackups.frequency.schedule", "12:00")); + config.setForceOnShutdown(props.getProperty("config.advancedbackups.frequency.shutdown", "false")); + config.setForceOnStartup(props.getProperty("config.advancedbackups.frequency.startup", "false")); + config.setStartupDelay(props.getProperty("config.advancedbackups.frequency.delay", "5")); + config.setSilent(props.getProperty("config.advancedbackups.logging.silent", "false")); - config.setCompressionLevel(props.getProperty("config.advancedbackups.zips.compression")); + config.setCompressionLevel(props.getProperty("config.advancedbackups.zips.compression", "5")); - config.setMaxDepth(props.getProperty("config.advancedbackups.chains.length")); - config.setCompressChains(props.getProperty("config.advancedbackups.chains.compress")); + config.setMaxDepth(props.getProperty("config.advancedbackups.chains.length", "50")); + config.setCompressChains(props.getProperty("config.advancedbackups.chains.compress", "true")); + config.setSmartChains(props.getProperty("config.advancedbackups.chains.smart", "true")); @@ -94,6 +119,41 @@ public static void loadConfig() { } } + boolean flag = false; + + for (String prop : supportedProps) { + if (!props.containsKey(prop)) { + flag = true; + break; + } + } + + if (flag) { + PlatformMethodWrapper.warningLogger.accept("Broken, incomplete or misising config found! Generating new file whilst preserving any existing config values..."); + + File newPropsFile = new File("./AdvancedBackups.properties"); + try { + if (!newPropsFile.exists()) { + newPropsFile.createNewFile(); + } + FileWriter writer = new FileWriter(newPropsFile); + writer.write(String.format(ConfigData.plainConfig, config.getEnabled(), + config.getSave(), config.getRequireActivity(), config.getBackupType(), + config.getPath(), config.getMaxSize(), config.getMinTimer(), + config.getMaxTimer(), config.getUptimeSchedule(), config.getSchedule(), + config.getForceOnShutdown(), config.getStartupDelay(), config.getStartupDelay(), + config.getSilent(), config.getCompressionLevel(), config.getMaxDepth(), + config.getCompressChains(), config.getSmartChains() + )); + writer.close(); + } catch (IOException e) { + // TODO : Scream to user + e.printStackTrace(); + + } + loadConfig(); + } + } } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java index ad9788ad..3b8b8d0e 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java @@ -1,5 +1,7 @@ package co.uk.mommyheather.advancedbackups.core.config; +import org.checkerframework.checker.units.qual.m; + public class ConfigData { private Boolean enabled; @@ -223,43 +225,43 @@ public void setSmartChains(String smartChains) { //default config output - can be ignored - public static final String defaults = String.join("\n", + public static final String plainConfig = String.join("\n", "#Enable or disable automatic backups.", "#Options : true, false #Default : true,", -"config.advancedbackups.enabled=true", +"config.advancedbackups.enabled=%s", "", "#Whether to save before making a backup.", "#Options : true, false #Default : false", -"config.advancedbackups.save=false", +"config.advancedbackups.save=%s", "", "#Whether to require player activity between backups.", "#Options : true, false #Default : false", -"config.advancedbackups.activity=false", +"config.advancedbackups.activity=%s", "", "#The type of backups to use.", "#Options : zip, differential, incremental #Default : differential", -"config.advancedbackups.type=differential", +"config.advancedbackups.type=%s", "", "#The absolute or relative path to the backup location.", "#Options : any file path. Default : ./backups", -"config.advancedbackups.path=./backups", +"config.advancedbackups.path=%s", "", "#The maximum size to keep, in GB. Keep relatively high for zips, tighter space requirements should instead use differential or incremental backups.", "#Range : 5 - 9999 #Default : 50", -"config.advancedbackups.size=50", +"config.advancedbackups.size=%s", "", "#Minimum time between backups, in hours. This can prevent a shutdown backup from triggering immediately after a scheduled backup or similar situations.", "#Range : 0.5 - 500 #Default : 0.5", -"config.advancedbackups.frequency.min=0.5", +"config.advancedbackups.frequency.min=%s", "", "#Triggers a backup if none has already happened within this time. Can be combined with an uptime-based schedule.", "#Range : 0.5 - 500 #Default : 24", -"config.advancedbackups.frequency.max=24", +"config.advancedbackups.frequency.max=%s", "", "#Whether the schedule below uses uptime (true) or real-world time (false).", "#Default : true", -"config.advancedbackups.frequency.uptime=true", +"config.advancedbackups.frequency.uptime=%s", "", "#When using server uptime:", " #A looping comma-separated backup schedule, based off of server uptime, hours:minutes. Examples:", @@ -274,23 +276,23 @@ public void setSmartChains(String smartChains) { " #4:00,8:00,12:00,16:00,17:00,18:00,19:00,20:00,21:00,24:00 - Makes a backup at specific times of day.", "", "#Default : 12:00", -"config.advancedbackups.frequency.schedule=12:00", +"config.advancedbackups.frequency.schedule=%s", "", "#Whether to force a backup on server shutdown. Respects min frequency.", "#Options : true, false #Default : false", -"config.advancedbackups.frequency.shutdown=false", +"config.advancedbackups.frequency.shutdown=%s", "", "#Whether to force a backup on server startup. Respects min frequency.", "#Options : true, false #Default : false", -"config.advancedbackups.frequency.startup=false", +"config.advancedbackups.frequency.startup=%s", "", "#Delay to use after startup, in seconds. Is always at least 5 seconds.", "#Range : 5-9999999999", -"config.advancedbackups.frequency.delay=5", +"config.advancedbackups.frequency.delay=%s", "", "#Whether to disable console and chat logging. Does not affect debug.log, does not affect error messages.", "#Options : true, false #Default : false", -"config.advancedbackups.logging.silent=false", +"config.advancedbackups.logging.silent=%s", "", "", "", @@ -300,7 +302,7 @@ public void setSmartChains(String smartChains) { "", "#The compression level to use for zip files. Higher numbers space usage, but decrease performance.", "#Range : 1-9 #Default : 4", -"config.advancedbackups.zips.compression=4", +"config.advancedbackups.zips.compression=%s", "", "", "", @@ -310,15 +312,23 @@ public void setSmartChains(String smartChains) { "", "#The maximum 'chain' length to keep.", "#Range : 5-500 #Default : 50", -"config.advancedbackups.chains.length=50", +"config.advancedbackups.chains.length=%s", "", "#Whether to compress 'chains'. This compresses the base backup and all sequential backups. Reduces space usage, but decreases performance.", "#Options : true, false #Default : true", -"config.advancedbackups.chains.compress=true", +"config.advancedbackups.chains.compress=%s", "", "#Whether to enable \"smart\" reset for chains - if every file is being backed up, mark the backup as complete and reset chain length regardless of intended backup type.", "#Options : true, false #Default : true", -"config.advancedbackups.chains.smart=true" +"config.advancedbackups.chains.smart=%s" ); + public static final String defaults = String.format(plainConfig, + "true", "false", "false", + "differential", "./backups", "50", + "0.5", "24", "true", + "12:00", "false", "false", + "5", "false", "4", + "50", "true", "true"); + } From 0939a601e869154c59a36dcfa559fe52089eed24 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Thu, 15 Jun 2023 14:34:12 +0000 Subject: [PATCH 112/580] Update core files --- .../advancedbackups/core/config/AVConfig.java | 94 +++++++++++++++---- .../core/config/ConfigData.java | 48 ++++++---- 2 files changed, 106 insertions(+), 36 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java index 71d3f511..5c01cd92 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java @@ -7,10 +7,34 @@ import java.util.ArrayList; import java.util.Properties; +import co.uk.mommyheather.advancedbackups.PlatformMethodWrapper; import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; public class AVConfig { + private static final String[] supportedProps = { + "config.advancedbackups.enabled", + "config.advancedbackups.save", + "config.advancedbackups.activity", + "config.advancedbackups.type", + "config.advancedbackups.path", + "config.advancedbackups.size", + "config.advancedbackups.frequency.min", + "config.advancedbackups.frequency.max", + "config.advancedbackups.frequency.uptime", + "config.advancedbackups.frequency.schedule", + "config.advancedbackups.frequency.shutdown", + "config.advancedbackups.frequency.startup", + "config.advancedbackups.frequency.delay", + "config.advancedbackups.logging.silent", + + "config.advancedbackups.zips.compression", + + "config.advancedbackups.chains.length", + "config.advancedbackups.chains.compress", + "config.advancedbackups.chains.smart" + + }; public static ConfigData config; @@ -61,25 +85,26 @@ public static void loadConfig() { config = new ConfigData(); - config.setEnabled(props.getProperty("config.advancedbackups.enabled")); - config.setSave(props.getProperty("config.advancedbackups.save")); - config.setRequireActivity(props.getProperty("config.advancedbackups.activity")); - config.setBackupType(props.getProperty("config.advancedbackups.type")); - config.setPath(props.getProperty("config.advancedbackups.path")); - config.setMaxSize(props.getProperty("config.advancedbackups.size")); - config.setMinTimer(props.getProperty("config.advancedbackups.frequency.min")); - config.setMaxTimer(props.getProperty("config.advancedbackups.frequency.max")); - config.setUptimeSchedule(props.getProperty("config.advancedbackups.frequency.uptime")); - config.setSchedule(props.getProperty("config.advancedbackups.frequency.schedule")); - config.setForceOnShutdown(props.getProperty("config.advancedbackups.frequency.shutdown")); - config.setForceOnStartup(props.getProperty("config.advancedbackups.frequency.startup")); - config.setStartupDelay(props.getProperty("config.advancedbackups.frequency.delay")); - config.setSilent(props.getProperty("config.advancedbackups.logging.silent")); + config.setEnabled(props.getProperty("config.advancedbackups.enabled", "true")); + config.setSave(props.getProperty("config.advancedbackups.save", "false")); + config.setRequireActivity(props.getProperty("config.advancedbackups.activity", "false")); + config.setBackupType(props.getProperty("config.advancedbackups.type", "differential")); + config.setPath(props.getProperty("config.advancedbackups.path", "./backups")); + config.setMaxSize(props.getProperty("config.advancedbackups.size", "50")); + config.setMinTimer(props.getProperty("config.advancedbackups.frequency.min", "0.5")); + config.setMaxTimer(props.getProperty("config.advancedbackups.frequency.max", "24")); + config.setUptimeSchedule(props.getProperty("config.advancedbackups.frequency.uptime", "true")); + config.setSchedule(props.getProperty("config.advancedbackups.frequency.schedule", "12:00")); + config.setForceOnShutdown(props.getProperty("config.advancedbackups.frequency.shutdown", "false")); + config.setForceOnStartup(props.getProperty("config.advancedbackups.frequency.startup", "false")); + config.setStartupDelay(props.getProperty("config.advancedbackups.frequency.delay", "5")); + config.setSilent(props.getProperty("config.advancedbackups.logging.silent", "false")); - config.setCompressionLevel(props.getProperty("config.advancedbackups.zips.compression")); + config.setCompressionLevel(props.getProperty("config.advancedbackups.zips.compression", "5")); - config.setMaxDepth(props.getProperty("config.advancedbackups.chains.length")); - config.setCompressChains(props.getProperty("config.advancedbackups.chains.compress")); + config.setMaxDepth(props.getProperty("config.advancedbackups.chains.length", "50")); + config.setCompressChains(props.getProperty("config.advancedbackups.chains.compress", "true")); + config.setSmartChains(props.getProperty("config.advancedbackups.chains.smart", "true")); @@ -94,6 +119,41 @@ public static void loadConfig() { } } + boolean flag = false; + + for (String prop : supportedProps) { + if (!props.containsKey(prop)) { + flag = true; + break; + } + } + + if (flag) { + PlatformMethodWrapper.warningLogger.accept("Broken, incomplete or misising config found! Generating new file whilst preserving any existing config values..."); + + File newPropsFile = new File("./AdvancedBackups.properties"); + try { + if (!newPropsFile.exists()) { + newPropsFile.createNewFile(); + } + FileWriter writer = new FileWriter(newPropsFile); + writer.write(String.format(ConfigData.plainConfig, config.getEnabled(), + config.getSave(), config.getRequireActivity(), config.getBackupType(), + config.getPath(), config.getMaxSize(), config.getMinTimer(), + config.getMaxTimer(), config.getUptimeSchedule(), config.getSchedule(), + config.getForceOnShutdown(), config.getStartupDelay(), config.getStartupDelay(), + config.getSilent(), config.getCompressionLevel(), config.getMaxDepth(), + config.getCompressChains(), config.getSmartChains() + )); + writer.close(); + } catch (IOException e) { + // TODO : Scream to user + e.printStackTrace(); + + } + loadConfig(); + } + } } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java index ad9788ad..3b8b8d0e 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java @@ -1,5 +1,7 @@ package co.uk.mommyheather.advancedbackups.core.config; +import org.checkerframework.checker.units.qual.m; + public class ConfigData { private Boolean enabled; @@ -223,43 +225,43 @@ public void setSmartChains(String smartChains) { //default config output - can be ignored - public static final String defaults = String.join("\n", + public static final String plainConfig = String.join("\n", "#Enable or disable automatic backups.", "#Options : true, false #Default : true,", -"config.advancedbackups.enabled=true", +"config.advancedbackups.enabled=%s", "", "#Whether to save before making a backup.", "#Options : true, false #Default : false", -"config.advancedbackups.save=false", +"config.advancedbackups.save=%s", "", "#Whether to require player activity between backups.", "#Options : true, false #Default : false", -"config.advancedbackups.activity=false", +"config.advancedbackups.activity=%s", "", "#The type of backups to use.", "#Options : zip, differential, incremental #Default : differential", -"config.advancedbackups.type=differential", +"config.advancedbackups.type=%s", "", "#The absolute or relative path to the backup location.", "#Options : any file path. Default : ./backups", -"config.advancedbackups.path=./backups", +"config.advancedbackups.path=%s", "", "#The maximum size to keep, in GB. Keep relatively high for zips, tighter space requirements should instead use differential or incremental backups.", "#Range : 5 - 9999 #Default : 50", -"config.advancedbackups.size=50", +"config.advancedbackups.size=%s", "", "#Minimum time between backups, in hours. This can prevent a shutdown backup from triggering immediately after a scheduled backup or similar situations.", "#Range : 0.5 - 500 #Default : 0.5", -"config.advancedbackups.frequency.min=0.5", +"config.advancedbackups.frequency.min=%s", "", "#Triggers a backup if none has already happened within this time. Can be combined with an uptime-based schedule.", "#Range : 0.5 - 500 #Default : 24", -"config.advancedbackups.frequency.max=24", +"config.advancedbackups.frequency.max=%s", "", "#Whether the schedule below uses uptime (true) or real-world time (false).", "#Default : true", -"config.advancedbackups.frequency.uptime=true", +"config.advancedbackups.frequency.uptime=%s", "", "#When using server uptime:", " #A looping comma-separated backup schedule, based off of server uptime, hours:minutes. Examples:", @@ -274,23 +276,23 @@ public void setSmartChains(String smartChains) { " #4:00,8:00,12:00,16:00,17:00,18:00,19:00,20:00,21:00,24:00 - Makes a backup at specific times of day.", "", "#Default : 12:00", -"config.advancedbackups.frequency.schedule=12:00", +"config.advancedbackups.frequency.schedule=%s", "", "#Whether to force a backup on server shutdown. Respects min frequency.", "#Options : true, false #Default : false", -"config.advancedbackups.frequency.shutdown=false", +"config.advancedbackups.frequency.shutdown=%s", "", "#Whether to force a backup on server startup. Respects min frequency.", "#Options : true, false #Default : false", -"config.advancedbackups.frequency.startup=false", +"config.advancedbackups.frequency.startup=%s", "", "#Delay to use after startup, in seconds. Is always at least 5 seconds.", "#Range : 5-9999999999", -"config.advancedbackups.frequency.delay=5", +"config.advancedbackups.frequency.delay=%s", "", "#Whether to disable console and chat logging. Does not affect debug.log, does not affect error messages.", "#Options : true, false #Default : false", -"config.advancedbackups.logging.silent=false", +"config.advancedbackups.logging.silent=%s", "", "", "", @@ -300,7 +302,7 @@ public void setSmartChains(String smartChains) { "", "#The compression level to use for zip files. Higher numbers space usage, but decrease performance.", "#Range : 1-9 #Default : 4", -"config.advancedbackups.zips.compression=4", +"config.advancedbackups.zips.compression=%s", "", "", "", @@ -310,15 +312,23 @@ public void setSmartChains(String smartChains) { "", "#The maximum 'chain' length to keep.", "#Range : 5-500 #Default : 50", -"config.advancedbackups.chains.length=50", +"config.advancedbackups.chains.length=%s", "", "#Whether to compress 'chains'. This compresses the base backup and all sequential backups. Reduces space usage, but decreases performance.", "#Options : true, false #Default : true", -"config.advancedbackups.chains.compress=true", +"config.advancedbackups.chains.compress=%s", "", "#Whether to enable \"smart\" reset for chains - if every file is being backed up, mark the backup as complete and reset chain length regardless of intended backup type.", "#Options : true, false #Default : true", -"config.advancedbackups.chains.smart=true" +"config.advancedbackups.chains.smart=%s" ); + public static final String defaults = String.format(plainConfig, + "true", "false", "false", + "differential", "./backups", "50", + "0.5", "24", "true", + "12:00", "false", "false", + "5", "false", "4", + "50", "true", "true"); + } From ab2a897be698505308565716129daed925569d68 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Thu, 15 Jun 2023 14:34:13 +0000 Subject: [PATCH 113/580] Update core files --- .../advancedbackups/core/config/AVConfig.java | 94 +++++++++++++++---- .../core/config/ConfigData.java | 48 ++++++---- 2 files changed, 106 insertions(+), 36 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java index 71d3f511..5c01cd92 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java @@ -7,10 +7,34 @@ import java.util.ArrayList; import java.util.Properties; +import co.uk.mommyheather.advancedbackups.PlatformMethodWrapper; import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; public class AVConfig { + private static final String[] supportedProps = { + "config.advancedbackups.enabled", + "config.advancedbackups.save", + "config.advancedbackups.activity", + "config.advancedbackups.type", + "config.advancedbackups.path", + "config.advancedbackups.size", + "config.advancedbackups.frequency.min", + "config.advancedbackups.frequency.max", + "config.advancedbackups.frequency.uptime", + "config.advancedbackups.frequency.schedule", + "config.advancedbackups.frequency.shutdown", + "config.advancedbackups.frequency.startup", + "config.advancedbackups.frequency.delay", + "config.advancedbackups.logging.silent", + + "config.advancedbackups.zips.compression", + + "config.advancedbackups.chains.length", + "config.advancedbackups.chains.compress", + "config.advancedbackups.chains.smart" + + }; public static ConfigData config; @@ -61,25 +85,26 @@ public static void loadConfig() { config = new ConfigData(); - config.setEnabled(props.getProperty("config.advancedbackups.enabled")); - config.setSave(props.getProperty("config.advancedbackups.save")); - config.setRequireActivity(props.getProperty("config.advancedbackups.activity")); - config.setBackupType(props.getProperty("config.advancedbackups.type")); - config.setPath(props.getProperty("config.advancedbackups.path")); - config.setMaxSize(props.getProperty("config.advancedbackups.size")); - config.setMinTimer(props.getProperty("config.advancedbackups.frequency.min")); - config.setMaxTimer(props.getProperty("config.advancedbackups.frequency.max")); - config.setUptimeSchedule(props.getProperty("config.advancedbackups.frequency.uptime")); - config.setSchedule(props.getProperty("config.advancedbackups.frequency.schedule")); - config.setForceOnShutdown(props.getProperty("config.advancedbackups.frequency.shutdown")); - config.setForceOnStartup(props.getProperty("config.advancedbackups.frequency.startup")); - config.setStartupDelay(props.getProperty("config.advancedbackups.frequency.delay")); - config.setSilent(props.getProperty("config.advancedbackups.logging.silent")); + config.setEnabled(props.getProperty("config.advancedbackups.enabled", "true")); + config.setSave(props.getProperty("config.advancedbackups.save", "false")); + config.setRequireActivity(props.getProperty("config.advancedbackups.activity", "false")); + config.setBackupType(props.getProperty("config.advancedbackups.type", "differential")); + config.setPath(props.getProperty("config.advancedbackups.path", "./backups")); + config.setMaxSize(props.getProperty("config.advancedbackups.size", "50")); + config.setMinTimer(props.getProperty("config.advancedbackups.frequency.min", "0.5")); + config.setMaxTimer(props.getProperty("config.advancedbackups.frequency.max", "24")); + config.setUptimeSchedule(props.getProperty("config.advancedbackups.frequency.uptime", "true")); + config.setSchedule(props.getProperty("config.advancedbackups.frequency.schedule", "12:00")); + config.setForceOnShutdown(props.getProperty("config.advancedbackups.frequency.shutdown", "false")); + config.setForceOnStartup(props.getProperty("config.advancedbackups.frequency.startup", "false")); + config.setStartupDelay(props.getProperty("config.advancedbackups.frequency.delay", "5")); + config.setSilent(props.getProperty("config.advancedbackups.logging.silent", "false")); - config.setCompressionLevel(props.getProperty("config.advancedbackups.zips.compression")); + config.setCompressionLevel(props.getProperty("config.advancedbackups.zips.compression", "5")); - config.setMaxDepth(props.getProperty("config.advancedbackups.chains.length")); - config.setCompressChains(props.getProperty("config.advancedbackups.chains.compress")); + config.setMaxDepth(props.getProperty("config.advancedbackups.chains.length", "50")); + config.setCompressChains(props.getProperty("config.advancedbackups.chains.compress", "true")); + config.setSmartChains(props.getProperty("config.advancedbackups.chains.smart", "true")); @@ -94,6 +119,41 @@ public static void loadConfig() { } } + boolean flag = false; + + for (String prop : supportedProps) { + if (!props.containsKey(prop)) { + flag = true; + break; + } + } + + if (flag) { + PlatformMethodWrapper.warningLogger.accept("Broken, incomplete or misising config found! Generating new file whilst preserving any existing config values..."); + + File newPropsFile = new File("./AdvancedBackups.properties"); + try { + if (!newPropsFile.exists()) { + newPropsFile.createNewFile(); + } + FileWriter writer = new FileWriter(newPropsFile); + writer.write(String.format(ConfigData.plainConfig, config.getEnabled(), + config.getSave(), config.getRequireActivity(), config.getBackupType(), + config.getPath(), config.getMaxSize(), config.getMinTimer(), + config.getMaxTimer(), config.getUptimeSchedule(), config.getSchedule(), + config.getForceOnShutdown(), config.getStartupDelay(), config.getStartupDelay(), + config.getSilent(), config.getCompressionLevel(), config.getMaxDepth(), + config.getCompressChains(), config.getSmartChains() + )); + writer.close(); + } catch (IOException e) { + // TODO : Scream to user + e.printStackTrace(); + + } + loadConfig(); + } + } } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java index ad9788ad..3b8b8d0e 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java @@ -1,5 +1,7 @@ package co.uk.mommyheather.advancedbackups.core.config; +import org.checkerframework.checker.units.qual.m; + public class ConfigData { private Boolean enabled; @@ -223,43 +225,43 @@ public void setSmartChains(String smartChains) { //default config output - can be ignored - public static final String defaults = String.join("\n", + public static final String plainConfig = String.join("\n", "#Enable or disable automatic backups.", "#Options : true, false #Default : true,", -"config.advancedbackups.enabled=true", +"config.advancedbackups.enabled=%s", "", "#Whether to save before making a backup.", "#Options : true, false #Default : false", -"config.advancedbackups.save=false", +"config.advancedbackups.save=%s", "", "#Whether to require player activity between backups.", "#Options : true, false #Default : false", -"config.advancedbackups.activity=false", +"config.advancedbackups.activity=%s", "", "#The type of backups to use.", "#Options : zip, differential, incremental #Default : differential", -"config.advancedbackups.type=differential", +"config.advancedbackups.type=%s", "", "#The absolute or relative path to the backup location.", "#Options : any file path. Default : ./backups", -"config.advancedbackups.path=./backups", +"config.advancedbackups.path=%s", "", "#The maximum size to keep, in GB. Keep relatively high for zips, tighter space requirements should instead use differential or incremental backups.", "#Range : 5 - 9999 #Default : 50", -"config.advancedbackups.size=50", +"config.advancedbackups.size=%s", "", "#Minimum time between backups, in hours. This can prevent a shutdown backup from triggering immediately after a scheduled backup or similar situations.", "#Range : 0.5 - 500 #Default : 0.5", -"config.advancedbackups.frequency.min=0.5", +"config.advancedbackups.frequency.min=%s", "", "#Triggers a backup if none has already happened within this time. Can be combined with an uptime-based schedule.", "#Range : 0.5 - 500 #Default : 24", -"config.advancedbackups.frequency.max=24", +"config.advancedbackups.frequency.max=%s", "", "#Whether the schedule below uses uptime (true) or real-world time (false).", "#Default : true", -"config.advancedbackups.frequency.uptime=true", +"config.advancedbackups.frequency.uptime=%s", "", "#When using server uptime:", " #A looping comma-separated backup schedule, based off of server uptime, hours:minutes. Examples:", @@ -274,23 +276,23 @@ public void setSmartChains(String smartChains) { " #4:00,8:00,12:00,16:00,17:00,18:00,19:00,20:00,21:00,24:00 - Makes a backup at specific times of day.", "", "#Default : 12:00", -"config.advancedbackups.frequency.schedule=12:00", +"config.advancedbackups.frequency.schedule=%s", "", "#Whether to force a backup on server shutdown. Respects min frequency.", "#Options : true, false #Default : false", -"config.advancedbackups.frequency.shutdown=false", +"config.advancedbackups.frequency.shutdown=%s", "", "#Whether to force a backup on server startup. Respects min frequency.", "#Options : true, false #Default : false", -"config.advancedbackups.frequency.startup=false", +"config.advancedbackups.frequency.startup=%s", "", "#Delay to use after startup, in seconds. Is always at least 5 seconds.", "#Range : 5-9999999999", -"config.advancedbackups.frequency.delay=5", +"config.advancedbackups.frequency.delay=%s", "", "#Whether to disable console and chat logging. Does not affect debug.log, does not affect error messages.", "#Options : true, false #Default : false", -"config.advancedbackups.logging.silent=false", +"config.advancedbackups.logging.silent=%s", "", "", "", @@ -300,7 +302,7 @@ public void setSmartChains(String smartChains) { "", "#The compression level to use for zip files. Higher numbers space usage, but decrease performance.", "#Range : 1-9 #Default : 4", -"config.advancedbackups.zips.compression=4", +"config.advancedbackups.zips.compression=%s", "", "", "", @@ -310,15 +312,23 @@ public void setSmartChains(String smartChains) { "", "#The maximum 'chain' length to keep.", "#Range : 5-500 #Default : 50", -"config.advancedbackups.chains.length=50", +"config.advancedbackups.chains.length=%s", "", "#Whether to compress 'chains'. This compresses the base backup and all sequential backups. Reduces space usage, but decreases performance.", "#Options : true, false #Default : true", -"config.advancedbackups.chains.compress=true", +"config.advancedbackups.chains.compress=%s", "", "#Whether to enable \"smart\" reset for chains - if every file is being backed up, mark the backup as complete and reset chain length regardless of intended backup type.", "#Options : true, false #Default : true", -"config.advancedbackups.chains.smart=true" +"config.advancedbackups.chains.smart=%s" ); + public static final String defaults = String.format(plainConfig, + "true", "false", "false", + "differential", "./backups", "50", + "0.5", "24", "true", + "12:00", "false", "false", + "5", "false", "4", + "50", "true", "true"); + } From ed6c7236e0434d2d5698c0b0aab08d1d2e41111c Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Thu, 15 Jun 2023 14:34:14 +0000 Subject: [PATCH 114/580] Update core files --- .../advancedbackups/core/config/AVConfig.java | 94 +++++++++++++++---- .../core/config/ConfigData.java | 48 ++++++---- 2 files changed, 106 insertions(+), 36 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java index 71d3f511..5c01cd92 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java @@ -7,10 +7,34 @@ import java.util.ArrayList; import java.util.Properties; +import co.uk.mommyheather.advancedbackups.PlatformMethodWrapper; import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; public class AVConfig { + private static final String[] supportedProps = { + "config.advancedbackups.enabled", + "config.advancedbackups.save", + "config.advancedbackups.activity", + "config.advancedbackups.type", + "config.advancedbackups.path", + "config.advancedbackups.size", + "config.advancedbackups.frequency.min", + "config.advancedbackups.frequency.max", + "config.advancedbackups.frequency.uptime", + "config.advancedbackups.frequency.schedule", + "config.advancedbackups.frequency.shutdown", + "config.advancedbackups.frequency.startup", + "config.advancedbackups.frequency.delay", + "config.advancedbackups.logging.silent", + + "config.advancedbackups.zips.compression", + + "config.advancedbackups.chains.length", + "config.advancedbackups.chains.compress", + "config.advancedbackups.chains.smart" + + }; public static ConfigData config; @@ -61,25 +85,26 @@ public static void loadConfig() { config = new ConfigData(); - config.setEnabled(props.getProperty("config.advancedbackups.enabled")); - config.setSave(props.getProperty("config.advancedbackups.save")); - config.setRequireActivity(props.getProperty("config.advancedbackups.activity")); - config.setBackupType(props.getProperty("config.advancedbackups.type")); - config.setPath(props.getProperty("config.advancedbackups.path")); - config.setMaxSize(props.getProperty("config.advancedbackups.size")); - config.setMinTimer(props.getProperty("config.advancedbackups.frequency.min")); - config.setMaxTimer(props.getProperty("config.advancedbackups.frequency.max")); - config.setUptimeSchedule(props.getProperty("config.advancedbackups.frequency.uptime")); - config.setSchedule(props.getProperty("config.advancedbackups.frequency.schedule")); - config.setForceOnShutdown(props.getProperty("config.advancedbackups.frequency.shutdown")); - config.setForceOnStartup(props.getProperty("config.advancedbackups.frequency.startup")); - config.setStartupDelay(props.getProperty("config.advancedbackups.frequency.delay")); - config.setSilent(props.getProperty("config.advancedbackups.logging.silent")); + config.setEnabled(props.getProperty("config.advancedbackups.enabled", "true")); + config.setSave(props.getProperty("config.advancedbackups.save", "false")); + config.setRequireActivity(props.getProperty("config.advancedbackups.activity", "false")); + config.setBackupType(props.getProperty("config.advancedbackups.type", "differential")); + config.setPath(props.getProperty("config.advancedbackups.path", "./backups")); + config.setMaxSize(props.getProperty("config.advancedbackups.size", "50")); + config.setMinTimer(props.getProperty("config.advancedbackups.frequency.min", "0.5")); + config.setMaxTimer(props.getProperty("config.advancedbackups.frequency.max", "24")); + config.setUptimeSchedule(props.getProperty("config.advancedbackups.frequency.uptime", "true")); + config.setSchedule(props.getProperty("config.advancedbackups.frequency.schedule", "12:00")); + config.setForceOnShutdown(props.getProperty("config.advancedbackups.frequency.shutdown", "false")); + config.setForceOnStartup(props.getProperty("config.advancedbackups.frequency.startup", "false")); + config.setStartupDelay(props.getProperty("config.advancedbackups.frequency.delay", "5")); + config.setSilent(props.getProperty("config.advancedbackups.logging.silent", "false")); - config.setCompressionLevel(props.getProperty("config.advancedbackups.zips.compression")); + config.setCompressionLevel(props.getProperty("config.advancedbackups.zips.compression", "5")); - config.setMaxDepth(props.getProperty("config.advancedbackups.chains.length")); - config.setCompressChains(props.getProperty("config.advancedbackups.chains.compress")); + config.setMaxDepth(props.getProperty("config.advancedbackups.chains.length", "50")); + config.setCompressChains(props.getProperty("config.advancedbackups.chains.compress", "true")); + config.setSmartChains(props.getProperty("config.advancedbackups.chains.smart", "true")); @@ -94,6 +119,41 @@ public static void loadConfig() { } } + boolean flag = false; + + for (String prop : supportedProps) { + if (!props.containsKey(prop)) { + flag = true; + break; + } + } + + if (flag) { + PlatformMethodWrapper.warningLogger.accept("Broken, incomplete or misising config found! Generating new file whilst preserving any existing config values..."); + + File newPropsFile = new File("./AdvancedBackups.properties"); + try { + if (!newPropsFile.exists()) { + newPropsFile.createNewFile(); + } + FileWriter writer = new FileWriter(newPropsFile); + writer.write(String.format(ConfigData.plainConfig, config.getEnabled(), + config.getSave(), config.getRequireActivity(), config.getBackupType(), + config.getPath(), config.getMaxSize(), config.getMinTimer(), + config.getMaxTimer(), config.getUptimeSchedule(), config.getSchedule(), + config.getForceOnShutdown(), config.getStartupDelay(), config.getStartupDelay(), + config.getSilent(), config.getCompressionLevel(), config.getMaxDepth(), + config.getCompressChains(), config.getSmartChains() + )); + writer.close(); + } catch (IOException e) { + // TODO : Scream to user + e.printStackTrace(); + + } + loadConfig(); + } + } } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java index ad9788ad..3b8b8d0e 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java @@ -1,5 +1,7 @@ package co.uk.mommyheather.advancedbackups.core.config; +import org.checkerframework.checker.units.qual.m; + public class ConfigData { private Boolean enabled; @@ -223,43 +225,43 @@ public void setSmartChains(String smartChains) { //default config output - can be ignored - public static final String defaults = String.join("\n", + public static final String plainConfig = String.join("\n", "#Enable or disable automatic backups.", "#Options : true, false #Default : true,", -"config.advancedbackups.enabled=true", +"config.advancedbackups.enabled=%s", "", "#Whether to save before making a backup.", "#Options : true, false #Default : false", -"config.advancedbackups.save=false", +"config.advancedbackups.save=%s", "", "#Whether to require player activity between backups.", "#Options : true, false #Default : false", -"config.advancedbackups.activity=false", +"config.advancedbackups.activity=%s", "", "#The type of backups to use.", "#Options : zip, differential, incremental #Default : differential", -"config.advancedbackups.type=differential", +"config.advancedbackups.type=%s", "", "#The absolute or relative path to the backup location.", "#Options : any file path. Default : ./backups", -"config.advancedbackups.path=./backups", +"config.advancedbackups.path=%s", "", "#The maximum size to keep, in GB. Keep relatively high for zips, tighter space requirements should instead use differential or incremental backups.", "#Range : 5 - 9999 #Default : 50", -"config.advancedbackups.size=50", +"config.advancedbackups.size=%s", "", "#Minimum time between backups, in hours. This can prevent a shutdown backup from triggering immediately after a scheduled backup or similar situations.", "#Range : 0.5 - 500 #Default : 0.5", -"config.advancedbackups.frequency.min=0.5", +"config.advancedbackups.frequency.min=%s", "", "#Triggers a backup if none has already happened within this time. Can be combined with an uptime-based schedule.", "#Range : 0.5 - 500 #Default : 24", -"config.advancedbackups.frequency.max=24", +"config.advancedbackups.frequency.max=%s", "", "#Whether the schedule below uses uptime (true) or real-world time (false).", "#Default : true", -"config.advancedbackups.frequency.uptime=true", +"config.advancedbackups.frequency.uptime=%s", "", "#When using server uptime:", " #A looping comma-separated backup schedule, based off of server uptime, hours:minutes. Examples:", @@ -274,23 +276,23 @@ public void setSmartChains(String smartChains) { " #4:00,8:00,12:00,16:00,17:00,18:00,19:00,20:00,21:00,24:00 - Makes a backup at specific times of day.", "", "#Default : 12:00", -"config.advancedbackups.frequency.schedule=12:00", +"config.advancedbackups.frequency.schedule=%s", "", "#Whether to force a backup on server shutdown. Respects min frequency.", "#Options : true, false #Default : false", -"config.advancedbackups.frequency.shutdown=false", +"config.advancedbackups.frequency.shutdown=%s", "", "#Whether to force a backup on server startup. Respects min frequency.", "#Options : true, false #Default : false", -"config.advancedbackups.frequency.startup=false", +"config.advancedbackups.frequency.startup=%s", "", "#Delay to use after startup, in seconds. Is always at least 5 seconds.", "#Range : 5-9999999999", -"config.advancedbackups.frequency.delay=5", +"config.advancedbackups.frequency.delay=%s", "", "#Whether to disable console and chat logging. Does not affect debug.log, does not affect error messages.", "#Options : true, false #Default : false", -"config.advancedbackups.logging.silent=false", +"config.advancedbackups.logging.silent=%s", "", "", "", @@ -300,7 +302,7 @@ public void setSmartChains(String smartChains) { "", "#The compression level to use for zip files. Higher numbers space usage, but decrease performance.", "#Range : 1-9 #Default : 4", -"config.advancedbackups.zips.compression=4", +"config.advancedbackups.zips.compression=%s", "", "", "", @@ -310,15 +312,23 @@ public void setSmartChains(String smartChains) { "", "#The maximum 'chain' length to keep.", "#Range : 5-500 #Default : 50", -"config.advancedbackups.chains.length=50", +"config.advancedbackups.chains.length=%s", "", "#Whether to compress 'chains'. This compresses the base backup and all sequential backups. Reduces space usage, but decreases performance.", "#Options : true, false #Default : true", -"config.advancedbackups.chains.compress=true", +"config.advancedbackups.chains.compress=%s", "", "#Whether to enable \"smart\" reset for chains - if every file is being backed up, mark the backup as complete and reset chain length regardless of intended backup type.", "#Options : true, false #Default : true", -"config.advancedbackups.chains.smart=true" +"config.advancedbackups.chains.smart=%s" ); + public static final String defaults = String.format(plainConfig, + "true", "false", "false", + "differential", "./backups", "50", + "0.5", "24", "true", + "12:00", "false", "false", + "5", "false", "4", + "50", "true", "true"); + } From 4cac610dac78efb098c49b4f8993e8a77413bfd6 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Thu, 15 Jun 2023 14:51:18 +0000 Subject: [PATCH 115/580] Update core files --- .../core/backups/BackupWrapper.java | 111 ++++++++++++------ .../advancedbackups/core/config/AVConfig.java | 8 +- .../core/config/ConfigData.java | 24 +++- 3 files changed, 105 insertions(+), 38 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java index 59b9f97f..afa9e309 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java @@ -129,54 +129,72 @@ public static void makeSingleBackup(long delay) { public static void finishBackup() { File directory = new File(AVConfig.config.getPath()); ThreadedBackup.running = false; + PlatformMethodWrapper.enableSaving(); switch(AVConfig.config.getBackupType()) { case "zip" : { directory = new File(directory, "/zips/"); - break; + long date = Long.MIN_VALUE; + while (true) { + if (calculateDirectorySize(directory) < AVConfig.config.getMaxSize() * 1000000000L) return; + File file = getFirstBackupAfterDate(directory, date); + date = file.lastModified(); + file.delete(); + } } case "differential" : { directory = new File(directory, "/differential/"); - break; + long date = Long.MIN_VALUE; + while (true) { + if (calculateDirectorySize(directory) < AVConfig.config.getMaxSize() * 1000000000L) return; + File file = getFirstBackupAfterDate(directory, date); + date = file.lastModified(); + if (file.getName().contains("full")) { + File nextFile = getFirstBackupAfterDate(directory, date); + if (nextFile.getName().contains("partial")) { + nextFile.delete(); + } + else { + file.delete(); + } + } + else { + file.delete(); + } + + } } case "incremental" : { directory = new File(directory, "/incremental/"); - break; - } + if (!AVConfig.config.getPurgeIncrementals()) return; + long date = Long.MIN_VALUE; + while (true) { + if (calculateDirectorySize(directory) < AVConfig.config.getMaxSize() * 1000000000L) return; + if (calculateChainCount(directory) < 2) return; + PlatformMethodWrapper.errorLogger.accept("Purging incremental backup chain - too much space taken up!"); + File file = getFirstBackupAfterDate(directory, date); + date = file.lastModified(); + if (file.getName().contains("full")) { + file.delete(); + while (true) { + file = getFirstBackupAfterDate(directory, date); + date = file.lastModified(); + if (file.getName().contains("full")) { + file.delete(); + } + else { + break; + } + } + } + else { + file.delete(); + } - } - - while (true) - { - File[] files = directory.listFiles(); - File oldestFile = null; - long totalLength = 0; - long lastModifiedTime = Long.MAX_VALUE; - if (files == null || files.length == 0) break; - for (File file : files) { - if (file.isFile()) { - totalLength += file.length(); } - else { - totalLength += calculateDirectorySize(file); - } - if (file.lastModified() < lastModifiedTime) { - lastModifiedTime = file.lastModified(); - oldestFile = file; - } - } - if (oldestFile != null && totalLength >= AVConfig.config.getMaxSize() * 1000000000L) { - oldestFile.delete(); - } - else { - break; } - } - - - PlatformMethodWrapper.enableSaving(); - + } } @@ -195,5 +213,30 @@ public static long calculateDirectorySize(File directory) { return size; } + public static File getFirstBackupAfterDate(File directory, long date) { + File[] files = directory.listFiles(); + File oldestFile = null; + long currentDate = Long.MAX_VALUE; + if (files == null || files.length == 0) return null; + for (File file : files) { + if (file.lastModified() < currentDate && file.lastModified() > date) { + currentDate = file.lastModified(); + oldestFile = file; + } + } + return oldestFile; + } + + public static int calculateChainCount(File directory) { + int count = 0; + File[] files = directory.listFiles(); + if (files == null || files.length == 0) return 0; + for (File file : files) { + if (file.getName().contains("full")) { + count++; + } + } + return count; + } } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java index 5c01cd92..af32c954 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java @@ -32,7 +32,9 @@ public class AVConfig { "config.advancedbackups.chains.length", "config.advancedbackups.chains.compress", - "config.advancedbackups.chains.smart" + "config.advancedbackups.chains.smart", + + "config.advancedbackups.purge.incrementals" }; @@ -106,6 +108,8 @@ public static void loadConfig() { config.setCompressChains(props.getProperty("config.advancedbackups.chains.compress", "true")); config.setSmartChains(props.getProperty("config.advancedbackups.chains.smart", "true")); + config.setPurgeIncrementals(props.getProperty("config.advancedbackups.purge.incrementals", "false")); + String timingsString = config.getSchedule(); @@ -143,7 +147,7 @@ public static void loadConfig() { config.getMaxTimer(), config.getUptimeSchedule(), config.getSchedule(), config.getForceOnShutdown(), config.getStartupDelay(), config.getStartupDelay(), config.getSilent(), config.getCompressionLevel(), config.getMaxDepth(), - config.getCompressChains(), config.getSmartChains() + config.getCompressChains(), config.getSmartChains(), config.getPurgeIncrementals() )); writer.close(); } catch (IOException e) { diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java index 3b8b8d0e..95f82824 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java @@ -77,6 +77,10 @@ public class ConfigData { // Smart chain resetting. // TRUE OR FALSE + private boolean purgeIncrementals; + // Whether to purge incremental backups if over the limit. + // TRUE OR FALSE + public Boolean getEnabled() { return enabled; } @@ -221,6 +225,15 @@ public boolean getSmartChains() { public void setSmartChains(String smartChains) { this.smartChains = Boolean.parseBoolean(smartChains); } + + + public boolean getPurgeIncrementals() { + return purgeIncrementals; + } + + public void setPurgeIncrementals(String purgeIncrementals) { + this.purgeIncrementals = Boolean.parseBoolean(purgeIncrementals); + } @@ -320,7 +333,13 @@ public void setSmartChains(String smartChains) { "", "#Whether to enable \"smart\" reset for chains - if every file is being backed up, mark the backup as complete and reset chain length regardless of intended backup type.", "#Options : true, false #Default : true", -"config.advancedbackups.chains.smart=%s" +"config.advancedbackups.chains.smart=%s", +"", +"#Whether to delete incremental backup chains if max size is exceeded. If not, incremental backups do not respect the max size config and never delete.", +"#Options : true, false #Default : false", +"config.advancedbackups.purge.incrementals=%s" + + ); public static final String defaults = String.format(plainConfig, @@ -329,6 +348,7 @@ public void setSmartChains(String smartChains) { "0.5", "24", "true", "12:00", "false", "false", "5", "false", "4", - "50", "true", "true"); + "50", "true", "true", + "false"); } From 076e57644a7105f31eedfbcc20247646f2e7b3c0 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Thu, 15 Jun 2023 14:51:20 +0000 Subject: [PATCH 116/580] Update core files --- .../core/backups/BackupWrapper.java | 111 ++++++++++++------ .../advancedbackups/core/config/AVConfig.java | 8 +- .../core/config/ConfigData.java | 24 +++- 3 files changed, 105 insertions(+), 38 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java index 59b9f97f..afa9e309 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java @@ -129,54 +129,72 @@ public static void makeSingleBackup(long delay) { public static void finishBackup() { File directory = new File(AVConfig.config.getPath()); ThreadedBackup.running = false; + PlatformMethodWrapper.enableSaving(); switch(AVConfig.config.getBackupType()) { case "zip" : { directory = new File(directory, "/zips/"); - break; + long date = Long.MIN_VALUE; + while (true) { + if (calculateDirectorySize(directory) < AVConfig.config.getMaxSize() * 1000000000L) return; + File file = getFirstBackupAfterDate(directory, date); + date = file.lastModified(); + file.delete(); + } } case "differential" : { directory = new File(directory, "/differential/"); - break; + long date = Long.MIN_VALUE; + while (true) { + if (calculateDirectorySize(directory) < AVConfig.config.getMaxSize() * 1000000000L) return; + File file = getFirstBackupAfterDate(directory, date); + date = file.lastModified(); + if (file.getName().contains("full")) { + File nextFile = getFirstBackupAfterDate(directory, date); + if (nextFile.getName().contains("partial")) { + nextFile.delete(); + } + else { + file.delete(); + } + } + else { + file.delete(); + } + + } } case "incremental" : { directory = new File(directory, "/incremental/"); - break; - } + if (!AVConfig.config.getPurgeIncrementals()) return; + long date = Long.MIN_VALUE; + while (true) { + if (calculateDirectorySize(directory) < AVConfig.config.getMaxSize() * 1000000000L) return; + if (calculateChainCount(directory) < 2) return; + PlatformMethodWrapper.errorLogger.accept("Purging incremental backup chain - too much space taken up!"); + File file = getFirstBackupAfterDate(directory, date); + date = file.lastModified(); + if (file.getName().contains("full")) { + file.delete(); + while (true) { + file = getFirstBackupAfterDate(directory, date); + date = file.lastModified(); + if (file.getName().contains("full")) { + file.delete(); + } + else { + break; + } + } + } + else { + file.delete(); + } - } - - while (true) - { - File[] files = directory.listFiles(); - File oldestFile = null; - long totalLength = 0; - long lastModifiedTime = Long.MAX_VALUE; - if (files == null || files.length == 0) break; - for (File file : files) { - if (file.isFile()) { - totalLength += file.length(); } - else { - totalLength += calculateDirectorySize(file); - } - if (file.lastModified() < lastModifiedTime) { - lastModifiedTime = file.lastModified(); - oldestFile = file; - } - } - if (oldestFile != null && totalLength >= AVConfig.config.getMaxSize() * 1000000000L) { - oldestFile.delete(); - } - else { - break; } - } - - - PlatformMethodWrapper.enableSaving(); - + } } @@ -195,5 +213,30 @@ public static long calculateDirectorySize(File directory) { return size; } + public static File getFirstBackupAfterDate(File directory, long date) { + File[] files = directory.listFiles(); + File oldestFile = null; + long currentDate = Long.MAX_VALUE; + if (files == null || files.length == 0) return null; + for (File file : files) { + if (file.lastModified() < currentDate && file.lastModified() > date) { + currentDate = file.lastModified(); + oldestFile = file; + } + } + return oldestFile; + } + + public static int calculateChainCount(File directory) { + int count = 0; + File[] files = directory.listFiles(); + if (files == null || files.length == 0) return 0; + for (File file : files) { + if (file.getName().contains("full")) { + count++; + } + } + return count; + } } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java index 5c01cd92..af32c954 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java @@ -32,7 +32,9 @@ public class AVConfig { "config.advancedbackups.chains.length", "config.advancedbackups.chains.compress", - "config.advancedbackups.chains.smart" + "config.advancedbackups.chains.smart", + + "config.advancedbackups.purge.incrementals" }; @@ -106,6 +108,8 @@ public static void loadConfig() { config.setCompressChains(props.getProperty("config.advancedbackups.chains.compress", "true")); config.setSmartChains(props.getProperty("config.advancedbackups.chains.smart", "true")); + config.setPurgeIncrementals(props.getProperty("config.advancedbackups.purge.incrementals", "false")); + String timingsString = config.getSchedule(); @@ -143,7 +147,7 @@ public static void loadConfig() { config.getMaxTimer(), config.getUptimeSchedule(), config.getSchedule(), config.getForceOnShutdown(), config.getStartupDelay(), config.getStartupDelay(), config.getSilent(), config.getCompressionLevel(), config.getMaxDepth(), - config.getCompressChains(), config.getSmartChains() + config.getCompressChains(), config.getSmartChains(), config.getPurgeIncrementals() )); writer.close(); } catch (IOException e) { diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java index 3b8b8d0e..95f82824 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java @@ -77,6 +77,10 @@ public class ConfigData { // Smart chain resetting. // TRUE OR FALSE + private boolean purgeIncrementals; + // Whether to purge incremental backups if over the limit. + // TRUE OR FALSE + public Boolean getEnabled() { return enabled; } @@ -221,6 +225,15 @@ public boolean getSmartChains() { public void setSmartChains(String smartChains) { this.smartChains = Boolean.parseBoolean(smartChains); } + + + public boolean getPurgeIncrementals() { + return purgeIncrementals; + } + + public void setPurgeIncrementals(String purgeIncrementals) { + this.purgeIncrementals = Boolean.parseBoolean(purgeIncrementals); + } @@ -320,7 +333,13 @@ public void setSmartChains(String smartChains) { "", "#Whether to enable \"smart\" reset for chains - if every file is being backed up, mark the backup as complete and reset chain length regardless of intended backup type.", "#Options : true, false #Default : true", -"config.advancedbackups.chains.smart=%s" +"config.advancedbackups.chains.smart=%s", +"", +"#Whether to delete incremental backup chains if max size is exceeded. If not, incremental backups do not respect the max size config and never delete.", +"#Options : true, false #Default : false", +"config.advancedbackups.purge.incrementals=%s" + + ); public static final String defaults = String.format(plainConfig, @@ -329,6 +348,7 @@ public void setSmartChains(String smartChains) { "0.5", "24", "true", "12:00", "false", "false", "5", "false", "4", - "50", "true", "true"); + "50", "true", "true", + "false"); } From b32fdabc95638f251fed7cbc6909d85b954676d4 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Thu, 15 Jun 2023 14:51:21 +0000 Subject: [PATCH 117/580] Update core files --- .../core/backups/BackupWrapper.java | 111 ++++++++++++------ .../advancedbackups/core/config/AVConfig.java | 8 +- .../core/config/ConfigData.java | 24 +++- 3 files changed, 105 insertions(+), 38 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java index 59b9f97f..afa9e309 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java @@ -129,54 +129,72 @@ public static void makeSingleBackup(long delay) { public static void finishBackup() { File directory = new File(AVConfig.config.getPath()); ThreadedBackup.running = false; + PlatformMethodWrapper.enableSaving(); switch(AVConfig.config.getBackupType()) { case "zip" : { directory = new File(directory, "/zips/"); - break; + long date = Long.MIN_VALUE; + while (true) { + if (calculateDirectorySize(directory) < AVConfig.config.getMaxSize() * 1000000000L) return; + File file = getFirstBackupAfterDate(directory, date); + date = file.lastModified(); + file.delete(); + } } case "differential" : { directory = new File(directory, "/differential/"); - break; + long date = Long.MIN_VALUE; + while (true) { + if (calculateDirectorySize(directory) < AVConfig.config.getMaxSize() * 1000000000L) return; + File file = getFirstBackupAfterDate(directory, date); + date = file.lastModified(); + if (file.getName().contains("full")) { + File nextFile = getFirstBackupAfterDate(directory, date); + if (nextFile.getName().contains("partial")) { + nextFile.delete(); + } + else { + file.delete(); + } + } + else { + file.delete(); + } + + } } case "incremental" : { directory = new File(directory, "/incremental/"); - break; - } + if (!AVConfig.config.getPurgeIncrementals()) return; + long date = Long.MIN_VALUE; + while (true) { + if (calculateDirectorySize(directory) < AVConfig.config.getMaxSize() * 1000000000L) return; + if (calculateChainCount(directory) < 2) return; + PlatformMethodWrapper.errorLogger.accept("Purging incremental backup chain - too much space taken up!"); + File file = getFirstBackupAfterDate(directory, date); + date = file.lastModified(); + if (file.getName().contains("full")) { + file.delete(); + while (true) { + file = getFirstBackupAfterDate(directory, date); + date = file.lastModified(); + if (file.getName().contains("full")) { + file.delete(); + } + else { + break; + } + } + } + else { + file.delete(); + } - } - - while (true) - { - File[] files = directory.listFiles(); - File oldestFile = null; - long totalLength = 0; - long lastModifiedTime = Long.MAX_VALUE; - if (files == null || files.length == 0) break; - for (File file : files) { - if (file.isFile()) { - totalLength += file.length(); } - else { - totalLength += calculateDirectorySize(file); - } - if (file.lastModified() < lastModifiedTime) { - lastModifiedTime = file.lastModified(); - oldestFile = file; - } - } - if (oldestFile != null && totalLength >= AVConfig.config.getMaxSize() * 1000000000L) { - oldestFile.delete(); - } - else { - break; } - } - - - PlatformMethodWrapper.enableSaving(); - + } } @@ -195,5 +213,30 @@ public static long calculateDirectorySize(File directory) { return size; } + public static File getFirstBackupAfterDate(File directory, long date) { + File[] files = directory.listFiles(); + File oldestFile = null; + long currentDate = Long.MAX_VALUE; + if (files == null || files.length == 0) return null; + for (File file : files) { + if (file.lastModified() < currentDate && file.lastModified() > date) { + currentDate = file.lastModified(); + oldestFile = file; + } + } + return oldestFile; + } + + public static int calculateChainCount(File directory) { + int count = 0; + File[] files = directory.listFiles(); + if (files == null || files.length == 0) return 0; + for (File file : files) { + if (file.getName().contains("full")) { + count++; + } + } + return count; + } } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java index 5c01cd92..af32c954 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java @@ -32,7 +32,9 @@ public class AVConfig { "config.advancedbackups.chains.length", "config.advancedbackups.chains.compress", - "config.advancedbackups.chains.smart" + "config.advancedbackups.chains.smart", + + "config.advancedbackups.purge.incrementals" }; @@ -106,6 +108,8 @@ public static void loadConfig() { config.setCompressChains(props.getProperty("config.advancedbackups.chains.compress", "true")); config.setSmartChains(props.getProperty("config.advancedbackups.chains.smart", "true")); + config.setPurgeIncrementals(props.getProperty("config.advancedbackups.purge.incrementals", "false")); + String timingsString = config.getSchedule(); @@ -143,7 +147,7 @@ public static void loadConfig() { config.getMaxTimer(), config.getUptimeSchedule(), config.getSchedule(), config.getForceOnShutdown(), config.getStartupDelay(), config.getStartupDelay(), config.getSilent(), config.getCompressionLevel(), config.getMaxDepth(), - config.getCompressChains(), config.getSmartChains() + config.getCompressChains(), config.getSmartChains(), config.getPurgeIncrementals() )); writer.close(); } catch (IOException e) { diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java index 3b8b8d0e..95f82824 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java @@ -77,6 +77,10 @@ public class ConfigData { // Smart chain resetting. // TRUE OR FALSE + private boolean purgeIncrementals; + // Whether to purge incremental backups if over the limit. + // TRUE OR FALSE + public Boolean getEnabled() { return enabled; } @@ -221,6 +225,15 @@ public boolean getSmartChains() { public void setSmartChains(String smartChains) { this.smartChains = Boolean.parseBoolean(smartChains); } + + + public boolean getPurgeIncrementals() { + return purgeIncrementals; + } + + public void setPurgeIncrementals(String purgeIncrementals) { + this.purgeIncrementals = Boolean.parseBoolean(purgeIncrementals); + } @@ -320,7 +333,13 @@ public void setSmartChains(String smartChains) { "", "#Whether to enable \"smart\" reset for chains - if every file is being backed up, mark the backup as complete and reset chain length regardless of intended backup type.", "#Options : true, false #Default : true", -"config.advancedbackups.chains.smart=%s" +"config.advancedbackups.chains.smart=%s", +"", +"#Whether to delete incremental backup chains if max size is exceeded. If not, incremental backups do not respect the max size config and never delete.", +"#Options : true, false #Default : false", +"config.advancedbackups.purge.incrementals=%s" + + ); public static final String defaults = String.format(plainConfig, @@ -329,6 +348,7 @@ public void setSmartChains(String smartChains) { "0.5", "24", "true", "12:00", "false", "false", "5", "false", "4", - "50", "true", "true"); + "50", "true", "true", + "false"); } From caa1feea01c5b8f33acfef878d85eb06db8386d1 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Thu, 15 Jun 2023 14:51:22 +0000 Subject: [PATCH 118/580] Update core files --- .../core/backups/BackupWrapper.java | 111 ++++++++++++------ .../advancedbackups/core/config/AVConfig.java | 8 +- .../core/config/ConfigData.java | 24 +++- 3 files changed, 105 insertions(+), 38 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java index 59b9f97f..afa9e309 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java @@ -129,54 +129,72 @@ public static void makeSingleBackup(long delay) { public static void finishBackup() { File directory = new File(AVConfig.config.getPath()); ThreadedBackup.running = false; + PlatformMethodWrapper.enableSaving(); switch(AVConfig.config.getBackupType()) { case "zip" : { directory = new File(directory, "/zips/"); - break; + long date = Long.MIN_VALUE; + while (true) { + if (calculateDirectorySize(directory) < AVConfig.config.getMaxSize() * 1000000000L) return; + File file = getFirstBackupAfterDate(directory, date); + date = file.lastModified(); + file.delete(); + } } case "differential" : { directory = new File(directory, "/differential/"); - break; + long date = Long.MIN_VALUE; + while (true) { + if (calculateDirectorySize(directory) < AVConfig.config.getMaxSize() * 1000000000L) return; + File file = getFirstBackupAfterDate(directory, date); + date = file.lastModified(); + if (file.getName().contains("full")) { + File nextFile = getFirstBackupAfterDate(directory, date); + if (nextFile.getName().contains("partial")) { + nextFile.delete(); + } + else { + file.delete(); + } + } + else { + file.delete(); + } + + } } case "incremental" : { directory = new File(directory, "/incremental/"); - break; - } + if (!AVConfig.config.getPurgeIncrementals()) return; + long date = Long.MIN_VALUE; + while (true) { + if (calculateDirectorySize(directory) < AVConfig.config.getMaxSize() * 1000000000L) return; + if (calculateChainCount(directory) < 2) return; + PlatformMethodWrapper.errorLogger.accept("Purging incremental backup chain - too much space taken up!"); + File file = getFirstBackupAfterDate(directory, date); + date = file.lastModified(); + if (file.getName().contains("full")) { + file.delete(); + while (true) { + file = getFirstBackupAfterDate(directory, date); + date = file.lastModified(); + if (file.getName().contains("full")) { + file.delete(); + } + else { + break; + } + } + } + else { + file.delete(); + } - } - - while (true) - { - File[] files = directory.listFiles(); - File oldestFile = null; - long totalLength = 0; - long lastModifiedTime = Long.MAX_VALUE; - if (files == null || files.length == 0) break; - for (File file : files) { - if (file.isFile()) { - totalLength += file.length(); } - else { - totalLength += calculateDirectorySize(file); - } - if (file.lastModified() < lastModifiedTime) { - lastModifiedTime = file.lastModified(); - oldestFile = file; - } - } - if (oldestFile != null && totalLength >= AVConfig.config.getMaxSize() * 1000000000L) { - oldestFile.delete(); - } - else { - break; } - } - - - PlatformMethodWrapper.enableSaving(); - + } } @@ -195,5 +213,30 @@ public static long calculateDirectorySize(File directory) { return size; } + public static File getFirstBackupAfterDate(File directory, long date) { + File[] files = directory.listFiles(); + File oldestFile = null; + long currentDate = Long.MAX_VALUE; + if (files == null || files.length == 0) return null; + for (File file : files) { + if (file.lastModified() < currentDate && file.lastModified() > date) { + currentDate = file.lastModified(); + oldestFile = file; + } + } + return oldestFile; + } + + public static int calculateChainCount(File directory) { + int count = 0; + File[] files = directory.listFiles(); + if (files == null || files.length == 0) return 0; + for (File file : files) { + if (file.getName().contains("full")) { + count++; + } + } + return count; + } } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java index 5c01cd92..af32c954 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java @@ -32,7 +32,9 @@ public class AVConfig { "config.advancedbackups.chains.length", "config.advancedbackups.chains.compress", - "config.advancedbackups.chains.smart" + "config.advancedbackups.chains.smart", + + "config.advancedbackups.purge.incrementals" }; @@ -106,6 +108,8 @@ public static void loadConfig() { config.setCompressChains(props.getProperty("config.advancedbackups.chains.compress", "true")); config.setSmartChains(props.getProperty("config.advancedbackups.chains.smart", "true")); + config.setPurgeIncrementals(props.getProperty("config.advancedbackups.purge.incrementals", "false")); + String timingsString = config.getSchedule(); @@ -143,7 +147,7 @@ public static void loadConfig() { config.getMaxTimer(), config.getUptimeSchedule(), config.getSchedule(), config.getForceOnShutdown(), config.getStartupDelay(), config.getStartupDelay(), config.getSilent(), config.getCompressionLevel(), config.getMaxDepth(), - config.getCompressChains(), config.getSmartChains() + config.getCompressChains(), config.getSmartChains(), config.getPurgeIncrementals() )); writer.close(); } catch (IOException e) { diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java index 3b8b8d0e..95f82824 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java @@ -77,6 +77,10 @@ public class ConfigData { // Smart chain resetting. // TRUE OR FALSE + private boolean purgeIncrementals; + // Whether to purge incremental backups if over the limit. + // TRUE OR FALSE + public Boolean getEnabled() { return enabled; } @@ -221,6 +225,15 @@ public boolean getSmartChains() { public void setSmartChains(String smartChains) { this.smartChains = Boolean.parseBoolean(smartChains); } + + + public boolean getPurgeIncrementals() { + return purgeIncrementals; + } + + public void setPurgeIncrementals(String purgeIncrementals) { + this.purgeIncrementals = Boolean.parseBoolean(purgeIncrementals); + } @@ -320,7 +333,13 @@ public void setSmartChains(String smartChains) { "", "#Whether to enable \"smart\" reset for chains - if every file is being backed up, mark the backup as complete and reset chain length regardless of intended backup type.", "#Options : true, false #Default : true", -"config.advancedbackups.chains.smart=%s" +"config.advancedbackups.chains.smart=%s", +"", +"#Whether to delete incremental backup chains if max size is exceeded. If not, incremental backups do not respect the max size config and never delete.", +"#Options : true, false #Default : false", +"config.advancedbackups.purge.incrementals=%s" + + ); public static final String defaults = String.format(plainConfig, @@ -329,6 +348,7 @@ public void setSmartChains(String smartChains) { "0.5", "24", "true", "12:00", "false", "false", "5", "false", "4", - "50", "true", "true"); + "50", "true", "true", + "false"); } From 7a94dafed0d8e9748afff1e1979a7a2686000afd Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Thu, 15 Jun 2023 14:51:23 +0000 Subject: [PATCH 119/580] Update core files --- .../core/backups/BackupWrapper.java | 111 ++++++++++++------ .../advancedbackups/core/config/AVConfig.java | 8 +- .../core/config/ConfigData.java | 24 +++- 3 files changed, 105 insertions(+), 38 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java index 59b9f97f..afa9e309 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java @@ -129,54 +129,72 @@ public static void makeSingleBackup(long delay) { public static void finishBackup() { File directory = new File(AVConfig.config.getPath()); ThreadedBackup.running = false; + PlatformMethodWrapper.enableSaving(); switch(AVConfig.config.getBackupType()) { case "zip" : { directory = new File(directory, "/zips/"); - break; + long date = Long.MIN_VALUE; + while (true) { + if (calculateDirectorySize(directory) < AVConfig.config.getMaxSize() * 1000000000L) return; + File file = getFirstBackupAfterDate(directory, date); + date = file.lastModified(); + file.delete(); + } } case "differential" : { directory = new File(directory, "/differential/"); - break; + long date = Long.MIN_VALUE; + while (true) { + if (calculateDirectorySize(directory) < AVConfig.config.getMaxSize() * 1000000000L) return; + File file = getFirstBackupAfterDate(directory, date); + date = file.lastModified(); + if (file.getName().contains("full")) { + File nextFile = getFirstBackupAfterDate(directory, date); + if (nextFile.getName().contains("partial")) { + nextFile.delete(); + } + else { + file.delete(); + } + } + else { + file.delete(); + } + + } } case "incremental" : { directory = new File(directory, "/incremental/"); - break; - } + if (!AVConfig.config.getPurgeIncrementals()) return; + long date = Long.MIN_VALUE; + while (true) { + if (calculateDirectorySize(directory) < AVConfig.config.getMaxSize() * 1000000000L) return; + if (calculateChainCount(directory) < 2) return; + PlatformMethodWrapper.errorLogger.accept("Purging incremental backup chain - too much space taken up!"); + File file = getFirstBackupAfterDate(directory, date); + date = file.lastModified(); + if (file.getName().contains("full")) { + file.delete(); + while (true) { + file = getFirstBackupAfterDate(directory, date); + date = file.lastModified(); + if (file.getName().contains("full")) { + file.delete(); + } + else { + break; + } + } + } + else { + file.delete(); + } - } - - while (true) - { - File[] files = directory.listFiles(); - File oldestFile = null; - long totalLength = 0; - long lastModifiedTime = Long.MAX_VALUE; - if (files == null || files.length == 0) break; - for (File file : files) { - if (file.isFile()) { - totalLength += file.length(); } - else { - totalLength += calculateDirectorySize(file); - } - if (file.lastModified() < lastModifiedTime) { - lastModifiedTime = file.lastModified(); - oldestFile = file; - } - } - if (oldestFile != null && totalLength >= AVConfig.config.getMaxSize() * 1000000000L) { - oldestFile.delete(); - } - else { - break; } - } - - - PlatformMethodWrapper.enableSaving(); - + } } @@ -195,5 +213,30 @@ public static long calculateDirectorySize(File directory) { return size; } + public static File getFirstBackupAfterDate(File directory, long date) { + File[] files = directory.listFiles(); + File oldestFile = null; + long currentDate = Long.MAX_VALUE; + if (files == null || files.length == 0) return null; + for (File file : files) { + if (file.lastModified() < currentDate && file.lastModified() > date) { + currentDate = file.lastModified(); + oldestFile = file; + } + } + return oldestFile; + } + + public static int calculateChainCount(File directory) { + int count = 0; + File[] files = directory.listFiles(); + if (files == null || files.length == 0) return 0; + for (File file : files) { + if (file.getName().contains("full")) { + count++; + } + } + return count; + } } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java index 5c01cd92..af32c954 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java @@ -32,7 +32,9 @@ public class AVConfig { "config.advancedbackups.chains.length", "config.advancedbackups.chains.compress", - "config.advancedbackups.chains.smart" + "config.advancedbackups.chains.smart", + + "config.advancedbackups.purge.incrementals" }; @@ -106,6 +108,8 @@ public static void loadConfig() { config.setCompressChains(props.getProperty("config.advancedbackups.chains.compress", "true")); config.setSmartChains(props.getProperty("config.advancedbackups.chains.smart", "true")); + config.setPurgeIncrementals(props.getProperty("config.advancedbackups.purge.incrementals", "false")); + String timingsString = config.getSchedule(); @@ -143,7 +147,7 @@ public static void loadConfig() { config.getMaxTimer(), config.getUptimeSchedule(), config.getSchedule(), config.getForceOnShutdown(), config.getStartupDelay(), config.getStartupDelay(), config.getSilent(), config.getCompressionLevel(), config.getMaxDepth(), - config.getCompressChains(), config.getSmartChains() + config.getCompressChains(), config.getSmartChains(), config.getPurgeIncrementals() )); writer.close(); } catch (IOException e) { diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java index 3b8b8d0e..95f82824 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java @@ -77,6 +77,10 @@ public class ConfigData { // Smart chain resetting. // TRUE OR FALSE + private boolean purgeIncrementals; + // Whether to purge incremental backups if over the limit. + // TRUE OR FALSE + public Boolean getEnabled() { return enabled; } @@ -221,6 +225,15 @@ public boolean getSmartChains() { public void setSmartChains(String smartChains) { this.smartChains = Boolean.parseBoolean(smartChains); } + + + public boolean getPurgeIncrementals() { + return purgeIncrementals; + } + + public void setPurgeIncrementals(String purgeIncrementals) { + this.purgeIncrementals = Boolean.parseBoolean(purgeIncrementals); + } @@ -320,7 +333,13 @@ public void setSmartChains(String smartChains) { "", "#Whether to enable \"smart\" reset for chains - if every file is being backed up, mark the backup as complete and reset chain length regardless of intended backup type.", "#Options : true, false #Default : true", -"config.advancedbackups.chains.smart=%s" +"config.advancedbackups.chains.smart=%s", +"", +"#Whether to delete incremental backup chains if max size is exceeded. If not, incremental backups do not respect the max size config and never delete.", +"#Options : true, false #Default : false", +"config.advancedbackups.purge.incrementals=%s" + + ); public static final String defaults = String.format(plainConfig, @@ -329,6 +348,7 @@ public void setSmartChains(String smartChains) { "0.5", "24", "true", "12:00", "false", "false", "5", "false", "4", - "50", "true", "true"); + "50", "true", "true", + "false"); } From 23ef1ddaedbcaad1a4cf17c500ff5d4d2908cc4e Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Thu, 15 Jun 2023 14:55:42 +0000 Subject: [PATCH 120/580] Update core files --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index ff837637..f3bc4002 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,7 @@ Many Minecraft versions are supported - request more if the one you want isn't y | config.advancedbackups.chains.length | The maximum chain length for incremental and differential backups. | 50 | 0.3 | | config.advancedbackups.chains.compress | Whether to compress incremental and differential backups into zip files. | true | 0.3 | | config.advancedbackups.chains.smart | For differential and incremental backups. Resets the chain length if every file is being backed up. | true | 0.3 | +| config.advancedbackups.purge.incremental | For incremental backups only. Enable to allow purging incremental backup chains if the defined storage usage is limit exceeded. | false | 1.0 | #### Commands: From 40aaece4114487de91b487a601ca885ccd8c467e Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Thu, 15 Jun 2023 14:55:43 +0000 Subject: [PATCH 121/580] Update core files --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index ff837637..f3bc4002 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,7 @@ Many Minecraft versions are supported - request more if the one you want isn't y | config.advancedbackups.chains.length | The maximum chain length for incremental and differential backups. | 50 | 0.3 | | config.advancedbackups.chains.compress | Whether to compress incremental and differential backups into zip files. | true | 0.3 | | config.advancedbackups.chains.smart | For differential and incremental backups. Resets the chain length if every file is being backed up. | true | 0.3 | +| config.advancedbackups.purge.incremental | For incremental backups only. Enable to allow purging incremental backup chains if the defined storage usage is limit exceeded. | false | 1.0 | #### Commands: From 373207025b7b27cde4bfd77d8db08aa4edf261ec Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Thu, 15 Jun 2023 14:55:44 +0000 Subject: [PATCH 122/580] Update core files --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index ff837637..f3bc4002 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,7 @@ Many Minecraft versions are supported - request more if the one you want isn't y | config.advancedbackups.chains.length | The maximum chain length for incremental and differential backups. | 50 | 0.3 | | config.advancedbackups.chains.compress | Whether to compress incremental and differential backups into zip files. | true | 0.3 | | config.advancedbackups.chains.smart | For differential and incremental backups. Resets the chain length if every file is being backed up. | true | 0.3 | +| config.advancedbackups.purge.incremental | For incremental backups only. Enable to allow purging incremental backup chains if the defined storage usage is limit exceeded. | false | 1.0 | #### Commands: From 1070a542d3177e07606b9353b5df267fc7eb4af8 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Thu, 15 Jun 2023 14:55:46 +0000 Subject: [PATCH 123/580] Update core files --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index ff837637..f3bc4002 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,7 @@ Many Minecraft versions are supported - request more if the one you want isn't y | config.advancedbackups.chains.length | The maximum chain length for incremental and differential backups. | 50 | 0.3 | | config.advancedbackups.chains.compress | Whether to compress incremental and differential backups into zip files. | true | 0.3 | | config.advancedbackups.chains.smart | For differential and incremental backups. Resets the chain length if every file is being backed up. | true | 0.3 | +| config.advancedbackups.purge.incremental | For incremental backups only. Enable to allow purging incremental backup chains if the defined storage usage is limit exceeded. | false | 1.0 | #### Commands: From fd569acaff41ea3d6ef3a1f97816aaa84ae833c8 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Thu, 15 Jun 2023 14:55:47 +0000 Subject: [PATCH 124/580] Update core files --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index ff837637..f3bc4002 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,7 @@ Many Minecraft versions are supported - request more if the one you want isn't y | config.advancedbackups.chains.length | The maximum chain length for incremental and differential backups. | 50 | 0.3 | | config.advancedbackups.chains.compress | Whether to compress incremental and differential backups into zip files. | true | 0.3 | | config.advancedbackups.chains.smart | For differential and incremental backups. Resets the chain length if every file is being backed up. | true | 0.3 | +| config.advancedbackups.purge.incremental | For incremental backups only. Enable to allow purging incremental backup chains if the defined storage usage is limit exceeded. | false | 1.0 | #### Commands: From e6419fdf91d7ff0f2018f5ec9af9229ef3f02399 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Thu, 15 Jun 2023 16:06:37 +0000 Subject: [PATCH 125/580] Update core files --- .../core/CoreCommandSystem.java | 41 +++++++++++++++++++ .../core/backups/ThreadedBackup.java | 25 ++++++++--- .../advancedbackups/core/config/AVConfig.java | 2 + .../core/config/ConfigData.java | 20 +++++++-- 4 files changed, 79 insertions(+), 9 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java index ae8a2fef..96c131a9 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java @@ -1,12 +1,27 @@ package co.uk.mommyheather.advancedbackups.core; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileWriter; +import java.nio.file.Files; import java.util.function.Consumer; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + import co.uk.mommyheather.advancedbackups.core.backups.BackupCheckEnum; import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; +import co.uk.mommyheather.advancedbackups.core.backups.gson.DifferentialManifest; import co.uk.mommyheather.advancedbackups.core.config.AVConfig; public class CoreCommandSystem { + private static GsonBuilder builder = new GsonBuilder(); + private static Gson gson; + static { + builder.setPrettyPrinting(); + gson = builder.create(); + } + //These methods are all called by relevant command classes in version specific code public static void checkBackups(Consumer chat) { @@ -33,4 +48,30 @@ public static void reloadConfig(Consumer chat) { AVConfig.loadConfig(); chat.accept("Done!"); } + + public static void resetChainLength(Consumer chat) { + chat.accept("Resetting chain length... The next backup will be a complete backup."); + boolean differential = AVConfig.config.getBackupType().equals("differential") ? true : false; + File manifestFile = differential ? new File(AVConfig.config.getPath() + "/differential/manifest.json") : new File(AVConfig.config.getPath() + "/incremental/manifest.json"); + DifferentialManifest manifest; + try { + if (manifestFile.exists()) { + manifest = gson.fromJson(new String(Files.readAllBytes(manifestFile.toPath())), DifferentialManifest.class); + manifest.setChain(manifest.getChain() + 1); + FileWriter writer = new FileWriter(manifestFile); + writer.write(gson.toJson(manifest)); + writer.flush(); + writer.close(); + chat.accept("Done!"); + return; + } + else { + chat.accept("No manifest file exists!"); + return; + } + } catch (Exception e) { + chat.accept("Error resetting chain length. - check logs for more info."); + e.printStackTrace(); + } + } } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java index 9ecedba7..423efe8a 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java @@ -28,6 +28,8 @@ public class ThreadedBackup extends Thread { private static Gson gson; private long delay; private static int count; + private static float partialSize; + private static float completeSize; public static boolean running = false; static { @@ -39,6 +41,8 @@ public ThreadedBackup(long delay) { setName("AB Active Backup Thread"); this.delay = delay; count = 0; + partialSize = 0F; + completeSize = 0F; } @Override @@ -131,8 +135,10 @@ private static void makeDifferentialOrIncrementalBackup(File location, boolean d long comp = differential ? manifest.getLastFull() : manifest.getLastPartial(); ArrayList toBackup = new ArrayList<>(); + ArrayList completeBackup = new ArrayList<>(); - boolean complete = manifest.getComplete().size() == 0 || manifest.getChain() >= AVConfig.config.getMaxDepth() ? true : false; + + boolean completeTemp = manifest.getComplete().size() == 0 || manifest.getChain() >= AVConfig.config.getMaxDepth() ? true : false; Files.walkFileTree(PlatformMethodWrapper.worldDir, new SimpleFileVisitor() { @Override @@ -143,19 +149,26 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { return FileVisitResult.CONTINUE; } count++; - if (complete || attributes.lastModifiedTime().toMillis() >= comp) { + completeSize += attributes.size(); + completeBackup.add(targetFile); + if (completeTemp || attributes.lastModifiedTime().toMillis() >= comp) { toBackup.add(targetFile); + partialSize += attributes.size(); } return FileVisitResult.CONTINUE; } }); - + boolean complete = completeTemp; if (toBackup.size() >= count) { - name += "-full"; + complete = true; } - else { - name += complete? "-full":"-partial"; + if ((partialSize / completeSize) * 100F > AVConfig.config.getMaxSizePercent()) { + complete = true; + toBackup.clear(); + toBackup.addAll(completeBackup); } + + name += complete? "-full":"-partial"; diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java index af32c954..3e66b8c0 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java @@ -33,6 +33,7 @@ public class AVConfig { "config.advancedbackups.chains.length", "config.advancedbackups.chains.compress", "config.advancedbackups.chains.smart", + "config.advancedbackups.chains.maxpercent", "config.advancedbackups.purge.incrementals" @@ -107,6 +108,7 @@ public static void loadConfig() { config.setMaxDepth(props.getProperty("config.advancedbackups.chains.length", "50")); config.setCompressChains(props.getProperty("config.advancedbackups.chains.compress", "true")); config.setSmartChains(props.getProperty("config.advancedbackups.chains.smart", "true")); + config.setMaxSizePercent(props.getProperty("config.advancedbackups.chains.maxpercent", "75")); config.setPurgeIncrementals(props.getProperty("config.advancedbackups.purge.incrementals", "false")); diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java index 95f82824..f5e7841f 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java @@ -1,7 +1,5 @@ package co.uk.mommyheather.advancedbackups.core.config; -import org.checkerframework.checker.units.qual.m; - public class ConfigData { private Boolean enabled; @@ -77,6 +75,10 @@ public class ConfigData { // Smart chain resetting. // TRUE OR FALSE + private int maxSizePercent; + // Resets chain length if what gets backed up is over the defined % size. + // 1-100 range. + private boolean purgeIncrementals; // Whether to purge incremental backups if over the limit. // TRUE OR FALSE @@ -234,6 +236,15 @@ public boolean getPurgeIncrementals() { public void setPurgeIncrementals(String purgeIncrementals) { this.purgeIncrementals = Boolean.parseBoolean(purgeIncrementals); } + + public int getMaxSizePercent() { + return maxSizePercent; + } + + public void setMaxSizePercent(String maxSizePercent) { + this.maxSizePercent = Integer.parseInt(maxSizePercent); + } + @@ -335,6 +346,9 @@ public void setPurgeIncrementals(String purgeIncrementals) { "#Options : true, false #Default : true", "config.advancedbackups.chains.smart=%s", "", +"#What % of a full backup is allowed to be contained in a partial before forcing it into a full backup. Useful for reducing partial backup size.", +"config.advancedbackups.chains.maxpercent=%s", +"", "#Whether to delete incremental backup chains if max size is exceeded. If not, incremental backups do not respect the max size config and never delete.", "#Options : true, false #Default : false", "config.advancedbackups.purge.incrementals=%s" @@ -349,6 +363,6 @@ public void setPurgeIncrementals(String purgeIncrementals) { "12:00", "false", "false", "5", "false", "4", "50", "true", "true", - "false"); + "75","false"); } From f74d4e1eaed2c86d069effabbfa6c50f4c1e2c28 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Thu, 15 Jun 2023 16:06:38 +0000 Subject: [PATCH 126/580] Update core files --- .../core/CoreCommandSystem.java | 41 +++++++++++++++++++ .../core/backups/ThreadedBackup.java | 25 ++++++++--- .../advancedbackups/core/config/AVConfig.java | 2 + .../core/config/ConfigData.java | 20 +++++++-- 4 files changed, 79 insertions(+), 9 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java index ae8a2fef..96c131a9 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java @@ -1,12 +1,27 @@ package co.uk.mommyheather.advancedbackups.core; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileWriter; +import java.nio.file.Files; import java.util.function.Consumer; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + import co.uk.mommyheather.advancedbackups.core.backups.BackupCheckEnum; import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; +import co.uk.mommyheather.advancedbackups.core.backups.gson.DifferentialManifest; import co.uk.mommyheather.advancedbackups.core.config.AVConfig; public class CoreCommandSystem { + private static GsonBuilder builder = new GsonBuilder(); + private static Gson gson; + static { + builder.setPrettyPrinting(); + gson = builder.create(); + } + //These methods are all called by relevant command classes in version specific code public static void checkBackups(Consumer chat) { @@ -33,4 +48,30 @@ public static void reloadConfig(Consumer chat) { AVConfig.loadConfig(); chat.accept("Done!"); } + + public static void resetChainLength(Consumer chat) { + chat.accept("Resetting chain length... The next backup will be a complete backup."); + boolean differential = AVConfig.config.getBackupType().equals("differential") ? true : false; + File manifestFile = differential ? new File(AVConfig.config.getPath() + "/differential/manifest.json") : new File(AVConfig.config.getPath() + "/incremental/manifest.json"); + DifferentialManifest manifest; + try { + if (manifestFile.exists()) { + manifest = gson.fromJson(new String(Files.readAllBytes(manifestFile.toPath())), DifferentialManifest.class); + manifest.setChain(manifest.getChain() + 1); + FileWriter writer = new FileWriter(manifestFile); + writer.write(gson.toJson(manifest)); + writer.flush(); + writer.close(); + chat.accept("Done!"); + return; + } + else { + chat.accept("No manifest file exists!"); + return; + } + } catch (Exception e) { + chat.accept("Error resetting chain length. - check logs for more info."); + e.printStackTrace(); + } + } } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java index 9ecedba7..423efe8a 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java @@ -28,6 +28,8 @@ public class ThreadedBackup extends Thread { private static Gson gson; private long delay; private static int count; + private static float partialSize; + private static float completeSize; public static boolean running = false; static { @@ -39,6 +41,8 @@ public ThreadedBackup(long delay) { setName("AB Active Backup Thread"); this.delay = delay; count = 0; + partialSize = 0F; + completeSize = 0F; } @Override @@ -131,8 +135,10 @@ private static void makeDifferentialOrIncrementalBackup(File location, boolean d long comp = differential ? manifest.getLastFull() : manifest.getLastPartial(); ArrayList toBackup = new ArrayList<>(); + ArrayList completeBackup = new ArrayList<>(); - boolean complete = manifest.getComplete().size() == 0 || manifest.getChain() >= AVConfig.config.getMaxDepth() ? true : false; + + boolean completeTemp = manifest.getComplete().size() == 0 || manifest.getChain() >= AVConfig.config.getMaxDepth() ? true : false; Files.walkFileTree(PlatformMethodWrapper.worldDir, new SimpleFileVisitor() { @Override @@ -143,19 +149,26 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { return FileVisitResult.CONTINUE; } count++; - if (complete || attributes.lastModifiedTime().toMillis() >= comp) { + completeSize += attributes.size(); + completeBackup.add(targetFile); + if (completeTemp || attributes.lastModifiedTime().toMillis() >= comp) { toBackup.add(targetFile); + partialSize += attributes.size(); } return FileVisitResult.CONTINUE; } }); - + boolean complete = completeTemp; if (toBackup.size() >= count) { - name += "-full"; + complete = true; } - else { - name += complete? "-full":"-partial"; + if ((partialSize / completeSize) * 100F > AVConfig.config.getMaxSizePercent()) { + complete = true; + toBackup.clear(); + toBackup.addAll(completeBackup); } + + name += complete? "-full":"-partial"; diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java index af32c954..3e66b8c0 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java @@ -33,6 +33,7 @@ public class AVConfig { "config.advancedbackups.chains.length", "config.advancedbackups.chains.compress", "config.advancedbackups.chains.smart", + "config.advancedbackups.chains.maxpercent", "config.advancedbackups.purge.incrementals" @@ -107,6 +108,7 @@ public static void loadConfig() { config.setMaxDepth(props.getProperty("config.advancedbackups.chains.length", "50")); config.setCompressChains(props.getProperty("config.advancedbackups.chains.compress", "true")); config.setSmartChains(props.getProperty("config.advancedbackups.chains.smart", "true")); + config.setMaxSizePercent(props.getProperty("config.advancedbackups.chains.maxpercent", "75")); config.setPurgeIncrementals(props.getProperty("config.advancedbackups.purge.incrementals", "false")); diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java index 95f82824..f5e7841f 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java @@ -1,7 +1,5 @@ package co.uk.mommyheather.advancedbackups.core.config; -import org.checkerframework.checker.units.qual.m; - public class ConfigData { private Boolean enabled; @@ -77,6 +75,10 @@ public class ConfigData { // Smart chain resetting. // TRUE OR FALSE + private int maxSizePercent; + // Resets chain length if what gets backed up is over the defined % size. + // 1-100 range. + private boolean purgeIncrementals; // Whether to purge incremental backups if over the limit. // TRUE OR FALSE @@ -234,6 +236,15 @@ public boolean getPurgeIncrementals() { public void setPurgeIncrementals(String purgeIncrementals) { this.purgeIncrementals = Boolean.parseBoolean(purgeIncrementals); } + + public int getMaxSizePercent() { + return maxSizePercent; + } + + public void setMaxSizePercent(String maxSizePercent) { + this.maxSizePercent = Integer.parseInt(maxSizePercent); + } + @@ -335,6 +346,9 @@ public void setPurgeIncrementals(String purgeIncrementals) { "#Options : true, false #Default : true", "config.advancedbackups.chains.smart=%s", "", +"#What % of a full backup is allowed to be contained in a partial before forcing it into a full backup. Useful for reducing partial backup size.", +"config.advancedbackups.chains.maxpercent=%s", +"", "#Whether to delete incremental backup chains if max size is exceeded. If not, incremental backups do not respect the max size config and never delete.", "#Options : true, false #Default : false", "config.advancedbackups.purge.incrementals=%s" @@ -349,6 +363,6 @@ public void setPurgeIncrementals(String purgeIncrementals) { "12:00", "false", "false", "5", "false", "4", "50", "true", "true", - "false"); + "75","false"); } From 4746c2dc612da7ed1cfe640de054f7457179a145 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Thu, 15 Jun 2023 16:06:39 +0000 Subject: [PATCH 127/580] Update core files --- .../core/CoreCommandSystem.java | 41 +++++++++++++++++++ .../core/backups/ThreadedBackup.java | 25 ++++++++--- .../advancedbackups/core/config/AVConfig.java | 2 + .../core/config/ConfigData.java | 20 +++++++-- 4 files changed, 79 insertions(+), 9 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java index ae8a2fef..96c131a9 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java @@ -1,12 +1,27 @@ package co.uk.mommyheather.advancedbackups.core; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileWriter; +import java.nio.file.Files; import java.util.function.Consumer; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + import co.uk.mommyheather.advancedbackups.core.backups.BackupCheckEnum; import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; +import co.uk.mommyheather.advancedbackups.core.backups.gson.DifferentialManifest; import co.uk.mommyheather.advancedbackups.core.config.AVConfig; public class CoreCommandSystem { + private static GsonBuilder builder = new GsonBuilder(); + private static Gson gson; + static { + builder.setPrettyPrinting(); + gson = builder.create(); + } + //These methods are all called by relevant command classes in version specific code public static void checkBackups(Consumer chat) { @@ -33,4 +48,30 @@ public static void reloadConfig(Consumer chat) { AVConfig.loadConfig(); chat.accept("Done!"); } + + public static void resetChainLength(Consumer chat) { + chat.accept("Resetting chain length... The next backup will be a complete backup."); + boolean differential = AVConfig.config.getBackupType().equals("differential") ? true : false; + File manifestFile = differential ? new File(AVConfig.config.getPath() + "/differential/manifest.json") : new File(AVConfig.config.getPath() + "/incremental/manifest.json"); + DifferentialManifest manifest; + try { + if (manifestFile.exists()) { + manifest = gson.fromJson(new String(Files.readAllBytes(manifestFile.toPath())), DifferentialManifest.class); + manifest.setChain(manifest.getChain() + 1); + FileWriter writer = new FileWriter(manifestFile); + writer.write(gson.toJson(manifest)); + writer.flush(); + writer.close(); + chat.accept("Done!"); + return; + } + else { + chat.accept("No manifest file exists!"); + return; + } + } catch (Exception e) { + chat.accept("Error resetting chain length. - check logs for more info."); + e.printStackTrace(); + } + } } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java index 9ecedba7..423efe8a 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java @@ -28,6 +28,8 @@ public class ThreadedBackup extends Thread { private static Gson gson; private long delay; private static int count; + private static float partialSize; + private static float completeSize; public static boolean running = false; static { @@ -39,6 +41,8 @@ public ThreadedBackup(long delay) { setName("AB Active Backup Thread"); this.delay = delay; count = 0; + partialSize = 0F; + completeSize = 0F; } @Override @@ -131,8 +135,10 @@ private static void makeDifferentialOrIncrementalBackup(File location, boolean d long comp = differential ? manifest.getLastFull() : manifest.getLastPartial(); ArrayList toBackup = new ArrayList<>(); + ArrayList completeBackup = new ArrayList<>(); - boolean complete = manifest.getComplete().size() == 0 || manifest.getChain() >= AVConfig.config.getMaxDepth() ? true : false; + + boolean completeTemp = manifest.getComplete().size() == 0 || manifest.getChain() >= AVConfig.config.getMaxDepth() ? true : false; Files.walkFileTree(PlatformMethodWrapper.worldDir, new SimpleFileVisitor() { @Override @@ -143,19 +149,26 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { return FileVisitResult.CONTINUE; } count++; - if (complete || attributes.lastModifiedTime().toMillis() >= comp) { + completeSize += attributes.size(); + completeBackup.add(targetFile); + if (completeTemp || attributes.lastModifiedTime().toMillis() >= comp) { toBackup.add(targetFile); + partialSize += attributes.size(); } return FileVisitResult.CONTINUE; } }); - + boolean complete = completeTemp; if (toBackup.size() >= count) { - name += "-full"; + complete = true; } - else { - name += complete? "-full":"-partial"; + if ((partialSize / completeSize) * 100F > AVConfig.config.getMaxSizePercent()) { + complete = true; + toBackup.clear(); + toBackup.addAll(completeBackup); } + + name += complete? "-full":"-partial"; diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java index af32c954..3e66b8c0 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java @@ -33,6 +33,7 @@ public class AVConfig { "config.advancedbackups.chains.length", "config.advancedbackups.chains.compress", "config.advancedbackups.chains.smart", + "config.advancedbackups.chains.maxpercent", "config.advancedbackups.purge.incrementals" @@ -107,6 +108,7 @@ public static void loadConfig() { config.setMaxDepth(props.getProperty("config.advancedbackups.chains.length", "50")); config.setCompressChains(props.getProperty("config.advancedbackups.chains.compress", "true")); config.setSmartChains(props.getProperty("config.advancedbackups.chains.smart", "true")); + config.setMaxSizePercent(props.getProperty("config.advancedbackups.chains.maxpercent", "75")); config.setPurgeIncrementals(props.getProperty("config.advancedbackups.purge.incrementals", "false")); diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java index 95f82824..f5e7841f 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java @@ -1,7 +1,5 @@ package co.uk.mommyheather.advancedbackups.core.config; -import org.checkerframework.checker.units.qual.m; - public class ConfigData { private Boolean enabled; @@ -77,6 +75,10 @@ public class ConfigData { // Smart chain resetting. // TRUE OR FALSE + private int maxSizePercent; + // Resets chain length if what gets backed up is over the defined % size. + // 1-100 range. + private boolean purgeIncrementals; // Whether to purge incremental backups if over the limit. // TRUE OR FALSE @@ -234,6 +236,15 @@ public boolean getPurgeIncrementals() { public void setPurgeIncrementals(String purgeIncrementals) { this.purgeIncrementals = Boolean.parseBoolean(purgeIncrementals); } + + public int getMaxSizePercent() { + return maxSizePercent; + } + + public void setMaxSizePercent(String maxSizePercent) { + this.maxSizePercent = Integer.parseInt(maxSizePercent); + } + @@ -335,6 +346,9 @@ public void setPurgeIncrementals(String purgeIncrementals) { "#Options : true, false #Default : true", "config.advancedbackups.chains.smart=%s", "", +"#What % of a full backup is allowed to be contained in a partial before forcing it into a full backup. Useful for reducing partial backup size.", +"config.advancedbackups.chains.maxpercent=%s", +"", "#Whether to delete incremental backup chains if max size is exceeded. If not, incremental backups do not respect the max size config and never delete.", "#Options : true, false #Default : false", "config.advancedbackups.purge.incrementals=%s" @@ -349,6 +363,6 @@ public void setPurgeIncrementals(String purgeIncrementals) { "12:00", "false", "false", "5", "false", "4", "50", "true", "true", - "false"); + "75","false"); } From 50d7fa88f1f6c1171de995137aa6584d19e41cce Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Thu, 15 Jun 2023 16:06:40 +0000 Subject: [PATCH 128/580] Update core files --- .../core/CoreCommandSystem.java | 41 +++++++++++++++++++ .../core/backups/ThreadedBackup.java | 25 ++++++++--- .../advancedbackups/core/config/AVConfig.java | 2 + .../core/config/ConfigData.java | 20 +++++++-- 4 files changed, 79 insertions(+), 9 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java index ae8a2fef..96c131a9 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java @@ -1,12 +1,27 @@ package co.uk.mommyheather.advancedbackups.core; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileWriter; +import java.nio.file.Files; import java.util.function.Consumer; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + import co.uk.mommyheather.advancedbackups.core.backups.BackupCheckEnum; import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; +import co.uk.mommyheather.advancedbackups.core.backups.gson.DifferentialManifest; import co.uk.mommyheather.advancedbackups.core.config.AVConfig; public class CoreCommandSystem { + private static GsonBuilder builder = new GsonBuilder(); + private static Gson gson; + static { + builder.setPrettyPrinting(); + gson = builder.create(); + } + //These methods are all called by relevant command classes in version specific code public static void checkBackups(Consumer chat) { @@ -33,4 +48,30 @@ public static void reloadConfig(Consumer chat) { AVConfig.loadConfig(); chat.accept("Done!"); } + + public static void resetChainLength(Consumer chat) { + chat.accept("Resetting chain length... The next backup will be a complete backup."); + boolean differential = AVConfig.config.getBackupType().equals("differential") ? true : false; + File manifestFile = differential ? new File(AVConfig.config.getPath() + "/differential/manifest.json") : new File(AVConfig.config.getPath() + "/incremental/manifest.json"); + DifferentialManifest manifest; + try { + if (manifestFile.exists()) { + manifest = gson.fromJson(new String(Files.readAllBytes(manifestFile.toPath())), DifferentialManifest.class); + manifest.setChain(manifest.getChain() + 1); + FileWriter writer = new FileWriter(manifestFile); + writer.write(gson.toJson(manifest)); + writer.flush(); + writer.close(); + chat.accept("Done!"); + return; + } + else { + chat.accept("No manifest file exists!"); + return; + } + } catch (Exception e) { + chat.accept("Error resetting chain length. - check logs for more info."); + e.printStackTrace(); + } + } } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java index 9ecedba7..423efe8a 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java @@ -28,6 +28,8 @@ public class ThreadedBackup extends Thread { private static Gson gson; private long delay; private static int count; + private static float partialSize; + private static float completeSize; public static boolean running = false; static { @@ -39,6 +41,8 @@ public ThreadedBackup(long delay) { setName("AB Active Backup Thread"); this.delay = delay; count = 0; + partialSize = 0F; + completeSize = 0F; } @Override @@ -131,8 +135,10 @@ private static void makeDifferentialOrIncrementalBackup(File location, boolean d long comp = differential ? manifest.getLastFull() : manifest.getLastPartial(); ArrayList toBackup = new ArrayList<>(); + ArrayList completeBackup = new ArrayList<>(); - boolean complete = manifest.getComplete().size() == 0 || manifest.getChain() >= AVConfig.config.getMaxDepth() ? true : false; + + boolean completeTemp = manifest.getComplete().size() == 0 || manifest.getChain() >= AVConfig.config.getMaxDepth() ? true : false; Files.walkFileTree(PlatformMethodWrapper.worldDir, new SimpleFileVisitor() { @Override @@ -143,19 +149,26 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { return FileVisitResult.CONTINUE; } count++; - if (complete || attributes.lastModifiedTime().toMillis() >= comp) { + completeSize += attributes.size(); + completeBackup.add(targetFile); + if (completeTemp || attributes.lastModifiedTime().toMillis() >= comp) { toBackup.add(targetFile); + partialSize += attributes.size(); } return FileVisitResult.CONTINUE; } }); - + boolean complete = completeTemp; if (toBackup.size() >= count) { - name += "-full"; + complete = true; } - else { - name += complete? "-full":"-partial"; + if ((partialSize / completeSize) * 100F > AVConfig.config.getMaxSizePercent()) { + complete = true; + toBackup.clear(); + toBackup.addAll(completeBackup); } + + name += complete? "-full":"-partial"; diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java index af32c954..3e66b8c0 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java @@ -33,6 +33,7 @@ public class AVConfig { "config.advancedbackups.chains.length", "config.advancedbackups.chains.compress", "config.advancedbackups.chains.smart", + "config.advancedbackups.chains.maxpercent", "config.advancedbackups.purge.incrementals" @@ -107,6 +108,7 @@ public static void loadConfig() { config.setMaxDepth(props.getProperty("config.advancedbackups.chains.length", "50")); config.setCompressChains(props.getProperty("config.advancedbackups.chains.compress", "true")); config.setSmartChains(props.getProperty("config.advancedbackups.chains.smart", "true")); + config.setMaxSizePercent(props.getProperty("config.advancedbackups.chains.maxpercent", "75")); config.setPurgeIncrementals(props.getProperty("config.advancedbackups.purge.incrementals", "false")); diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java index 95f82824..f5e7841f 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java @@ -1,7 +1,5 @@ package co.uk.mommyheather.advancedbackups.core.config; -import org.checkerframework.checker.units.qual.m; - public class ConfigData { private Boolean enabled; @@ -77,6 +75,10 @@ public class ConfigData { // Smart chain resetting. // TRUE OR FALSE + private int maxSizePercent; + // Resets chain length if what gets backed up is over the defined % size. + // 1-100 range. + private boolean purgeIncrementals; // Whether to purge incremental backups if over the limit. // TRUE OR FALSE @@ -234,6 +236,15 @@ public boolean getPurgeIncrementals() { public void setPurgeIncrementals(String purgeIncrementals) { this.purgeIncrementals = Boolean.parseBoolean(purgeIncrementals); } + + public int getMaxSizePercent() { + return maxSizePercent; + } + + public void setMaxSizePercent(String maxSizePercent) { + this.maxSizePercent = Integer.parseInt(maxSizePercent); + } + @@ -335,6 +346,9 @@ public void setPurgeIncrementals(String purgeIncrementals) { "#Options : true, false #Default : true", "config.advancedbackups.chains.smart=%s", "", +"#What % of a full backup is allowed to be contained in a partial before forcing it into a full backup. Useful for reducing partial backup size.", +"config.advancedbackups.chains.maxpercent=%s", +"", "#Whether to delete incremental backup chains if max size is exceeded. If not, incremental backups do not respect the max size config and never delete.", "#Options : true, false #Default : false", "config.advancedbackups.purge.incrementals=%s" @@ -349,6 +363,6 @@ public void setPurgeIncrementals(String purgeIncrementals) { "12:00", "false", "false", "5", "false", "4", "50", "true", "true", - "false"); + "75","false"); } From 4f3f81c586cef502f1dedd08a6152ac4353437a4 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Thu, 15 Jun 2023 16:06:41 +0000 Subject: [PATCH 129/580] Update core files --- .../core/CoreCommandSystem.java | 41 +++++++++++++++++++ .../core/backups/ThreadedBackup.java | 25 ++++++++--- .../advancedbackups/core/config/AVConfig.java | 2 + .../core/config/ConfigData.java | 20 +++++++-- 4 files changed, 79 insertions(+), 9 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java index ae8a2fef..96c131a9 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java @@ -1,12 +1,27 @@ package co.uk.mommyheather.advancedbackups.core; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileWriter; +import java.nio.file.Files; import java.util.function.Consumer; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + import co.uk.mommyheather.advancedbackups.core.backups.BackupCheckEnum; import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; +import co.uk.mommyheather.advancedbackups.core.backups.gson.DifferentialManifest; import co.uk.mommyheather.advancedbackups.core.config.AVConfig; public class CoreCommandSystem { + private static GsonBuilder builder = new GsonBuilder(); + private static Gson gson; + static { + builder.setPrettyPrinting(); + gson = builder.create(); + } + //These methods are all called by relevant command classes in version specific code public static void checkBackups(Consumer chat) { @@ -33,4 +48,30 @@ public static void reloadConfig(Consumer chat) { AVConfig.loadConfig(); chat.accept("Done!"); } + + public static void resetChainLength(Consumer chat) { + chat.accept("Resetting chain length... The next backup will be a complete backup."); + boolean differential = AVConfig.config.getBackupType().equals("differential") ? true : false; + File manifestFile = differential ? new File(AVConfig.config.getPath() + "/differential/manifest.json") : new File(AVConfig.config.getPath() + "/incremental/manifest.json"); + DifferentialManifest manifest; + try { + if (manifestFile.exists()) { + manifest = gson.fromJson(new String(Files.readAllBytes(manifestFile.toPath())), DifferentialManifest.class); + manifest.setChain(manifest.getChain() + 1); + FileWriter writer = new FileWriter(manifestFile); + writer.write(gson.toJson(manifest)); + writer.flush(); + writer.close(); + chat.accept("Done!"); + return; + } + else { + chat.accept("No manifest file exists!"); + return; + } + } catch (Exception e) { + chat.accept("Error resetting chain length. - check logs for more info."); + e.printStackTrace(); + } + } } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java index 9ecedba7..423efe8a 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java @@ -28,6 +28,8 @@ public class ThreadedBackup extends Thread { private static Gson gson; private long delay; private static int count; + private static float partialSize; + private static float completeSize; public static boolean running = false; static { @@ -39,6 +41,8 @@ public ThreadedBackup(long delay) { setName("AB Active Backup Thread"); this.delay = delay; count = 0; + partialSize = 0F; + completeSize = 0F; } @Override @@ -131,8 +135,10 @@ private static void makeDifferentialOrIncrementalBackup(File location, boolean d long comp = differential ? manifest.getLastFull() : manifest.getLastPartial(); ArrayList toBackup = new ArrayList<>(); + ArrayList completeBackup = new ArrayList<>(); - boolean complete = manifest.getComplete().size() == 0 || manifest.getChain() >= AVConfig.config.getMaxDepth() ? true : false; + + boolean completeTemp = manifest.getComplete().size() == 0 || manifest.getChain() >= AVConfig.config.getMaxDepth() ? true : false; Files.walkFileTree(PlatformMethodWrapper.worldDir, new SimpleFileVisitor() { @Override @@ -143,19 +149,26 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { return FileVisitResult.CONTINUE; } count++; - if (complete || attributes.lastModifiedTime().toMillis() >= comp) { + completeSize += attributes.size(); + completeBackup.add(targetFile); + if (completeTemp || attributes.lastModifiedTime().toMillis() >= comp) { toBackup.add(targetFile); + partialSize += attributes.size(); } return FileVisitResult.CONTINUE; } }); - + boolean complete = completeTemp; if (toBackup.size() >= count) { - name += "-full"; + complete = true; } - else { - name += complete? "-full":"-partial"; + if ((partialSize / completeSize) * 100F > AVConfig.config.getMaxSizePercent()) { + complete = true; + toBackup.clear(); + toBackup.addAll(completeBackup); } + + name += complete? "-full":"-partial"; diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java index af32c954..3e66b8c0 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java @@ -33,6 +33,7 @@ public class AVConfig { "config.advancedbackups.chains.length", "config.advancedbackups.chains.compress", "config.advancedbackups.chains.smart", + "config.advancedbackups.chains.maxpercent", "config.advancedbackups.purge.incrementals" @@ -107,6 +108,7 @@ public static void loadConfig() { config.setMaxDepth(props.getProperty("config.advancedbackups.chains.length", "50")); config.setCompressChains(props.getProperty("config.advancedbackups.chains.compress", "true")); config.setSmartChains(props.getProperty("config.advancedbackups.chains.smart", "true")); + config.setMaxSizePercent(props.getProperty("config.advancedbackups.chains.maxpercent", "75")); config.setPurgeIncrementals(props.getProperty("config.advancedbackups.purge.incrementals", "false")); diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java index 95f82824..f5e7841f 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java @@ -1,7 +1,5 @@ package co.uk.mommyheather.advancedbackups.core.config; -import org.checkerframework.checker.units.qual.m; - public class ConfigData { private Boolean enabled; @@ -77,6 +75,10 @@ public class ConfigData { // Smart chain resetting. // TRUE OR FALSE + private int maxSizePercent; + // Resets chain length if what gets backed up is over the defined % size. + // 1-100 range. + private boolean purgeIncrementals; // Whether to purge incremental backups if over the limit. // TRUE OR FALSE @@ -234,6 +236,15 @@ public boolean getPurgeIncrementals() { public void setPurgeIncrementals(String purgeIncrementals) { this.purgeIncrementals = Boolean.parseBoolean(purgeIncrementals); } + + public int getMaxSizePercent() { + return maxSizePercent; + } + + public void setMaxSizePercent(String maxSizePercent) { + this.maxSizePercent = Integer.parseInt(maxSizePercent); + } + @@ -335,6 +346,9 @@ public void setPurgeIncrementals(String purgeIncrementals) { "#Options : true, false #Default : true", "config.advancedbackups.chains.smart=%s", "", +"#What % of a full backup is allowed to be contained in a partial before forcing it into a full backup. Useful for reducing partial backup size.", +"config.advancedbackups.chains.maxpercent=%s", +"", "#Whether to delete incremental backup chains if max size is exceeded. If not, incremental backups do not respect the max size config and never delete.", "#Options : true, false #Default : false", "config.advancedbackups.purge.incrementals=%s" @@ -349,6 +363,6 @@ public void setPurgeIncrementals(String purgeIncrementals) { "12:00", "false", "false", "5", "false", "4", "50", "true", "true", - "false"); + "75","false"); } From 8b4777d7d2c5a601a53d7eb35b645b46c306172f Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Thu, 15 Jun 2023 16:07:49 +0000 Subject: [PATCH 130/580] Update core files --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index f3bc4002..f6ce15c5 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,7 @@ Many Minecraft versions are supported - request more if the one you want isn't y | start | Starts a backup if all checks pass. Tells you check results.| 1.0 | | reload | Reloads the config.| 1.0 | | force-backup | Forces a backup without running any checks.| 1.0 | +| reset-chain | Resets any current chain length.| 1.0 | ### Commandline: From c50fcf2aa1dab4d4456daf02b70b4737db9bf931 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Thu, 15 Jun 2023 16:07:50 +0000 Subject: [PATCH 131/580] Update core files --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index f3bc4002..f6ce15c5 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,7 @@ Many Minecraft versions are supported - request more if the one you want isn't y | start | Starts a backup if all checks pass. Tells you check results.| 1.0 | | reload | Reloads the config.| 1.0 | | force-backup | Forces a backup without running any checks.| 1.0 | +| reset-chain | Resets any current chain length.| 1.0 | ### Commandline: From 0613f8fcf8fedb06f005b636053a7df1115aed20 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Thu, 15 Jun 2023 16:07:51 +0000 Subject: [PATCH 132/580] Update core files --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index f3bc4002..f6ce15c5 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,7 @@ Many Minecraft versions are supported - request more if the one you want isn't y | start | Starts a backup if all checks pass. Tells you check results.| 1.0 | | reload | Reloads the config.| 1.0 | | force-backup | Forces a backup without running any checks.| 1.0 | +| reset-chain | Resets any current chain length.| 1.0 | ### Commandline: From c1606310cf9b274f4a3a4ecdaecbda022c1860df Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Thu, 15 Jun 2023 16:07:53 +0000 Subject: [PATCH 133/580] Update core files --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index f3bc4002..f6ce15c5 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,7 @@ Many Minecraft versions are supported - request more if the one you want isn't y | start | Starts a backup if all checks pass. Tells you check results.| 1.0 | | reload | Reloads the config.| 1.0 | | force-backup | Forces a backup without running any checks.| 1.0 | +| reset-chain | Resets any current chain length.| 1.0 | ### Commandline: From b090ca7a4939eff7ccb51e0c37c375d354abbf60 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Thu, 15 Jun 2023 16:07:54 +0000 Subject: [PATCH 134/580] Update core files --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index f3bc4002..f6ce15c5 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,7 @@ Many Minecraft versions are supported - request more if the one you want isn't y | start | Starts a backup if all checks pass. Tells you check results.| 1.0 | | reload | Reloads the config.| 1.0 | | force-backup | Forces a backup without running any checks.| 1.0 | +| reset-chain | Resets any current chain length.| 1.0 | ### Commandline: From 9a431abb056bb51efc9ff1f65363bca0d3a6a483 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Thu, 15 Jun 2023 16:11:57 +0000 Subject: [PATCH 135/580] Update core files --- .../uk/mommyheather/advancedbackups/core/CoreCommandSystem.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java index 96c131a9..76e59aef 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java @@ -57,7 +57,7 @@ public static void resetChainLength(Consumer chat) { try { if (manifestFile.exists()) { manifest = gson.fromJson(new String(Files.readAllBytes(manifestFile.toPath())), DifferentialManifest.class); - manifest.setChain(manifest.getChain() + 1); + manifest.setChain(manifest.getChain() + AVConfig.config.getMaxDepth()); FileWriter writer = new FileWriter(manifestFile); writer.write(gson.toJson(manifest)); writer.flush(); From 54858605c1866ab96eb957b86e33cb82f2a39edf Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Thu, 15 Jun 2023 16:11:58 +0000 Subject: [PATCH 136/580] Update core files --- .../uk/mommyheather/advancedbackups/core/CoreCommandSystem.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java index 96c131a9..76e59aef 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java @@ -57,7 +57,7 @@ public static void resetChainLength(Consumer chat) { try { if (manifestFile.exists()) { manifest = gson.fromJson(new String(Files.readAllBytes(manifestFile.toPath())), DifferentialManifest.class); - manifest.setChain(manifest.getChain() + 1); + manifest.setChain(manifest.getChain() + AVConfig.config.getMaxDepth()); FileWriter writer = new FileWriter(manifestFile); writer.write(gson.toJson(manifest)); writer.flush(); From 033e0f7032ac0f54cb3e6525d93a09b6f4f6cdc5 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Thu, 15 Jun 2023 16:12:00 +0000 Subject: [PATCH 137/580] Update core files --- .../uk/mommyheather/advancedbackups/core/CoreCommandSystem.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java index 96c131a9..76e59aef 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java @@ -57,7 +57,7 @@ public static void resetChainLength(Consumer chat) { try { if (manifestFile.exists()) { manifest = gson.fromJson(new String(Files.readAllBytes(manifestFile.toPath())), DifferentialManifest.class); - manifest.setChain(manifest.getChain() + 1); + manifest.setChain(manifest.getChain() + AVConfig.config.getMaxDepth()); FileWriter writer = new FileWriter(manifestFile); writer.write(gson.toJson(manifest)); writer.flush(); From 212a04abee5387fddca7fdc5726cdc556ebba572 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Thu, 15 Jun 2023 16:12:01 +0000 Subject: [PATCH 138/580] Update core files --- .../uk/mommyheather/advancedbackups/core/CoreCommandSystem.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java index 96c131a9..76e59aef 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java @@ -57,7 +57,7 @@ public static void resetChainLength(Consumer chat) { try { if (manifestFile.exists()) { manifest = gson.fromJson(new String(Files.readAllBytes(manifestFile.toPath())), DifferentialManifest.class); - manifest.setChain(manifest.getChain() + 1); + manifest.setChain(manifest.getChain() + AVConfig.config.getMaxDepth()); FileWriter writer = new FileWriter(manifestFile); writer.write(gson.toJson(manifest)); writer.flush(); From 09ca94d0f31177fa8cadfd214eddae940126820c Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Thu, 15 Jun 2023 16:12:03 +0000 Subject: [PATCH 139/580] Update core files --- .../uk/mommyheather/advancedbackups/core/CoreCommandSystem.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java index 96c131a9..76e59aef 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java @@ -57,7 +57,7 @@ public static void resetChainLength(Consumer chat) { try { if (manifestFile.exists()) { manifest = gson.fromJson(new String(Files.readAllBytes(manifestFile.toPath())), DifferentialManifest.class); - manifest.setChain(manifest.getChain() + 1); + manifest.setChain(manifest.getChain() + AVConfig.config.getMaxDepth()); FileWriter writer = new FileWriter(manifestFile); writer.write(gson.toJson(manifest)); writer.flush(); From 8c099ea990e4ecc13fb0244d91a63ebd92b10b8b Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Fri, 16 Jun 2023 13:07:38 +0000 Subject: [PATCH 140/580] Update core files --- .../cli/AdvancedBackupsCLI.java | 48 +++++++++++++++---- 1 file changed, 38 insertions(+), 10 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java index a0bc2b23..09424dc9 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java @@ -282,21 +282,49 @@ private static File getWorldFile() { ret = new File(ret, "/saves/"); } - ret = new File(ret, getWorldName()); + ret = new File(ret, getWorldName(ret)); return ret; } - private static String getWorldName() { - - - info("Please enter your world name. Default for servers is \"world\"."); - String line = input.nextLine(); - if (line == "") { - warn("Please enter a name."); - return getWorldName(); + private static String getWorldName(File dir) { + ArrayList worlds = new ArrayList<>(); + int worldIndex; + for (File file : dir.listFiles()) { + boolean flag = false; + if (!file.isDirectory()) continue; + for (File file2 : file.listFiles()) { + if (file2.getName().contains("level.dat")) { + flag = true; + } + } + if (flag) { + worlds.add(file.getName()); + } + } + info("Please select your world. Default for servers is \"world\"."); + int index = 1; + for (String world : worlds) { + info (index + ". " + world); + index++; + } + try { + String line = input.nextLine(); + if (line == "") { + warn("Please enter a number."); + return getWorldName(dir); + } + worldIndex = Integer.parseInt(line); + } catch (InputMismatchException | NumberFormatException e) { + warn("That was not a number. Please enter a number."); + return getWorldName(dir); } - return line; + if (worldIndex < 1 || worldIndex > worlds.size()) { + warn("Please enter a number between " + worlds.size() + "."); + return getWorldName(dir); + } + + return worlds.get(worldIndex - 1); } From 8ce5657760c2b4fda4ccba88fb063eed9fbe8d6d Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Fri, 16 Jun 2023 13:07:39 +0000 Subject: [PATCH 141/580] Update core files --- .../cli/AdvancedBackupsCLI.java | 48 +++++++++++++++---- 1 file changed, 38 insertions(+), 10 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java index a0bc2b23..09424dc9 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java @@ -282,21 +282,49 @@ private static File getWorldFile() { ret = new File(ret, "/saves/"); } - ret = new File(ret, getWorldName()); + ret = new File(ret, getWorldName(ret)); return ret; } - private static String getWorldName() { - - - info("Please enter your world name. Default for servers is \"world\"."); - String line = input.nextLine(); - if (line == "") { - warn("Please enter a name."); - return getWorldName(); + private static String getWorldName(File dir) { + ArrayList worlds = new ArrayList<>(); + int worldIndex; + for (File file : dir.listFiles()) { + boolean flag = false; + if (!file.isDirectory()) continue; + for (File file2 : file.listFiles()) { + if (file2.getName().contains("level.dat")) { + flag = true; + } + } + if (flag) { + worlds.add(file.getName()); + } + } + info("Please select your world. Default for servers is \"world\"."); + int index = 1; + for (String world : worlds) { + info (index + ". " + world); + index++; + } + try { + String line = input.nextLine(); + if (line == "") { + warn("Please enter a number."); + return getWorldName(dir); + } + worldIndex = Integer.parseInt(line); + } catch (InputMismatchException | NumberFormatException e) { + warn("That was not a number. Please enter a number."); + return getWorldName(dir); } - return line; + if (worldIndex < 1 || worldIndex > worlds.size()) { + warn("Please enter a number between " + worlds.size() + "."); + return getWorldName(dir); + } + + return worlds.get(worldIndex - 1); } From a0beae2f29268d45bd90f680e0a77a413919d9cf Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Fri, 16 Jun 2023 13:07:40 +0000 Subject: [PATCH 142/580] Update core files --- .../cli/AdvancedBackupsCLI.java | 48 +++++++++++++++---- 1 file changed, 38 insertions(+), 10 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java index a0bc2b23..09424dc9 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java @@ -282,21 +282,49 @@ private static File getWorldFile() { ret = new File(ret, "/saves/"); } - ret = new File(ret, getWorldName()); + ret = new File(ret, getWorldName(ret)); return ret; } - private static String getWorldName() { - - - info("Please enter your world name. Default for servers is \"world\"."); - String line = input.nextLine(); - if (line == "") { - warn("Please enter a name."); - return getWorldName(); + private static String getWorldName(File dir) { + ArrayList worlds = new ArrayList<>(); + int worldIndex; + for (File file : dir.listFiles()) { + boolean flag = false; + if (!file.isDirectory()) continue; + for (File file2 : file.listFiles()) { + if (file2.getName().contains("level.dat")) { + flag = true; + } + } + if (flag) { + worlds.add(file.getName()); + } + } + info("Please select your world. Default for servers is \"world\"."); + int index = 1; + for (String world : worlds) { + info (index + ". " + world); + index++; + } + try { + String line = input.nextLine(); + if (line == "") { + warn("Please enter a number."); + return getWorldName(dir); + } + worldIndex = Integer.parseInt(line); + } catch (InputMismatchException | NumberFormatException e) { + warn("That was not a number. Please enter a number."); + return getWorldName(dir); } - return line; + if (worldIndex < 1 || worldIndex > worlds.size()) { + warn("Please enter a number between " + worlds.size() + "."); + return getWorldName(dir); + } + + return worlds.get(worldIndex - 1); } From 44c2ced25549677da75a73a3d3ed13e889a603f2 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Fri, 16 Jun 2023 13:07:41 +0000 Subject: [PATCH 143/580] Update core files --- .../cli/AdvancedBackupsCLI.java | 48 +++++++++++++++---- 1 file changed, 38 insertions(+), 10 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java index a0bc2b23..09424dc9 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java @@ -282,21 +282,49 @@ private static File getWorldFile() { ret = new File(ret, "/saves/"); } - ret = new File(ret, getWorldName()); + ret = new File(ret, getWorldName(ret)); return ret; } - private static String getWorldName() { - - - info("Please enter your world name. Default for servers is \"world\"."); - String line = input.nextLine(); - if (line == "") { - warn("Please enter a name."); - return getWorldName(); + private static String getWorldName(File dir) { + ArrayList worlds = new ArrayList<>(); + int worldIndex; + for (File file : dir.listFiles()) { + boolean flag = false; + if (!file.isDirectory()) continue; + for (File file2 : file.listFiles()) { + if (file2.getName().contains("level.dat")) { + flag = true; + } + } + if (flag) { + worlds.add(file.getName()); + } + } + info("Please select your world. Default for servers is \"world\"."); + int index = 1; + for (String world : worlds) { + info (index + ". " + world); + index++; + } + try { + String line = input.nextLine(); + if (line == "") { + warn("Please enter a number."); + return getWorldName(dir); + } + worldIndex = Integer.parseInt(line); + } catch (InputMismatchException | NumberFormatException e) { + warn("That was not a number. Please enter a number."); + return getWorldName(dir); } - return line; + if (worldIndex < 1 || worldIndex > worlds.size()) { + warn("Please enter a number between " + worlds.size() + "."); + return getWorldName(dir); + } + + return worlds.get(worldIndex - 1); } From d248d54195e62d4c67ecaf34ada03ac746ea3d8d Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Fri, 16 Jun 2023 13:07:42 +0000 Subject: [PATCH 144/580] Update core files --- .../cli/AdvancedBackupsCLI.java | 48 +++++++++++++++---- 1 file changed, 38 insertions(+), 10 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java index a0bc2b23..09424dc9 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java @@ -282,21 +282,49 @@ private static File getWorldFile() { ret = new File(ret, "/saves/"); } - ret = new File(ret, getWorldName()); + ret = new File(ret, getWorldName(ret)); return ret; } - private static String getWorldName() { - - - info("Please enter your world name. Default for servers is \"world\"."); - String line = input.nextLine(); - if (line == "") { - warn("Please enter a name."); - return getWorldName(); + private static String getWorldName(File dir) { + ArrayList worlds = new ArrayList<>(); + int worldIndex; + for (File file : dir.listFiles()) { + boolean flag = false; + if (!file.isDirectory()) continue; + for (File file2 : file.listFiles()) { + if (file2.getName().contains("level.dat")) { + flag = true; + } + } + if (flag) { + worlds.add(file.getName()); + } + } + info("Please select your world. Default for servers is \"world\"."); + int index = 1; + for (String world : worlds) { + info (index + ". " + world); + index++; + } + try { + String line = input.nextLine(); + if (line == "") { + warn("Please enter a number."); + return getWorldName(dir); + } + worldIndex = Integer.parseInt(line); + } catch (InputMismatchException | NumberFormatException e) { + warn("That was not a number. Please enter a number."); + return getWorldName(dir); } - return line; + if (worldIndex < 1 || worldIndex > worlds.size()) { + warn("Please enter a number between " + worlds.size() + "."); + return getWorldName(dir); + } + + return worlds.get(worldIndex - 1); } From 176441ff44b6326848ad99bfdd61f73cd945644c Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Fri, 16 Jun 2023 13:14:15 +0000 Subject: [PATCH 145/580] Update core files --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index f6ce15c5..822b8d9a 100644 --- a/README.md +++ b/README.md @@ -124,6 +124,7 @@ Once you select a file, it will be restored. The program will then exit. - [Profiles](profiles) - [More Commands](more-commands) - [Client Feedback](client-feedback) +- [Commandline Improvements](commandline) ## Profiles @@ -165,3 +166,12 @@ Having some client feedback would allow connected clients that have the mod view This might be in the form of either a progress bar, or a simple percentage. Clients with the mod should have a way to opt out of this. + + +## Commandline + +Export feature : +- When asked whether restoring a singular file or the whole world, a third option will be present : export. +- This will package the backup into a singular zip file (...so yeah, just copy over the backup in the case of zip backups). +- It will leave the actual world intact. + From 95f29ad5e09e87630ce8f27e7c8f931e0da7da64 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Fri, 16 Jun 2023 13:14:16 +0000 Subject: [PATCH 146/580] Update core files --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index f6ce15c5..822b8d9a 100644 --- a/README.md +++ b/README.md @@ -124,6 +124,7 @@ Once you select a file, it will be restored. The program will then exit. - [Profiles](profiles) - [More Commands](more-commands) - [Client Feedback](client-feedback) +- [Commandline Improvements](commandline) ## Profiles @@ -165,3 +166,12 @@ Having some client feedback would allow connected clients that have the mod view This might be in the form of either a progress bar, or a simple percentage. Clients with the mod should have a way to opt out of this. + + +## Commandline + +Export feature : +- When asked whether restoring a singular file or the whole world, a third option will be present : export. +- This will package the backup into a singular zip file (...so yeah, just copy over the backup in the case of zip backups). +- It will leave the actual world intact. + From 80069ddb177afd417f00937813b3b87041908940 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Fri, 16 Jun 2023 13:14:17 +0000 Subject: [PATCH 147/580] Update core files --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index f6ce15c5..822b8d9a 100644 --- a/README.md +++ b/README.md @@ -124,6 +124,7 @@ Once you select a file, it will be restored. The program will then exit. - [Profiles](profiles) - [More Commands](more-commands) - [Client Feedback](client-feedback) +- [Commandline Improvements](commandline) ## Profiles @@ -165,3 +166,12 @@ Having some client feedback would allow connected clients that have the mod view This might be in the form of either a progress bar, or a simple percentage. Clients with the mod should have a way to opt out of this. + + +## Commandline + +Export feature : +- When asked whether restoring a singular file or the whole world, a third option will be present : export. +- This will package the backup into a singular zip file (...so yeah, just copy over the backup in the case of zip backups). +- It will leave the actual world intact. + From 19b92780748effb9087a11ae8b4eeb80ee622893 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Fri, 16 Jun 2023 13:14:17 +0000 Subject: [PATCH 148/580] Update core files --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index f6ce15c5..822b8d9a 100644 --- a/README.md +++ b/README.md @@ -124,6 +124,7 @@ Once you select a file, it will be restored. The program will then exit. - [Profiles](profiles) - [More Commands](more-commands) - [Client Feedback](client-feedback) +- [Commandline Improvements](commandline) ## Profiles @@ -165,3 +166,12 @@ Having some client feedback would allow connected clients that have the mod view This might be in the form of either a progress bar, or a simple percentage. Clients with the mod should have a way to opt out of this. + + +## Commandline + +Export feature : +- When asked whether restoring a singular file or the whole world, a third option will be present : export. +- This will package the backup into a singular zip file (...so yeah, just copy over the backup in the case of zip backups). +- It will leave the actual world intact. + From e9957fa32cffd35aa9148369d1d10420d5685936 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Fri, 16 Jun 2023 13:14:18 +0000 Subject: [PATCH 149/580] Update core files --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index f6ce15c5..822b8d9a 100644 --- a/README.md +++ b/README.md @@ -124,6 +124,7 @@ Once you select a file, it will be restored. The program will then exit. - [Profiles](profiles) - [More Commands](more-commands) - [Client Feedback](client-feedback) +- [Commandline Improvements](commandline) ## Profiles @@ -165,3 +166,12 @@ Having some client feedback would allow connected clients that have the mod view This might be in the form of either a progress bar, or a simple percentage. Clients with the mod should have a way to opt out of this. + + +## Commandline + +Export feature : +- When asked whether restoring a singular file or the whole world, a third option will be present : export. +- This will package the backup into a singular zip file (...so yeah, just copy over the backup in the case of zip backups). +- It will leave the actual world intact. + From b5bc053bfea27d4e997b817dc91df0bde7546ae2 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Fri, 16 Jun 2023 13:15:18 +0000 Subject: [PATCH 150/580] Update core files --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 822b8d9a..fcba28c6 100644 --- a/README.md +++ b/README.md @@ -121,10 +121,10 @@ Once you select a file, it will be restored. The program will then exit. # Future Plans: - Note : these are in no particular order. -- [Profiles](profiles) -- [More Commands](more-commands) -- [Client Feedback](client-feedback) -- [Commandline Improvements](commandline) +- [Profiles](#profiles) +- [More Commands](#more-commands) +- [Client Feedback](#client-feedback) +- [Commandline Improvements](#commandline) ## Profiles From 7b322aa8b1a80542cc667f82541e5b07089258da Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Fri, 16 Jun 2023 13:15:19 +0000 Subject: [PATCH 151/580] Update core files --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 822b8d9a..fcba28c6 100644 --- a/README.md +++ b/README.md @@ -121,10 +121,10 @@ Once you select a file, it will be restored. The program will then exit. # Future Plans: - Note : these are in no particular order. -- [Profiles](profiles) -- [More Commands](more-commands) -- [Client Feedback](client-feedback) -- [Commandline Improvements](commandline) +- [Profiles](#profiles) +- [More Commands](#more-commands) +- [Client Feedback](#client-feedback) +- [Commandline Improvements](#commandline) ## Profiles From 96f95d2487501a2e60b76688d0657bfd2da409ec Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Fri, 16 Jun 2023 13:15:20 +0000 Subject: [PATCH 152/580] Update core files --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 822b8d9a..fcba28c6 100644 --- a/README.md +++ b/README.md @@ -121,10 +121,10 @@ Once you select a file, it will be restored. The program will then exit. # Future Plans: - Note : these are in no particular order. -- [Profiles](profiles) -- [More Commands](more-commands) -- [Client Feedback](client-feedback) -- [Commandline Improvements](commandline) +- [Profiles](#profiles) +- [More Commands](#more-commands) +- [Client Feedback](#client-feedback) +- [Commandline Improvements](#commandline) ## Profiles From 944bdff07fc08304fd861ec6dc69783061ea6b26 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Fri, 16 Jun 2023 13:15:21 +0000 Subject: [PATCH 153/580] Update core files --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 822b8d9a..fcba28c6 100644 --- a/README.md +++ b/README.md @@ -121,10 +121,10 @@ Once you select a file, it will be restored. The program will then exit. # Future Plans: - Note : these are in no particular order. -- [Profiles](profiles) -- [More Commands](more-commands) -- [Client Feedback](client-feedback) -- [Commandline Improvements](commandline) +- [Profiles](#profiles) +- [More Commands](#more-commands) +- [Client Feedback](#client-feedback) +- [Commandline Improvements](#commandline) ## Profiles From 102839ebee38f6e29d547fb66d17bef3a6b17479 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Fri, 16 Jun 2023 13:15:22 +0000 Subject: [PATCH 154/580] Update core files --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 822b8d9a..fcba28c6 100644 --- a/README.md +++ b/README.md @@ -121,10 +121,10 @@ Once you select a file, it will be restored. The program will then exit. # Future Plans: - Note : these are in no particular order. -- [Profiles](profiles) -- [More Commands](more-commands) -- [Client Feedback](client-feedback) -- [Commandline Improvements](commandline) +- [Profiles](#profiles) +- [More Commands](#more-commands) +- [Client Feedback](#client-feedback) +- [Commandline Improvements](#commandline) ## Profiles From 8c348cfae35361b0fea8ebeb4579ee884a0cd76b Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Fri, 16 Jun 2023 13:15:45 +0000 Subject: [PATCH 155/580] Update core files --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index fcba28c6..8fe67530 100644 --- a/README.md +++ b/README.md @@ -124,7 +124,7 @@ Once you select a file, it will be restored. The program will then exit. - [Profiles](#profiles) - [More Commands](#more-commands) - [Client Feedback](#client-feedback) -- [Commandline Improvements](#commandline) +- [Commandline Improvements](#commandline-improvements) ## Profiles @@ -168,7 +168,7 @@ This might be in the form of either a progress bar, or a simple percentage. Clients with the mod should have a way to opt out of this. -## Commandline +## Commandline improvements Export feature : - When asked whether restoring a singular file or the whole world, a third option will be present : export. From 79b21583de12f885eb5ae7f420c2e070968a285e Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Fri, 16 Jun 2023 13:15:46 +0000 Subject: [PATCH 156/580] Update core files --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index fcba28c6..8fe67530 100644 --- a/README.md +++ b/README.md @@ -124,7 +124,7 @@ Once you select a file, it will be restored. The program will then exit. - [Profiles](#profiles) - [More Commands](#more-commands) - [Client Feedback](#client-feedback) -- [Commandline Improvements](#commandline) +- [Commandline Improvements](#commandline-improvements) ## Profiles @@ -168,7 +168,7 @@ This might be in the form of either a progress bar, or a simple percentage. Clients with the mod should have a way to opt out of this. -## Commandline +## Commandline improvements Export feature : - When asked whether restoring a singular file or the whole world, a third option will be present : export. From 14981f9c8de6f998e3a4d2c6f2fd57d0a666bb85 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Fri, 16 Jun 2023 13:15:47 +0000 Subject: [PATCH 157/580] Update core files --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index fcba28c6..8fe67530 100644 --- a/README.md +++ b/README.md @@ -124,7 +124,7 @@ Once you select a file, it will be restored. The program will then exit. - [Profiles](#profiles) - [More Commands](#more-commands) - [Client Feedback](#client-feedback) -- [Commandline Improvements](#commandline) +- [Commandline Improvements](#commandline-improvements) ## Profiles @@ -168,7 +168,7 @@ This might be in the form of either a progress bar, or a simple percentage. Clients with the mod should have a way to opt out of this. -## Commandline +## Commandline improvements Export feature : - When asked whether restoring a singular file or the whole world, a third option will be present : export. From f2f7e41e4a5475ea867f9fce4d3886e940594797 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Fri, 16 Jun 2023 13:15:48 +0000 Subject: [PATCH 158/580] Update core files --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index fcba28c6..8fe67530 100644 --- a/README.md +++ b/README.md @@ -124,7 +124,7 @@ Once you select a file, it will be restored. The program will then exit. - [Profiles](#profiles) - [More Commands](#more-commands) - [Client Feedback](#client-feedback) -- [Commandline Improvements](#commandline) +- [Commandline Improvements](#commandline-improvements) ## Profiles @@ -168,7 +168,7 @@ This might be in the form of either a progress bar, or a simple percentage. Clients with the mod should have a way to opt out of this. -## Commandline +## Commandline improvements Export feature : - When asked whether restoring a singular file or the whole world, a third option will be present : export. From 0c589988417611428fa1bfe091bc0ef374db9e77 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Fri, 16 Jun 2023 13:15:50 +0000 Subject: [PATCH 159/580] Update core files --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index fcba28c6..8fe67530 100644 --- a/README.md +++ b/README.md @@ -124,7 +124,7 @@ Once you select a file, it will be restored. The program will then exit. - [Profiles](#profiles) - [More Commands](#more-commands) - [Client Feedback](#client-feedback) -- [Commandline Improvements](#commandline) +- [Commandline Improvements](#commandline-improvements) ## Profiles @@ -168,7 +168,7 @@ This might be in the form of either a progress bar, or a simple percentage. Clients with the mod should have a way to opt out of this. -## Commandline +## Commandline improvements Export feature : - When asked whether restoring a singular file or the whole world, a third option will be present : export. From 623342e86fc1bc43780a26dde04ffed7fe1c5640 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Fri, 16 Jun 2023 13:31:58 +0000 Subject: [PATCH 160/580] Update core files --- .../cli/AdvancedBackupsCLI.java | 39 +++++++++++++++++++ .../core/backups/ThreadedBackup.java | 2 +- 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java index 09424dc9..b12d13d2 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java @@ -27,9 +27,12 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import java.util.zip.ZipInputStream; +import java.util.zip.ZipOutputStream; import org.fusesource.jansi.AnsiConsole; +import co.uk.mommyheather.advancedbackups.core.backups.ThreadedBackup; + public class AdvancedBackupsCLI { private static String backupLocation; @@ -753,6 +756,7 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) thro private static void deleteEntireWorld(File worldDir) { + backupExistingWorld(worldDir); try { Files.walkFileTree(worldDir.toPath(), new SimpleFileVisitor() { @Override @@ -775,6 +779,41 @@ public FileVisitResult postVisitDirectory(Path file, java.io.IOException arg1) { } } + private static void backupExistingWorld(File worldDir) { + try { + File out = new File(worldDir, "../cli" + ThreadedBackup.serialiseBackupName() + ".zip"); + FileOutputStream outputStream = new FileOutputStream(out); + ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream); + zipOutputStream.setLevel(4); + Files.walkFileTree(worldDir.toPath(), new SimpleFileVisitor() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { + Path targetFile; + try { + targetFile = worldDir.toPath().relativize(file); + if (targetFile.toFile().getName().compareTo("session.lock") == 0) { + return FileVisitResult.CONTINUE; + } + zipOutputStream.putNextEntry(new ZipEntry(targetFile.toString())); + byte[] bytes = Files.readAllBytes(file); + zipOutputStream.write(bytes, 0, bytes.length); + zipOutputStream.closeEntry(); + + } catch (IOException e) { + // TODO : Scream at user + e.printStackTrace(); + } + + return FileVisitResult.CONTINUE; + } + }); + zipOutputStream.flush(); + zipOutputStream.close(); + } catch (Exception e) { + + } + } + private static T getFileToRestore(HashMap files, String directory) { ArrayList toDisplay = new ArrayList<>(); diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java index 423efe8a..5165f7a7 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java @@ -228,7 +228,7 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { } - private static String serialiseBackupName() { + public static String serialiseBackupName() { Date date = new Date(); String pattern = "yyyy-MM-dd hh-mm-ss"; From 1b093d9ef1fb9edb39f7efadd10ea494149f23bc Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Fri, 16 Jun 2023 13:31:59 +0000 Subject: [PATCH 161/580] Update core files --- .../cli/AdvancedBackupsCLI.java | 39 +++++++++++++++++++ .../core/backups/ThreadedBackup.java | 2 +- 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java index 09424dc9..b12d13d2 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java @@ -27,9 +27,12 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import java.util.zip.ZipInputStream; +import java.util.zip.ZipOutputStream; import org.fusesource.jansi.AnsiConsole; +import co.uk.mommyheather.advancedbackups.core.backups.ThreadedBackup; + public class AdvancedBackupsCLI { private static String backupLocation; @@ -753,6 +756,7 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) thro private static void deleteEntireWorld(File worldDir) { + backupExistingWorld(worldDir); try { Files.walkFileTree(worldDir.toPath(), new SimpleFileVisitor() { @Override @@ -775,6 +779,41 @@ public FileVisitResult postVisitDirectory(Path file, java.io.IOException arg1) { } } + private static void backupExistingWorld(File worldDir) { + try { + File out = new File(worldDir, "../cli" + ThreadedBackup.serialiseBackupName() + ".zip"); + FileOutputStream outputStream = new FileOutputStream(out); + ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream); + zipOutputStream.setLevel(4); + Files.walkFileTree(worldDir.toPath(), new SimpleFileVisitor() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { + Path targetFile; + try { + targetFile = worldDir.toPath().relativize(file); + if (targetFile.toFile().getName().compareTo("session.lock") == 0) { + return FileVisitResult.CONTINUE; + } + zipOutputStream.putNextEntry(new ZipEntry(targetFile.toString())); + byte[] bytes = Files.readAllBytes(file); + zipOutputStream.write(bytes, 0, bytes.length); + zipOutputStream.closeEntry(); + + } catch (IOException e) { + // TODO : Scream at user + e.printStackTrace(); + } + + return FileVisitResult.CONTINUE; + } + }); + zipOutputStream.flush(); + zipOutputStream.close(); + } catch (Exception e) { + + } + } + private static T getFileToRestore(HashMap files, String directory) { ArrayList toDisplay = new ArrayList<>(); diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java index 423efe8a..5165f7a7 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java @@ -228,7 +228,7 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { } - private static String serialiseBackupName() { + public static String serialiseBackupName() { Date date = new Date(); String pattern = "yyyy-MM-dd hh-mm-ss"; From 82248155c87547d1ac11128d0f3a20c77382efbe Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Fri, 16 Jun 2023 13:32:01 +0000 Subject: [PATCH 162/580] Update core files --- .../cli/AdvancedBackupsCLI.java | 39 +++++++++++++++++++ .../core/backups/ThreadedBackup.java | 2 +- 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java index 09424dc9..b12d13d2 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java @@ -27,9 +27,12 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import java.util.zip.ZipInputStream; +import java.util.zip.ZipOutputStream; import org.fusesource.jansi.AnsiConsole; +import co.uk.mommyheather.advancedbackups.core.backups.ThreadedBackup; + public class AdvancedBackupsCLI { private static String backupLocation; @@ -753,6 +756,7 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) thro private static void deleteEntireWorld(File worldDir) { + backupExistingWorld(worldDir); try { Files.walkFileTree(worldDir.toPath(), new SimpleFileVisitor() { @Override @@ -775,6 +779,41 @@ public FileVisitResult postVisitDirectory(Path file, java.io.IOException arg1) { } } + private static void backupExistingWorld(File worldDir) { + try { + File out = new File(worldDir, "../cli" + ThreadedBackup.serialiseBackupName() + ".zip"); + FileOutputStream outputStream = new FileOutputStream(out); + ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream); + zipOutputStream.setLevel(4); + Files.walkFileTree(worldDir.toPath(), new SimpleFileVisitor() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { + Path targetFile; + try { + targetFile = worldDir.toPath().relativize(file); + if (targetFile.toFile().getName().compareTo("session.lock") == 0) { + return FileVisitResult.CONTINUE; + } + zipOutputStream.putNextEntry(new ZipEntry(targetFile.toString())); + byte[] bytes = Files.readAllBytes(file); + zipOutputStream.write(bytes, 0, bytes.length); + zipOutputStream.closeEntry(); + + } catch (IOException e) { + // TODO : Scream at user + e.printStackTrace(); + } + + return FileVisitResult.CONTINUE; + } + }); + zipOutputStream.flush(); + zipOutputStream.close(); + } catch (Exception e) { + + } + } + private static T getFileToRestore(HashMap files, String directory) { ArrayList toDisplay = new ArrayList<>(); diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java index 423efe8a..5165f7a7 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java @@ -228,7 +228,7 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { } - private static String serialiseBackupName() { + public static String serialiseBackupName() { Date date = new Date(); String pattern = "yyyy-MM-dd hh-mm-ss"; From c23b30a645e268cf2f7010d9798e7a1a92c08d10 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Fri, 16 Jun 2023 13:32:02 +0000 Subject: [PATCH 163/580] Update core files --- .../cli/AdvancedBackupsCLI.java | 39 +++++++++++++++++++ .../core/backups/ThreadedBackup.java | 2 +- 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java index 09424dc9..b12d13d2 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java @@ -27,9 +27,12 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import java.util.zip.ZipInputStream; +import java.util.zip.ZipOutputStream; import org.fusesource.jansi.AnsiConsole; +import co.uk.mommyheather.advancedbackups.core.backups.ThreadedBackup; + public class AdvancedBackupsCLI { private static String backupLocation; @@ -753,6 +756,7 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) thro private static void deleteEntireWorld(File worldDir) { + backupExistingWorld(worldDir); try { Files.walkFileTree(worldDir.toPath(), new SimpleFileVisitor() { @Override @@ -775,6 +779,41 @@ public FileVisitResult postVisitDirectory(Path file, java.io.IOException arg1) { } } + private static void backupExistingWorld(File worldDir) { + try { + File out = new File(worldDir, "../cli" + ThreadedBackup.serialiseBackupName() + ".zip"); + FileOutputStream outputStream = new FileOutputStream(out); + ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream); + zipOutputStream.setLevel(4); + Files.walkFileTree(worldDir.toPath(), new SimpleFileVisitor() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { + Path targetFile; + try { + targetFile = worldDir.toPath().relativize(file); + if (targetFile.toFile().getName().compareTo("session.lock") == 0) { + return FileVisitResult.CONTINUE; + } + zipOutputStream.putNextEntry(new ZipEntry(targetFile.toString())); + byte[] bytes = Files.readAllBytes(file); + zipOutputStream.write(bytes, 0, bytes.length); + zipOutputStream.closeEntry(); + + } catch (IOException e) { + // TODO : Scream at user + e.printStackTrace(); + } + + return FileVisitResult.CONTINUE; + } + }); + zipOutputStream.flush(); + zipOutputStream.close(); + } catch (Exception e) { + + } + } + private static T getFileToRestore(HashMap files, String directory) { ArrayList toDisplay = new ArrayList<>(); diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java index 423efe8a..5165f7a7 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java @@ -228,7 +228,7 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { } - private static String serialiseBackupName() { + public static String serialiseBackupName() { Date date = new Date(); String pattern = "yyyy-MM-dd hh-mm-ss"; From 366caa9e14ced88883fad2be24e568656e3f3f80 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Fri, 16 Jun 2023 13:32:03 +0000 Subject: [PATCH 164/580] Update core files --- .../cli/AdvancedBackupsCLI.java | 39 +++++++++++++++++++ .../core/backups/ThreadedBackup.java | 2 +- 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java index 09424dc9..b12d13d2 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java @@ -27,9 +27,12 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import java.util.zip.ZipInputStream; +import java.util.zip.ZipOutputStream; import org.fusesource.jansi.AnsiConsole; +import co.uk.mommyheather.advancedbackups.core.backups.ThreadedBackup; + public class AdvancedBackupsCLI { private static String backupLocation; @@ -753,6 +756,7 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) thro private static void deleteEntireWorld(File worldDir) { + backupExistingWorld(worldDir); try { Files.walkFileTree(worldDir.toPath(), new SimpleFileVisitor() { @Override @@ -775,6 +779,41 @@ public FileVisitResult postVisitDirectory(Path file, java.io.IOException arg1) { } } + private static void backupExistingWorld(File worldDir) { + try { + File out = new File(worldDir, "../cli" + ThreadedBackup.serialiseBackupName() + ".zip"); + FileOutputStream outputStream = new FileOutputStream(out); + ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream); + zipOutputStream.setLevel(4); + Files.walkFileTree(worldDir.toPath(), new SimpleFileVisitor() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { + Path targetFile; + try { + targetFile = worldDir.toPath().relativize(file); + if (targetFile.toFile().getName().compareTo("session.lock") == 0) { + return FileVisitResult.CONTINUE; + } + zipOutputStream.putNextEntry(new ZipEntry(targetFile.toString())); + byte[] bytes = Files.readAllBytes(file); + zipOutputStream.write(bytes, 0, bytes.length); + zipOutputStream.closeEntry(); + + } catch (IOException e) { + // TODO : Scream at user + e.printStackTrace(); + } + + return FileVisitResult.CONTINUE; + } + }); + zipOutputStream.flush(); + zipOutputStream.close(); + } catch (Exception e) { + + } + } + private static T getFileToRestore(HashMap files, String directory) { ArrayList toDisplay = new ArrayList<>(); diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java index 423efe8a..5165f7a7 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java @@ -228,7 +228,7 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { } - private static String serialiseBackupName() { + public static String serialiseBackupName() { Date date = new Date(); String pattern = "yyyy-MM-dd hh-mm-ss"; From 892a017aa66627de0aaad64b58db726f6e091066 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Fri, 16 Jun 2023 15:34:19 +0000 Subject: [PATCH 165/580] Update core files --- .../advancedbackups/core/config/AVConfig.java | 16 ++--- .../core/config/ConfigData.java | 68 +++++++++++-------- 2 files changed, 47 insertions(+), 37 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java index 3e66b8c0..b56eed0c 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java @@ -61,7 +61,7 @@ public static void initConfig() { file.setWritable(true); } FileWriter writer = new FileWriter(file); - writer.write(ConfigData.defaults); + writer.write(ConfigData.defaults()); writer.close(); } catch (IOException e) { // TODO : Scream to user @@ -143,13 +143,13 @@ public static void loadConfig() { newPropsFile.createNewFile(); } FileWriter writer = new FileWriter(newPropsFile); - writer.write(String.format(ConfigData.plainConfig, config.getEnabled(), - config.getSave(), config.getRequireActivity(), config.getBackupType(), - config.getPath(), config.getMaxSize(), config.getMinTimer(), - config.getMaxTimer(), config.getUptimeSchedule(), config.getSchedule(), - config.getForceOnShutdown(), config.getStartupDelay(), config.getStartupDelay(), - config.getSilent(), config.getCompressionLevel(), config.getMaxDepth(), - config.getCompressChains(), config.getSmartChains(), config.getPurgeIncrementals() + writer.write(ConfigData.config(config.getEnabled(), config.getSave(), + config.getRequireActivity(), config.getBackupType(), config.getPath(), + config.getMaxSize(), config.getMinTimer(), config.getMaxTimer(), + config.getUptimeSchedule(), config.getSchedule(), config.getForceOnShutdown(), + config.getForceOnStartup(), config.getStartupDelay(), config.getSilent(), + config.getCompressionLevel(), config.getMaxDepth(), config.getCompressChains(), + config.getSmartChains(), config.getMaxSizePercent(), config.getPurgeIncrementals() )); writer.close(); } catch (IOException e) { diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java index f5e7841f..ecf162c9 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java @@ -249,43 +249,50 @@ public void setMaxSizePercent(String maxSizePercent) { //default config output - can be ignored - public static final String plainConfig = String.join("\n", + public static String config(Object enabled, Object save, + Object activity, Object type, Object location, + Object size, Object min, Object max, + Object uptime, Object schedule, Object shutdown, + Object startup, Object delay, Object silent, + Object compression, Object chainLength, Object compressChains, + Object smartChains, Object maxPercent, Object purgeIncrementals) { + return String.join("\n", "#Enable or disable automatic backups.", "#Options : true, false #Default : true,", -"config.advancedbackups.enabled=%s", +"config.advancedbackups.enabled=" + enabled, "", "#Whether to save before making a backup.", "#Options : true, false #Default : false", -"config.advancedbackups.save=%s", +"config.advancedbackups.save=" + save, "", "#Whether to require player activity between backups.", "#Options : true, false #Default : false", -"config.advancedbackups.activity=%s", +"config.advancedbackups.activity=" + activity, "", "#The type of backups to use.", "#Options : zip, differential, incremental #Default : differential", -"config.advancedbackups.type=%s", +"config.advancedbackups.type=" + type, "", "#The absolute or relative path to the backup location.", "#Options : any file path. Default : ./backups", -"config.advancedbackups.path=%s", +"config.advancedbackups.path=" + location, "", "#The maximum size to keep, in GB. Keep relatively high for zips, tighter space requirements should instead use differential or incremental backups.", "#Range : 5 - 9999 #Default : 50", -"config.advancedbackups.size=%s", +"config.advancedbackups.size=" + size, "", "#Minimum time between backups, in hours. This can prevent a shutdown backup from triggering immediately after a scheduled backup or similar situations.", "#Range : 0.5 - 500 #Default : 0.5", -"config.advancedbackups.frequency.min=%s", +"config.advancedbackups.frequency.min=" + min, "", "#Triggers a backup if none has already happened within this time. Can be combined with an uptime-based schedule.", "#Range : 0.5 - 500 #Default : 24", -"config.advancedbackups.frequency.max=%s", +"config.advancedbackups.frequency.max=" + max, "", "#Whether the schedule below uses uptime (true) or real-world time (false).", "#Default : true", -"config.advancedbackups.frequency.uptime=%s", +"config.advancedbackups.frequency.uptime=" + uptime, "", "#When using server uptime:", " #A looping comma-separated backup schedule, based off of server uptime, hours:minutes. Examples:", @@ -300,23 +307,23 @@ public void setMaxSizePercent(String maxSizePercent) { " #4:00,8:00,12:00,16:00,17:00,18:00,19:00,20:00,21:00,24:00 - Makes a backup at specific times of day.", "", "#Default : 12:00", -"config.advancedbackups.frequency.schedule=%s", +"config.advancedbackups.frequency.schedule=" + schedule, "", "#Whether to force a backup on server shutdown. Respects min frequency.", "#Options : true, false #Default : false", -"config.advancedbackups.frequency.shutdown=%s", +"config.advancedbackups.frequency.shutdown=" + shutdown, "", "#Whether to force a backup on server startup. Respects min frequency.", "#Options : true, false #Default : false", -"config.advancedbackups.frequency.startup=%s", +"config.advancedbackups.frequency.startup=" + startup, "", "#Delay to use after startup, in seconds. Is always at least 5 seconds.", "#Range : 5-9999999999", -"config.advancedbackups.frequency.delay=%s", +"config.advancedbackups.frequency.delay=" + delay, "", "#Whether to disable console and chat logging. Does not affect debug.log, does not affect error messages.", "#Options : true, false #Default : false", -"config.advancedbackups.logging.silent=%s", +"config.advancedbackups.logging.silent=" + silent, "", "", "", @@ -326,7 +333,7 @@ public void setMaxSizePercent(String maxSizePercent) { "", "#The compression level to use for zip files. Higher numbers space usage, but decrease performance.", "#Range : 1-9 #Default : 4", -"config.advancedbackups.zips.compression=%s", +"config.advancedbackups.zips.compression=" + compression, "", "", "", @@ -336,33 +343,36 @@ public void setMaxSizePercent(String maxSizePercent) { "", "#The maximum 'chain' length to keep.", "#Range : 5-500 #Default : 50", -"config.advancedbackups.chains.length=%s", +"config.advancedbackups.chains.length=" + chainLength, "", "#Whether to compress 'chains'. This compresses the base backup and all sequential backups. Reduces space usage, but decreases performance.", "#Options : true, false #Default : true", -"config.advancedbackups.chains.compress=%s", +"config.advancedbackups.chains.compress=" + compressChains, "", "#Whether to enable \"smart\" reset for chains - if every file is being backed up, mark the backup as complete and reset chain length regardless of intended backup type.", "#Options : true, false #Default : true", -"config.advancedbackups.chains.smart=%s", +"config.advancedbackups.chains.smart=" + smartChains, "", "#What % of a full backup is allowed to be contained in a partial before forcing it into a full backup. Useful for reducing partial backup size.", -"config.advancedbackups.chains.maxpercent=%s", +"config.advancedbackups.chains.maxpercent=" + maxPercent, "", "#Whether to delete incremental backup chains if max size is exceeded. If not, incremental backups do not respect the max size config and never delete.", "#Options : true, false #Default : false", -"config.advancedbackups.purge.incrementals=%s" +"config.advancedbackups.purge.incrementals=" + purgeIncrementals ); + } - public static final String defaults = String.format(plainConfig, - "true", "false", "false", - "differential", "./backups", "50", - "0.5", "24", "true", - "12:00", "false", "false", - "5", "false", "4", - "50", "true", "true", - "75","false"); + public static String defaults() { + return config( + "true", "false", "false", + "differential", "./backups", "50", + "0.5", "24", "true", + "12:00", "false", "false", + "5", "false", "4", + "50", "true", "true", + "75","false"); + } } From fc427639bd0fc477f8931c129552fedca8aba34d Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Fri, 16 Jun 2023 15:34:20 +0000 Subject: [PATCH 166/580] Update core files --- .../advancedbackups/core/config/AVConfig.java | 16 ++--- .../core/config/ConfigData.java | 68 +++++++++++-------- 2 files changed, 47 insertions(+), 37 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java index 3e66b8c0..b56eed0c 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java @@ -61,7 +61,7 @@ public static void initConfig() { file.setWritable(true); } FileWriter writer = new FileWriter(file); - writer.write(ConfigData.defaults); + writer.write(ConfigData.defaults()); writer.close(); } catch (IOException e) { // TODO : Scream to user @@ -143,13 +143,13 @@ public static void loadConfig() { newPropsFile.createNewFile(); } FileWriter writer = new FileWriter(newPropsFile); - writer.write(String.format(ConfigData.plainConfig, config.getEnabled(), - config.getSave(), config.getRequireActivity(), config.getBackupType(), - config.getPath(), config.getMaxSize(), config.getMinTimer(), - config.getMaxTimer(), config.getUptimeSchedule(), config.getSchedule(), - config.getForceOnShutdown(), config.getStartupDelay(), config.getStartupDelay(), - config.getSilent(), config.getCompressionLevel(), config.getMaxDepth(), - config.getCompressChains(), config.getSmartChains(), config.getPurgeIncrementals() + writer.write(ConfigData.config(config.getEnabled(), config.getSave(), + config.getRequireActivity(), config.getBackupType(), config.getPath(), + config.getMaxSize(), config.getMinTimer(), config.getMaxTimer(), + config.getUptimeSchedule(), config.getSchedule(), config.getForceOnShutdown(), + config.getForceOnStartup(), config.getStartupDelay(), config.getSilent(), + config.getCompressionLevel(), config.getMaxDepth(), config.getCompressChains(), + config.getSmartChains(), config.getMaxSizePercent(), config.getPurgeIncrementals() )); writer.close(); } catch (IOException e) { diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java index f5e7841f..ecf162c9 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java @@ -249,43 +249,50 @@ public void setMaxSizePercent(String maxSizePercent) { //default config output - can be ignored - public static final String plainConfig = String.join("\n", + public static String config(Object enabled, Object save, + Object activity, Object type, Object location, + Object size, Object min, Object max, + Object uptime, Object schedule, Object shutdown, + Object startup, Object delay, Object silent, + Object compression, Object chainLength, Object compressChains, + Object smartChains, Object maxPercent, Object purgeIncrementals) { + return String.join("\n", "#Enable or disable automatic backups.", "#Options : true, false #Default : true,", -"config.advancedbackups.enabled=%s", +"config.advancedbackups.enabled=" + enabled, "", "#Whether to save before making a backup.", "#Options : true, false #Default : false", -"config.advancedbackups.save=%s", +"config.advancedbackups.save=" + save, "", "#Whether to require player activity between backups.", "#Options : true, false #Default : false", -"config.advancedbackups.activity=%s", +"config.advancedbackups.activity=" + activity, "", "#The type of backups to use.", "#Options : zip, differential, incremental #Default : differential", -"config.advancedbackups.type=%s", +"config.advancedbackups.type=" + type, "", "#The absolute or relative path to the backup location.", "#Options : any file path. Default : ./backups", -"config.advancedbackups.path=%s", +"config.advancedbackups.path=" + location, "", "#The maximum size to keep, in GB. Keep relatively high for zips, tighter space requirements should instead use differential or incremental backups.", "#Range : 5 - 9999 #Default : 50", -"config.advancedbackups.size=%s", +"config.advancedbackups.size=" + size, "", "#Minimum time between backups, in hours. This can prevent a shutdown backup from triggering immediately after a scheduled backup or similar situations.", "#Range : 0.5 - 500 #Default : 0.5", -"config.advancedbackups.frequency.min=%s", +"config.advancedbackups.frequency.min=" + min, "", "#Triggers a backup if none has already happened within this time. Can be combined with an uptime-based schedule.", "#Range : 0.5 - 500 #Default : 24", -"config.advancedbackups.frequency.max=%s", +"config.advancedbackups.frequency.max=" + max, "", "#Whether the schedule below uses uptime (true) or real-world time (false).", "#Default : true", -"config.advancedbackups.frequency.uptime=%s", +"config.advancedbackups.frequency.uptime=" + uptime, "", "#When using server uptime:", " #A looping comma-separated backup schedule, based off of server uptime, hours:minutes. Examples:", @@ -300,23 +307,23 @@ public void setMaxSizePercent(String maxSizePercent) { " #4:00,8:00,12:00,16:00,17:00,18:00,19:00,20:00,21:00,24:00 - Makes a backup at specific times of day.", "", "#Default : 12:00", -"config.advancedbackups.frequency.schedule=%s", +"config.advancedbackups.frequency.schedule=" + schedule, "", "#Whether to force a backup on server shutdown. Respects min frequency.", "#Options : true, false #Default : false", -"config.advancedbackups.frequency.shutdown=%s", +"config.advancedbackups.frequency.shutdown=" + shutdown, "", "#Whether to force a backup on server startup. Respects min frequency.", "#Options : true, false #Default : false", -"config.advancedbackups.frequency.startup=%s", +"config.advancedbackups.frequency.startup=" + startup, "", "#Delay to use after startup, in seconds. Is always at least 5 seconds.", "#Range : 5-9999999999", -"config.advancedbackups.frequency.delay=%s", +"config.advancedbackups.frequency.delay=" + delay, "", "#Whether to disable console and chat logging. Does not affect debug.log, does not affect error messages.", "#Options : true, false #Default : false", -"config.advancedbackups.logging.silent=%s", +"config.advancedbackups.logging.silent=" + silent, "", "", "", @@ -326,7 +333,7 @@ public void setMaxSizePercent(String maxSizePercent) { "", "#The compression level to use for zip files. Higher numbers space usage, but decrease performance.", "#Range : 1-9 #Default : 4", -"config.advancedbackups.zips.compression=%s", +"config.advancedbackups.zips.compression=" + compression, "", "", "", @@ -336,33 +343,36 @@ public void setMaxSizePercent(String maxSizePercent) { "", "#The maximum 'chain' length to keep.", "#Range : 5-500 #Default : 50", -"config.advancedbackups.chains.length=%s", +"config.advancedbackups.chains.length=" + chainLength, "", "#Whether to compress 'chains'. This compresses the base backup and all sequential backups. Reduces space usage, but decreases performance.", "#Options : true, false #Default : true", -"config.advancedbackups.chains.compress=%s", +"config.advancedbackups.chains.compress=" + compressChains, "", "#Whether to enable \"smart\" reset for chains - if every file is being backed up, mark the backup as complete and reset chain length regardless of intended backup type.", "#Options : true, false #Default : true", -"config.advancedbackups.chains.smart=%s", +"config.advancedbackups.chains.smart=" + smartChains, "", "#What % of a full backup is allowed to be contained in a partial before forcing it into a full backup. Useful for reducing partial backup size.", -"config.advancedbackups.chains.maxpercent=%s", +"config.advancedbackups.chains.maxpercent=" + maxPercent, "", "#Whether to delete incremental backup chains if max size is exceeded. If not, incremental backups do not respect the max size config and never delete.", "#Options : true, false #Default : false", -"config.advancedbackups.purge.incrementals=%s" +"config.advancedbackups.purge.incrementals=" + purgeIncrementals ); + } - public static final String defaults = String.format(plainConfig, - "true", "false", "false", - "differential", "./backups", "50", - "0.5", "24", "true", - "12:00", "false", "false", - "5", "false", "4", - "50", "true", "true", - "75","false"); + public static String defaults() { + return config( + "true", "false", "false", + "differential", "./backups", "50", + "0.5", "24", "true", + "12:00", "false", "false", + "5", "false", "4", + "50", "true", "true", + "75","false"); + } } From e6347097a63f4050a52a241ed63643ac3a093854 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Fri, 16 Jun 2023 15:34:21 +0000 Subject: [PATCH 167/580] Update core files --- .../advancedbackups/core/config/AVConfig.java | 16 ++--- .../core/config/ConfigData.java | 68 +++++++++++-------- 2 files changed, 47 insertions(+), 37 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java index 3e66b8c0..b56eed0c 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java @@ -61,7 +61,7 @@ public static void initConfig() { file.setWritable(true); } FileWriter writer = new FileWriter(file); - writer.write(ConfigData.defaults); + writer.write(ConfigData.defaults()); writer.close(); } catch (IOException e) { // TODO : Scream to user @@ -143,13 +143,13 @@ public static void loadConfig() { newPropsFile.createNewFile(); } FileWriter writer = new FileWriter(newPropsFile); - writer.write(String.format(ConfigData.plainConfig, config.getEnabled(), - config.getSave(), config.getRequireActivity(), config.getBackupType(), - config.getPath(), config.getMaxSize(), config.getMinTimer(), - config.getMaxTimer(), config.getUptimeSchedule(), config.getSchedule(), - config.getForceOnShutdown(), config.getStartupDelay(), config.getStartupDelay(), - config.getSilent(), config.getCompressionLevel(), config.getMaxDepth(), - config.getCompressChains(), config.getSmartChains(), config.getPurgeIncrementals() + writer.write(ConfigData.config(config.getEnabled(), config.getSave(), + config.getRequireActivity(), config.getBackupType(), config.getPath(), + config.getMaxSize(), config.getMinTimer(), config.getMaxTimer(), + config.getUptimeSchedule(), config.getSchedule(), config.getForceOnShutdown(), + config.getForceOnStartup(), config.getStartupDelay(), config.getSilent(), + config.getCompressionLevel(), config.getMaxDepth(), config.getCompressChains(), + config.getSmartChains(), config.getMaxSizePercent(), config.getPurgeIncrementals() )); writer.close(); } catch (IOException e) { diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java index f5e7841f..ecf162c9 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java @@ -249,43 +249,50 @@ public void setMaxSizePercent(String maxSizePercent) { //default config output - can be ignored - public static final String plainConfig = String.join("\n", + public static String config(Object enabled, Object save, + Object activity, Object type, Object location, + Object size, Object min, Object max, + Object uptime, Object schedule, Object shutdown, + Object startup, Object delay, Object silent, + Object compression, Object chainLength, Object compressChains, + Object smartChains, Object maxPercent, Object purgeIncrementals) { + return String.join("\n", "#Enable or disable automatic backups.", "#Options : true, false #Default : true,", -"config.advancedbackups.enabled=%s", +"config.advancedbackups.enabled=" + enabled, "", "#Whether to save before making a backup.", "#Options : true, false #Default : false", -"config.advancedbackups.save=%s", +"config.advancedbackups.save=" + save, "", "#Whether to require player activity between backups.", "#Options : true, false #Default : false", -"config.advancedbackups.activity=%s", +"config.advancedbackups.activity=" + activity, "", "#The type of backups to use.", "#Options : zip, differential, incremental #Default : differential", -"config.advancedbackups.type=%s", +"config.advancedbackups.type=" + type, "", "#The absolute or relative path to the backup location.", "#Options : any file path. Default : ./backups", -"config.advancedbackups.path=%s", +"config.advancedbackups.path=" + location, "", "#The maximum size to keep, in GB. Keep relatively high for zips, tighter space requirements should instead use differential or incremental backups.", "#Range : 5 - 9999 #Default : 50", -"config.advancedbackups.size=%s", +"config.advancedbackups.size=" + size, "", "#Minimum time between backups, in hours. This can prevent a shutdown backup from triggering immediately after a scheduled backup or similar situations.", "#Range : 0.5 - 500 #Default : 0.5", -"config.advancedbackups.frequency.min=%s", +"config.advancedbackups.frequency.min=" + min, "", "#Triggers a backup if none has already happened within this time. Can be combined with an uptime-based schedule.", "#Range : 0.5 - 500 #Default : 24", -"config.advancedbackups.frequency.max=%s", +"config.advancedbackups.frequency.max=" + max, "", "#Whether the schedule below uses uptime (true) or real-world time (false).", "#Default : true", -"config.advancedbackups.frequency.uptime=%s", +"config.advancedbackups.frequency.uptime=" + uptime, "", "#When using server uptime:", " #A looping comma-separated backup schedule, based off of server uptime, hours:minutes. Examples:", @@ -300,23 +307,23 @@ public void setMaxSizePercent(String maxSizePercent) { " #4:00,8:00,12:00,16:00,17:00,18:00,19:00,20:00,21:00,24:00 - Makes a backup at specific times of day.", "", "#Default : 12:00", -"config.advancedbackups.frequency.schedule=%s", +"config.advancedbackups.frequency.schedule=" + schedule, "", "#Whether to force a backup on server shutdown. Respects min frequency.", "#Options : true, false #Default : false", -"config.advancedbackups.frequency.shutdown=%s", +"config.advancedbackups.frequency.shutdown=" + shutdown, "", "#Whether to force a backup on server startup. Respects min frequency.", "#Options : true, false #Default : false", -"config.advancedbackups.frequency.startup=%s", +"config.advancedbackups.frequency.startup=" + startup, "", "#Delay to use after startup, in seconds. Is always at least 5 seconds.", "#Range : 5-9999999999", -"config.advancedbackups.frequency.delay=%s", +"config.advancedbackups.frequency.delay=" + delay, "", "#Whether to disable console and chat logging. Does not affect debug.log, does not affect error messages.", "#Options : true, false #Default : false", -"config.advancedbackups.logging.silent=%s", +"config.advancedbackups.logging.silent=" + silent, "", "", "", @@ -326,7 +333,7 @@ public void setMaxSizePercent(String maxSizePercent) { "", "#The compression level to use for zip files. Higher numbers space usage, but decrease performance.", "#Range : 1-9 #Default : 4", -"config.advancedbackups.zips.compression=%s", +"config.advancedbackups.zips.compression=" + compression, "", "", "", @@ -336,33 +343,36 @@ public void setMaxSizePercent(String maxSizePercent) { "", "#The maximum 'chain' length to keep.", "#Range : 5-500 #Default : 50", -"config.advancedbackups.chains.length=%s", +"config.advancedbackups.chains.length=" + chainLength, "", "#Whether to compress 'chains'. This compresses the base backup and all sequential backups. Reduces space usage, but decreases performance.", "#Options : true, false #Default : true", -"config.advancedbackups.chains.compress=%s", +"config.advancedbackups.chains.compress=" + compressChains, "", "#Whether to enable \"smart\" reset for chains - if every file is being backed up, mark the backup as complete and reset chain length regardless of intended backup type.", "#Options : true, false #Default : true", -"config.advancedbackups.chains.smart=%s", +"config.advancedbackups.chains.smart=" + smartChains, "", "#What % of a full backup is allowed to be contained in a partial before forcing it into a full backup. Useful for reducing partial backup size.", -"config.advancedbackups.chains.maxpercent=%s", +"config.advancedbackups.chains.maxpercent=" + maxPercent, "", "#Whether to delete incremental backup chains if max size is exceeded. If not, incremental backups do not respect the max size config and never delete.", "#Options : true, false #Default : false", -"config.advancedbackups.purge.incrementals=%s" +"config.advancedbackups.purge.incrementals=" + purgeIncrementals ); + } - public static final String defaults = String.format(plainConfig, - "true", "false", "false", - "differential", "./backups", "50", - "0.5", "24", "true", - "12:00", "false", "false", - "5", "false", "4", - "50", "true", "true", - "75","false"); + public static String defaults() { + return config( + "true", "false", "false", + "differential", "./backups", "50", + "0.5", "24", "true", + "12:00", "false", "false", + "5", "false", "4", + "50", "true", "true", + "75","false"); + } } From 95f494ede543c862dc239b09bbd1c1bda019d984 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Fri, 16 Jun 2023 15:34:21 +0000 Subject: [PATCH 168/580] Update core files --- .../advancedbackups/core/config/AVConfig.java | 16 ++--- .../core/config/ConfigData.java | 68 +++++++++++-------- 2 files changed, 47 insertions(+), 37 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java index 3e66b8c0..b56eed0c 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java @@ -61,7 +61,7 @@ public static void initConfig() { file.setWritable(true); } FileWriter writer = new FileWriter(file); - writer.write(ConfigData.defaults); + writer.write(ConfigData.defaults()); writer.close(); } catch (IOException e) { // TODO : Scream to user @@ -143,13 +143,13 @@ public static void loadConfig() { newPropsFile.createNewFile(); } FileWriter writer = new FileWriter(newPropsFile); - writer.write(String.format(ConfigData.plainConfig, config.getEnabled(), - config.getSave(), config.getRequireActivity(), config.getBackupType(), - config.getPath(), config.getMaxSize(), config.getMinTimer(), - config.getMaxTimer(), config.getUptimeSchedule(), config.getSchedule(), - config.getForceOnShutdown(), config.getStartupDelay(), config.getStartupDelay(), - config.getSilent(), config.getCompressionLevel(), config.getMaxDepth(), - config.getCompressChains(), config.getSmartChains(), config.getPurgeIncrementals() + writer.write(ConfigData.config(config.getEnabled(), config.getSave(), + config.getRequireActivity(), config.getBackupType(), config.getPath(), + config.getMaxSize(), config.getMinTimer(), config.getMaxTimer(), + config.getUptimeSchedule(), config.getSchedule(), config.getForceOnShutdown(), + config.getForceOnStartup(), config.getStartupDelay(), config.getSilent(), + config.getCompressionLevel(), config.getMaxDepth(), config.getCompressChains(), + config.getSmartChains(), config.getMaxSizePercent(), config.getPurgeIncrementals() )); writer.close(); } catch (IOException e) { diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java index f5e7841f..ecf162c9 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java @@ -249,43 +249,50 @@ public void setMaxSizePercent(String maxSizePercent) { //default config output - can be ignored - public static final String plainConfig = String.join("\n", + public static String config(Object enabled, Object save, + Object activity, Object type, Object location, + Object size, Object min, Object max, + Object uptime, Object schedule, Object shutdown, + Object startup, Object delay, Object silent, + Object compression, Object chainLength, Object compressChains, + Object smartChains, Object maxPercent, Object purgeIncrementals) { + return String.join("\n", "#Enable or disable automatic backups.", "#Options : true, false #Default : true,", -"config.advancedbackups.enabled=%s", +"config.advancedbackups.enabled=" + enabled, "", "#Whether to save before making a backup.", "#Options : true, false #Default : false", -"config.advancedbackups.save=%s", +"config.advancedbackups.save=" + save, "", "#Whether to require player activity between backups.", "#Options : true, false #Default : false", -"config.advancedbackups.activity=%s", +"config.advancedbackups.activity=" + activity, "", "#The type of backups to use.", "#Options : zip, differential, incremental #Default : differential", -"config.advancedbackups.type=%s", +"config.advancedbackups.type=" + type, "", "#The absolute or relative path to the backup location.", "#Options : any file path. Default : ./backups", -"config.advancedbackups.path=%s", +"config.advancedbackups.path=" + location, "", "#The maximum size to keep, in GB. Keep relatively high for zips, tighter space requirements should instead use differential or incremental backups.", "#Range : 5 - 9999 #Default : 50", -"config.advancedbackups.size=%s", +"config.advancedbackups.size=" + size, "", "#Minimum time between backups, in hours. This can prevent a shutdown backup from triggering immediately after a scheduled backup or similar situations.", "#Range : 0.5 - 500 #Default : 0.5", -"config.advancedbackups.frequency.min=%s", +"config.advancedbackups.frequency.min=" + min, "", "#Triggers a backup if none has already happened within this time. Can be combined with an uptime-based schedule.", "#Range : 0.5 - 500 #Default : 24", -"config.advancedbackups.frequency.max=%s", +"config.advancedbackups.frequency.max=" + max, "", "#Whether the schedule below uses uptime (true) or real-world time (false).", "#Default : true", -"config.advancedbackups.frequency.uptime=%s", +"config.advancedbackups.frequency.uptime=" + uptime, "", "#When using server uptime:", " #A looping comma-separated backup schedule, based off of server uptime, hours:minutes. Examples:", @@ -300,23 +307,23 @@ public void setMaxSizePercent(String maxSizePercent) { " #4:00,8:00,12:00,16:00,17:00,18:00,19:00,20:00,21:00,24:00 - Makes a backup at specific times of day.", "", "#Default : 12:00", -"config.advancedbackups.frequency.schedule=%s", +"config.advancedbackups.frequency.schedule=" + schedule, "", "#Whether to force a backup on server shutdown. Respects min frequency.", "#Options : true, false #Default : false", -"config.advancedbackups.frequency.shutdown=%s", +"config.advancedbackups.frequency.shutdown=" + shutdown, "", "#Whether to force a backup on server startup. Respects min frequency.", "#Options : true, false #Default : false", -"config.advancedbackups.frequency.startup=%s", +"config.advancedbackups.frequency.startup=" + startup, "", "#Delay to use after startup, in seconds. Is always at least 5 seconds.", "#Range : 5-9999999999", -"config.advancedbackups.frequency.delay=%s", +"config.advancedbackups.frequency.delay=" + delay, "", "#Whether to disable console and chat logging. Does not affect debug.log, does not affect error messages.", "#Options : true, false #Default : false", -"config.advancedbackups.logging.silent=%s", +"config.advancedbackups.logging.silent=" + silent, "", "", "", @@ -326,7 +333,7 @@ public void setMaxSizePercent(String maxSizePercent) { "", "#The compression level to use for zip files. Higher numbers space usage, but decrease performance.", "#Range : 1-9 #Default : 4", -"config.advancedbackups.zips.compression=%s", +"config.advancedbackups.zips.compression=" + compression, "", "", "", @@ -336,33 +343,36 @@ public void setMaxSizePercent(String maxSizePercent) { "", "#The maximum 'chain' length to keep.", "#Range : 5-500 #Default : 50", -"config.advancedbackups.chains.length=%s", +"config.advancedbackups.chains.length=" + chainLength, "", "#Whether to compress 'chains'. This compresses the base backup and all sequential backups. Reduces space usage, but decreases performance.", "#Options : true, false #Default : true", -"config.advancedbackups.chains.compress=%s", +"config.advancedbackups.chains.compress=" + compressChains, "", "#Whether to enable \"smart\" reset for chains - if every file is being backed up, mark the backup as complete and reset chain length regardless of intended backup type.", "#Options : true, false #Default : true", -"config.advancedbackups.chains.smart=%s", +"config.advancedbackups.chains.smart=" + smartChains, "", "#What % of a full backup is allowed to be contained in a partial before forcing it into a full backup. Useful for reducing partial backup size.", -"config.advancedbackups.chains.maxpercent=%s", +"config.advancedbackups.chains.maxpercent=" + maxPercent, "", "#Whether to delete incremental backup chains if max size is exceeded. If not, incremental backups do not respect the max size config and never delete.", "#Options : true, false #Default : false", -"config.advancedbackups.purge.incrementals=%s" +"config.advancedbackups.purge.incrementals=" + purgeIncrementals ); + } - public static final String defaults = String.format(plainConfig, - "true", "false", "false", - "differential", "./backups", "50", - "0.5", "24", "true", - "12:00", "false", "false", - "5", "false", "4", - "50", "true", "true", - "75","false"); + public static String defaults() { + return config( + "true", "false", "false", + "differential", "./backups", "50", + "0.5", "24", "true", + "12:00", "false", "false", + "5", "false", "4", + "50", "true", "true", + "75","false"); + } } From 4380b893a5e91f00b0d1b20dc86fd6775948d960 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Fri, 16 Jun 2023 15:34:22 +0000 Subject: [PATCH 169/580] Update core files --- .../advancedbackups/core/config/AVConfig.java | 16 ++--- .../core/config/ConfigData.java | 68 +++++++++++-------- 2 files changed, 47 insertions(+), 37 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java index 3e66b8c0..b56eed0c 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java @@ -61,7 +61,7 @@ public static void initConfig() { file.setWritable(true); } FileWriter writer = new FileWriter(file); - writer.write(ConfigData.defaults); + writer.write(ConfigData.defaults()); writer.close(); } catch (IOException e) { // TODO : Scream to user @@ -143,13 +143,13 @@ public static void loadConfig() { newPropsFile.createNewFile(); } FileWriter writer = new FileWriter(newPropsFile); - writer.write(String.format(ConfigData.plainConfig, config.getEnabled(), - config.getSave(), config.getRequireActivity(), config.getBackupType(), - config.getPath(), config.getMaxSize(), config.getMinTimer(), - config.getMaxTimer(), config.getUptimeSchedule(), config.getSchedule(), - config.getForceOnShutdown(), config.getStartupDelay(), config.getStartupDelay(), - config.getSilent(), config.getCompressionLevel(), config.getMaxDepth(), - config.getCompressChains(), config.getSmartChains(), config.getPurgeIncrementals() + writer.write(ConfigData.config(config.getEnabled(), config.getSave(), + config.getRequireActivity(), config.getBackupType(), config.getPath(), + config.getMaxSize(), config.getMinTimer(), config.getMaxTimer(), + config.getUptimeSchedule(), config.getSchedule(), config.getForceOnShutdown(), + config.getForceOnStartup(), config.getStartupDelay(), config.getSilent(), + config.getCompressionLevel(), config.getMaxDepth(), config.getCompressChains(), + config.getSmartChains(), config.getMaxSizePercent(), config.getPurgeIncrementals() )); writer.close(); } catch (IOException e) { diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java index f5e7841f..ecf162c9 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java @@ -249,43 +249,50 @@ public void setMaxSizePercent(String maxSizePercent) { //default config output - can be ignored - public static final String plainConfig = String.join("\n", + public static String config(Object enabled, Object save, + Object activity, Object type, Object location, + Object size, Object min, Object max, + Object uptime, Object schedule, Object shutdown, + Object startup, Object delay, Object silent, + Object compression, Object chainLength, Object compressChains, + Object smartChains, Object maxPercent, Object purgeIncrementals) { + return String.join("\n", "#Enable or disable automatic backups.", "#Options : true, false #Default : true,", -"config.advancedbackups.enabled=%s", +"config.advancedbackups.enabled=" + enabled, "", "#Whether to save before making a backup.", "#Options : true, false #Default : false", -"config.advancedbackups.save=%s", +"config.advancedbackups.save=" + save, "", "#Whether to require player activity between backups.", "#Options : true, false #Default : false", -"config.advancedbackups.activity=%s", +"config.advancedbackups.activity=" + activity, "", "#The type of backups to use.", "#Options : zip, differential, incremental #Default : differential", -"config.advancedbackups.type=%s", +"config.advancedbackups.type=" + type, "", "#The absolute or relative path to the backup location.", "#Options : any file path. Default : ./backups", -"config.advancedbackups.path=%s", +"config.advancedbackups.path=" + location, "", "#The maximum size to keep, in GB. Keep relatively high for zips, tighter space requirements should instead use differential or incremental backups.", "#Range : 5 - 9999 #Default : 50", -"config.advancedbackups.size=%s", +"config.advancedbackups.size=" + size, "", "#Minimum time between backups, in hours. This can prevent a shutdown backup from triggering immediately after a scheduled backup or similar situations.", "#Range : 0.5 - 500 #Default : 0.5", -"config.advancedbackups.frequency.min=%s", +"config.advancedbackups.frequency.min=" + min, "", "#Triggers a backup if none has already happened within this time. Can be combined with an uptime-based schedule.", "#Range : 0.5 - 500 #Default : 24", -"config.advancedbackups.frequency.max=%s", +"config.advancedbackups.frequency.max=" + max, "", "#Whether the schedule below uses uptime (true) or real-world time (false).", "#Default : true", -"config.advancedbackups.frequency.uptime=%s", +"config.advancedbackups.frequency.uptime=" + uptime, "", "#When using server uptime:", " #A looping comma-separated backup schedule, based off of server uptime, hours:minutes. Examples:", @@ -300,23 +307,23 @@ public void setMaxSizePercent(String maxSizePercent) { " #4:00,8:00,12:00,16:00,17:00,18:00,19:00,20:00,21:00,24:00 - Makes a backup at specific times of day.", "", "#Default : 12:00", -"config.advancedbackups.frequency.schedule=%s", +"config.advancedbackups.frequency.schedule=" + schedule, "", "#Whether to force a backup on server shutdown. Respects min frequency.", "#Options : true, false #Default : false", -"config.advancedbackups.frequency.shutdown=%s", +"config.advancedbackups.frequency.shutdown=" + shutdown, "", "#Whether to force a backup on server startup. Respects min frequency.", "#Options : true, false #Default : false", -"config.advancedbackups.frequency.startup=%s", +"config.advancedbackups.frequency.startup=" + startup, "", "#Delay to use after startup, in seconds. Is always at least 5 seconds.", "#Range : 5-9999999999", -"config.advancedbackups.frequency.delay=%s", +"config.advancedbackups.frequency.delay=" + delay, "", "#Whether to disable console and chat logging. Does not affect debug.log, does not affect error messages.", "#Options : true, false #Default : false", -"config.advancedbackups.logging.silent=%s", +"config.advancedbackups.logging.silent=" + silent, "", "", "", @@ -326,7 +333,7 @@ public void setMaxSizePercent(String maxSizePercent) { "", "#The compression level to use for zip files. Higher numbers space usage, but decrease performance.", "#Range : 1-9 #Default : 4", -"config.advancedbackups.zips.compression=%s", +"config.advancedbackups.zips.compression=" + compression, "", "", "", @@ -336,33 +343,36 @@ public void setMaxSizePercent(String maxSizePercent) { "", "#The maximum 'chain' length to keep.", "#Range : 5-500 #Default : 50", -"config.advancedbackups.chains.length=%s", +"config.advancedbackups.chains.length=" + chainLength, "", "#Whether to compress 'chains'. This compresses the base backup and all sequential backups. Reduces space usage, but decreases performance.", "#Options : true, false #Default : true", -"config.advancedbackups.chains.compress=%s", +"config.advancedbackups.chains.compress=" + compressChains, "", "#Whether to enable \"smart\" reset for chains - if every file is being backed up, mark the backup as complete and reset chain length regardless of intended backup type.", "#Options : true, false #Default : true", -"config.advancedbackups.chains.smart=%s", +"config.advancedbackups.chains.smart=" + smartChains, "", "#What % of a full backup is allowed to be contained in a partial before forcing it into a full backup. Useful for reducing partial backup size.", -"config.advancedbackups.chains.maxpercent=%s", +"config.advancedbackups.chains.maxpercent=" + maxPercent, "", "#Whether to delete incremental backup chains if max size is exceeded. If not, incremental backups do not respect the max size config and never delete.", "#Options : true, false #Default : false", -"config.advancedbackups.purge.incrementals=%s" +"config.advancedbackups.purge.incrementals=" + purgeIncrementals ); + } - public static final String defaults = String.format(plainConfig, - "true", "false", "false", - "differential", "./backups", "50", - "0.5", "24", "true", - "12:00", "false", "false", - "5", "false", "4", - "50", "true", "true", - "75","false"); + public static String defaults() { + return config( + "true", "false", "false", + "differential", "./backups", "50", + "0.5", "24", "true", + "12:00", "false", "false", + "5", "false", "4", + "50", "true", "true", + "75","false"); + } } From 708813c61a79c25933e81d40d9597580cbd9f08b Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Fri, 16 Jun 2023 19:01:38 +0100 Subject: [PATCH 170/580] Extra command + version bump for 1.0 release. --- .../advancedbackups/AdvancedBackupsCommand.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index b8a6c961..a0ce62b0 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -38,6 +38,13 @@ public static void register(CommandDispatcher stack) { }); return 1; })) + + .then(Commands.literal("reset-chain").executes((runner) -> { + CoreCommandSystem.resetChainLength((response) -> { + runner.getSource().sendSuccess(new TextComponent(response), true); + }); + return 1; + })) ); } From 75b1887bfdf29f9268665cca7e70767a67bb1d2c Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Fri, 16 Jun 2023 19:03:45 +0100 Subject: [PATCH 171/580] version bump --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index b83fab1f..e2761673 100644 --- a/build.gradle +++ b/build.gradle @@ -16,7 +16,7 @@ plugins { apply plugin: 'net.minecraftforge.gradle' -version = '0.3' +version = '1.0' group = 'co.uk.mommyheather.advancedbackups' // http://maven.apache.org/guides/mini/guide-naming-conventions.html archivesBaseName = 'AdvancedBackups-' + modloaderName + "-" + minecraftVersion From e4ba68fe6f7d0e0ae3005da9f3b51079fc1e11df Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Sat, 17 Jun 2023 09:08:15 +0100 Subject: [PATCH 172/580] Implement command, version bump. --- gradle.properties | 2 +- .../advancedbackups/AdvancedBackupsCommand.java | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index f5d7702d..d559170a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,7 @@ yarn_mappings=1.18.2+build.4 loader_version=0.14.19 # Mod Properties -mod_version=0.3 +mod_version=1.0 maven_group=co.uk.mommyheather.advancedbackups archives_base_name=advanced-backups modloaderName =fabric diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index cdd2386b..52e552bf 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -38,6 +38,13 @@ public static void register(CommandDispatcher stack) { }); return 1; })) + + .then(CommandManager.literal("reset-chain").executes((runner) -> { + CoreCommandSystem.reloadConfig((response) -> { + runner.getSource().sendFeedback(Text.of(response), true); + }); + return 1; + })) ); } From 101133df3106494aed1a0f568aba5f63ecb35f17 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Sat, 17 Jun 2023 09:34:20 +0100 Subject: [PATCH 173/580] Support command, version bump. --- build.gradle | 2 +- .../advancedbackups/AdvancedBackupsCommand.java | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 0ea30f82..6dfc2189 100644 --- a/build.gradle +++ b/build.gradle @@ -12,7 +12,7 @@ apply plugin: 'net.minecraftforge.gradle' apply plugin: 'eclipse' apply plugin: 'maven-publish' -version = '0.3' +version = '1.0' group = 'com.github.raveninthedark.advancedbackups' // http://maven.apache.org/guides/mini/guide-naming-conventions.html archivesBaseName = 'AdvancedBackups-' + modloaderName + "-" + minecraftVersion diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index 5b06cf05..1e07383c 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -38,6 +38,13 @@ public static void register(CommandDispatcher stack) { }); return 1; })) + + .then(Commands.literal("reset-chain").executes((runner) -> { + CoreCommandSystem.resetChainLength((response) -> { + runner.getSource().sendSuccess(new StringTextComponent(response), true); + }); + return 1; + })) ); } From 61a4c2e2fb0da1d8b6010a7313a109c691a85722 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Sat, 17 Jun 2023 10:00:26 +0000 Subject: [PATCH 174/580] Update core files --- .../advancedbackups/core/backups/BackupTimingThread.java | 4 +++- .../advancedbackups/core/backups/BackupWrapper.java | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java index 4da53ce9..c9cb675e 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java @@ -33,6 +33,8 @@ public void run() { private long calculateNextBackupTime() { long forcedMillis = BackupWrapper.mostRecentBackupTime() + (long) (AVConfig.config.getMaxTimer() * 3600000L); + if (forcedMillis == AVConfig.config.getMaxTimer() * 3600000L) forcedMillis = 300000; //sets it to 5m if no backup exists, to get the chain going + else forcedMillis -= System.currentTimeMillis(); long ret = Long.MAX_VALUE; if (AVConfig.config.getUptimeSchedule() && !BackupWrapper.configuredPlaytime.isEmpty()) { ArrayList timings = new ArrayList(BackupWrapper.configuredPlaytime); @@ -48,7 +50,7 @@ private long calculateNextBackupTime() { else if (!BackupWrapper.configuredPlaytime.isEmpty()) { long nextTime = 0; - long currentTime = (LocalDateTime.now().getHour() * 3600000) + (LocalDateTime.now().getMinute() * 60000); + long currentTime = System.currentTimeMillis(); ArrayList timings = new ArrayList(BackupWrapper.configuredPlaytime); for (long time : timings) { if (time >= currentTime) { diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java index afa9e309..f53771a2 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java @@ -28,7 +28,6 @@ public static void checkShutdownBackups() { } public static void checkAndMakeBackups(long delay) { - prepareBackupDestination(); BackupCheckEnum e = checkBackups(); if (e.success()) { makeSingleBackup(delay); @@ -41,6 +40,7 @@ public static void checkAndMakeBackups() { public static BackupCheckEnum checkBackups() { + prepareBackupDestination(); if (!AVConfig.config.getEnabled()) return BackupCheckEnum.DISABLED; if (AVConfig.config.getRequireActivity() && !PlatformMethodWrapper.activity) return BackupCheckEnum.NOACTIVITY; if (checkMostRecentBackup()) return BackupCheckEnum.TOORECENT; From 886e73fce32b4eaa1b8f8d9e4e5b84206edc6e50 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Sat, 17 Jun 2023 10:00:27 +0000 Subject: [PATCH 175/580] Update core files --- .../advancedbackups/core/backups/BackupTimingThread.java | 4 +++- .../advancedbackups/core/backups/BackupWrapper.java | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java index 4da53ce9..c9cb675e 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java @@ -33,6 +33,8 @@ public void run() { private long calculateNextBackupTime() { long forcedMillis = BackupWrapper.mostRecentBackupTime() + (long) (AVConfig.config.getMaxTimer() * 3600000L); + if (forcedMillis == AVConfig.config.getMaxTimer() * 3600000L) forcedMillis = 300000; //sets it to 5m if no backup exists, to get the chain going + else forcedMillis -= System.currentTimeMillis(); long ret = Long.MAX_VALUE; if (AVConfig.config.getUptimeSchedule() && !BackupWrapper.configuredPlaytime.isEmpty()) { ArrayList timings = new ArrayList(BackupWrapper.configuredPlaytime); @@ -48,7 +50,7 @@ private long calculateNextBackupTime() { else if (!BackupWrapper.configuredPlaytime.isEmpty()) { long nextTime = 0; - long currentTime = (LocalDateTime.now().getHour() * 3600000) + (LocalDateTime.now().getMinute() * 60000); + long currentTime = System.currentTimeMillis(); ArrayList timings = new ArrayList(BackupWrapper.configuredPlaytime); for (long time : timings) { if (time >= currentTime) { diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java index afa9e309..f53771a2 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java @@ -28,7 +28,6 @@ public static void checkShutdownBackups() { } public static void checkAndMakeBackups(long delay) { - prepareBackupDestination(); BackupCheckEnum e = checkBackups(); if (e.success()) { makeSingleBackup(delay); @@ -41,6 +40,7 @@ public static void checkAndMakeBackups() { public static BackupCheckEnum checkBackups() { + prepareBackupDestination(); if (!AVConfig.config.getEnabled()) return BackupCheckEnum.DISABLED; if (AVConfig.config.getRequireActivity() && !PlatformMethodWrapper.activity) return BackupCheckEnum.NOACTIVITY; if (checkMostRecentBackup()) return BackupCheckEnum.TOORECENT; From a5979f82a20b93ccfc7282a7520f032b55f99467 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Sat, 17 Jun 2023 10:00:28 +0000 Subject: [PATCH 176/580] Update core files --- .../advancedbackups/core/backups/BackupTimingThread.java | 4 +++- .../advancedbackups/core/backups/BackupWrapper.java | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java index 4da53ce9..c9cb675e 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java @@ -33,6 +33,8 @@ public void run() { private long calculateNextBackupTime() { long forcedMillis = BackupWrapper.mostRecentBackupTime() + (long) (AVConfig.config.getMaxTimer() * 3600000L); + if (forcedMillis == AVConfig.config.getMaxTimer() * 3600000L) forcedMillis = 300000; //sets it to 5m if no backup exists, to get the chain going + else forcedMillis -= System.currentTimeMillis(); long ret = Long.MAX_VALUE; if (AVConfig.config.getUptimeSchedule() && !BackupWrapper.configuredPlaytime.isEmpty()) { ArrayList timings = new ArrayList(BackupWrapper.configuredPlaytime); @@ -48,7 +50,7 @@ private long calculateNextBackupTime() { else if (!BackupWrapper.configuredPlaytime.isEmpty()) { long nextTime = 0; - long currentTime = (LocalDateTime.now().getHour() * 3600000) + (LocalDateTime.now().getMinute() * 60000); + long currentTime = System.currentTimeMillis(); ArrayList timings = new ArrayList(BackupWrapper.configuredPlaytime); for (long time : timings) { if (time >= currentTime) { diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java index afa9e309..f53771a2 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java @@ -28,7 +28,6 @@ public static void checkShutdownBackups() { } public static void checkAndMakeBackups(long delay) { - prepareBackupDestination(); BackupCheckEnum e = checkBackups(); if (e.success()) { makeSingleBackup(delay); @@ -41,6 +40,7 @@ public static void checkAndMakeBackups() { public static BackupCheckEnum checkBackups() { + prepareBackupDestination(); if (!AVConfig.config.getEnabled()) return BackupCheckEnum.DISABLED; if (AVConfig.config.getRequireActivity() && !PlatformMethodWrapper.activity) return BackupCheckEnum.NOACTIVITY; if (checkMostRecentBackup()) return BackupCheckEnum.TOORECENT; From 09fc49306ffc965928316b2b9fa32748f63f22b2 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Sat, 17 Jun 2023 10:00:29 +0000 Subject: [PATCH 177/580] Update core files --- .../advancedbackups/core/backups/BackupTimingThread.java | 4 +++- .../advancedbackups/core/backups/BackupWrapper.java | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java index 4da53ce9..c9cb675e 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java @@ -33,6 +33,8 @@ public void run() { private long calculateNextBackupTime() { long forcedMillis = BackupWrapper.mostRecentBackupTime() + (long) (AVConfig.config.getMaxTimer() * 3600000L); + if (forcedMillis == AVConfig.config.getMaxTimer() * 3600000L) forcedMillis = 300000; //sets it to 5m if no backup exists, to get the chain going + else forcedMillis -= System.currentTimeMillis(); long ret = Long.MAX_VALUE; if (AVConfig.config.getUptimeSchedule() && !BackupWrapper.configuredPlaytime.isEmpty()) { ArrayList timings = new ArrayList(BackupWrapper.configuredPlaytime); @@ -48,7 +50,7 @@ private long calculateNextBackupTime() { else if (!BackupWrapper.configuredPlaytime.isEmpty()) { long nextTime = 0; - long currentTime = (LocalDateTime.now().getHour() * 3600000) + (LocalDateTime.now().getMinute() * 60000); + long currentTime = System.currentTimeMillis(); ArrayList timings = new ArrayList(BackupWrapper.configuredPlaytime); for (long time : timings) { if (time >= currentTime) { diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java index afa9e309..f53771a2 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java @@ -28,7 +28,6 @@ public static void checkShutdownBackups() { } public static void checkAndMakeBackups(long delay) { - prepareBackupDestination(); BackupCheckEnum e = checkBackups(); if (e.success()) { makeSingleBackup(delay); @@ -41,6 +40,7 @@ public static void checkAndMakeBackups() { public static BackupCheckEnum checkBackups() { + prepareBackupDestination(); if (!AVConfig.config.getEnabled()) return BackupCheckEnum.DISABLED; if (AVConfig.config.getRequireActivity() && !PlatformMethodWrapper.activity) return BackupCheckEnum.NOACTIVITY; if (checkMostRecentBackup()) return BackupCheckEnum.TOORECENT; From bd8bd17810d2de0aac6b6f4d1decfa7a9e56ca83 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Sat, 17 Jun 2023 10:00:30 +0000 Subject: [PATCH 178/580] Update core files --- .../advancedbackups/core/backups/BackupTimingThread.java | 4 +++- .../advancedbackups/core/backups/BackupWrapper.java | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java index 4da53ce9..c9cb675e 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java @@ -33,6 +33,8 @@ public void run() { private long calculateNextBackupTime() { long forcedMillis = BackupWrapper.mostRecentBackupTime() + (long) (AVConfig.config.getMaxTimer() * 3600000L); + if (forcedMillis == AVConfig.config.getMaxTimer() * 3600000L) forcedMillis = 300000; //sets it to 5m if no backup exists, to get the chain going + else forcedMillis -= System.currentTimeMillis(); long ret = Long.MAX_VALUE; if (AVConfig.config.getUptimeSchedule() && !BackupWrapper.configuredPlaytime.isEmpty()) { ArrayList timings = new ArrayList(BackupWrapper.configuredPlaytime); @@ -48,7 +50,7 @@ private long calculateNextBackupTime() { else if (!BackupWrapper.configuredPlaytime.isEmpty()) { long nextTime = 0; - long currentTime = (LocalDateTime.now().getHour() * 3600000) + (LocalDateTime.now().getMinute() * 60000); + long currentTime = System.currentTimeMillis(); ArrayList timings = new ArrayList(BackupWrapper.configuredPlaytime); for (long time : timings) { if (time >= currentTime) { diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java index afa9e309..f53771a2 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java @@ -28,7 +28,6 @@ public static void checkShutdownBackups() { } public static void checkAndMakeBackups(long delay) { - prepareBackupDestination(); BackupCheckEnum e = checkBackups(); if (e.success()) { makeSingleBackup(delay); @@ -41,6 +40,7 @@ public static void checkAndMakeBackups() { public static BackupCheckEnum checkBackups() { + prepareBackupDestination(); if (!AVConfig.config.getEnabled()) return BackupCheckEnum.DISABLED; if (AVConfig.config.getRequireActivity() && !PlatformMethodWrapper.activity) return BackupCheckEnum.NOACTIVITY; if (checkMostRecentBackup()) return BackupCheckEnum.TOORECENT; From 930fce47f14ee8208f3211be8009abfc050025e7 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Sat, 17 Jun 2023 12:20:26 +0100 Subject: [PATCH 179/580] Support command, version bump. --- build.gradle | 2 +- .../AdvancedBackupsCommand.java | 20 +++++++++++++++++++ src/main/resources/mcmod.info | 3 +-- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 15563c95..a7485fe5 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ plugins { } -version = '0.3.1' +version = '1.0' group = 'co.uk.mommyheather.advancedbackups' // http://maven.apache.org/guides/mini/guide-naming-conventions.html archivesBaseName = 'AdvancedBackups-' + modloaderName + "-" + minecraftVersion diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index d1670b60..5f8f92a1 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -17,6 +17,7 @@ public AdvancedBackupsCommand() addSubcommand(new Start()); addSubcommand(new Force()); addSubcommand(new Reload()); + addSubcommand(new ResetChain()); } @Override @@ -113,4 +114,23 @@ public String getUsage(ICommandSender sender) { return "commands.advancedbackups.start.usage"; } } + + public static class ResetChain extends CommandTreeBase { + public ResetChain(){} + @Override + public void execute(MinecraftServer server, ICommandSender sender, String[] args) throws CommandException { + CoreCommandSystem.resetChainLength((response) -> { + sender.sendMessage(new TextComponentString(response)); + }); + } + @Override + public String getName() + { + return "reset-chain"; + } + @Override + public String getUsage(ICommandSender sender) { + return "commands.advancedbackups.resetchain.usage"; + } + } } diff --git a/src/main/resources/mcmod.info b/src/main/resources/mcmod.info index 4797f5eb..38903d90 100644 --- a/src/main/resources/mcmod.info +++ b/src/main/resources/mcmod.info @@ -3,8 +3,7 @@ "modid": "advancedbackups", "name": "Advanced Backups", "description": "Powerful backup mod.", - "version": "${version}", - "mcversion": "${mcversion}", + "version": "1.0 ", "url": "https://github.com/MommyHeather/AdvancedBackups", "updateUrl": "", "authorList": ["MommyHeather"], From 86abf15df172067748c1eea8c57d3c0fca2e30f8 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Sat, 17 Jun 2023 12:33:39 +0100 Subject: [PATCH 180/580] Support command, version bump --- build.gradle.kts | 2 +- .../advancedbackups/AdvancedBackupsCommand.java | 14 +++++++++++++- src/main/resources/mcmod.info | 2 +- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 569c2b8e..86aef4ff 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -10,7 +10,7 @@ plugins { -version = "0.3" +version = "1.0" group = "co.uk.mommyheather.advancedbackups" // http://maven.apache.org/guides/mini/guide-naming-conventions.html //archivesBaseName = "AdvancedBackups-forge-1.7.10" diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index ad2e513e..fe5de121 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -9,6 +9,7 @@ import net.minecraft.command.WrongUsageException; import net.minecraft.server.MinecraftServer; import net.minecraft.util.ChatComponentText; +import scala.collection.script.Reset; public class AdvancedBackupsCommand extends CommandBase { @@ -35,7 +36,7 @@ public int getRequiredPermissionLevel() public String getCommandUsage(ICommandSender icommandsender) { - return "/advancedbackups (check|start|force-backup|reload)"; + return "/advancedbackups (check|start|force-backup|reload|reset-chain)"; } @@ -61,6 +62,9 @@ else if ("reload".equals(args[0])) { Reload.execute(sender); } + else if ("reset-chain".equals(args[0])) { + ResetChain.execute(sender); + } else { throw new WrongUsageException(getCommandUsage(sender)); @@ -95,6 +99,14 @@ public static void execute(ICommandSender sender) { sender.addChatMessage(new ChatComponentText(response)); }); } + } + + public static class ResetChain { + public static void execute(ICommandSender sender) { + CoreCommandSystem.resetChainLength((response) -> { + sender.addChatMessage(new ChatComponentText(response)); + }); + } } diff --git a/src/main/resources/mcmod.info b/src/main/resources/mcmod.info index 20d03144..0b8455ee 100644 --- a/src/main/resources/mcmod.info +++ b/src/main/resources/mcmod.info @@ -2,7 +2,7 @@ { "modid": "advancedbackups", "name": "Advanced Backups", - "version": "${modVersion}", + "version": "1.0", "mcversion": "1.7.10", "description": "A highly advanced backup mod.", "url": "https://github.com/MommyHeather/AdvancedBackups", From ba278176a1ee951d22138eba5821d403f2d60df7 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Wed, 23 Aug 2023 19:03:22 +0100 Subject: [PATCH 181/580] 1.19 forge --- build.gradle | 59 ++++--------------- gradle.properties | 2 +- .../AdvancedBackupsCommand.java | 12 ++-- 3 files changed, 17 insertions(+), 56 deletions(-) diff --git a/build.gradle b/build.gradle index e2761673..8f716f15 100644 --- a/build.gradle +++ b/build.gradle @@ -1,19 +1,9 @@ -buildscript { - repositories { - // These repositories are only for Gradle plugins, put any other repositories in the repository block further below - maven { url = 'https://maven.minecraftforge.net' } - mavenCentral() - } - dependencies { - classpath group: 'net.minecraftforge.gradle', name: 'ForgeGradle', version: '5.1.+', changing: true - } -} -// Only edit below this line, the above code adds and enables the necessary things for Forge to be setup. plugins { id 'eclipse' id 'maven-publish' + id 'net.minecraftforge.gradle' version '5.1.+' } -apply plugin: 'net.minecraftforge.gradle' + version = '1.0' @@ -38,7 +28,7 @@ minecraft { // // Use non-default mappings at your own risk. They may not always work. // Simply re-run your setup task after changing the mappings to update your workspace. - mappings channel: 'official', version: '1.18.2' + mappings channel: 'official', version: '1.19.2' // accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg') // Currently, this location cannot be changed from the default. @@ -87,34 +77,6 @@ minecraft { } } - // This run config launches GameTestServer and runs all registered gametests, then exits. - // By default, the server will crash when no gametests are provided. - // The gametest system is also enabled by default for other run configs under the /test command. - gameTestServer { - workingDirectory project.file('run') - - // Recommended logging data for a userdev environment - // The markers can be added/remove as needed separated by commas. - // "SCAN": For mods scan. - // "REGISTRIES": For firing of registry events. - // "REGISTRYDUMP": For getting the contents of all registries. - property 'forge.logging.markers', 'REGISTRIES' - - // Recommended logging level for the console - // You can set various levels here. - // Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels - property 'forge.logging.console.level', 'debug' - - // Comma-separated list of namespaces to load gametests from. Empty = all namespaces. - property 'forge.enabledGameTestNamespaces', 'advancedbackups' - - mods { - advancedbackups { - source sourceSets.main - } - } - } - data { workingDirectory project.file('run') @@ -137,6 +99,11 @@ minecraft { // Include resources generated by data generators. sourceSets.main.resources { srcDir 'src/generated/resources' } +configurations { + // configuration that holds jars to include in the jar + extraLibs +} + repositories { // Put repositories for dependencies here // ForgeGradle automatically adds the Forge maven and Maven Central for you @@ -147,20 +114,14 @@ repositories { // } } -configurations { - // configuration that holds jars to include in the jar - extraLibs -} - dependencies { // Specify the version of Minecraft to use. If this is any group other than 'net.minecraft', it is assumed // that the dep is a ForgeGradle 'patcher' dependency, and its patches will be applied. // The userdev artifact is a special name and will get all sorts of transformations applied to it. - minecraft 'net.minecraftforge:forge:1.18.2-40.2.1' - //extraLibs 'com.sun.jna.platform:5.13.0' + minecraft 'net.minecraftforge:forge:1.19.2-43.2.0' implementation files('dependencies/jansi-2.4.0.jar') extraLibs files('dependencies/jansi-2.4.0.jar') - + // Real mod deobf dependency examples - these get remapped to your current mappings // compileOnly fg.deobf("mezz.jei:jei-${mc_version}:${jei_version}:api") // Adds JEI API as a compile dependency // runtimeOnly fg.deobf("mezz.jei:jei-${mc_version}:${jei_version}") // Adds the full JEI mod as a runtime dependency diff --git a/gradle.properties b/gradle.properties index 0cb3e73b..5b712214 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,4 +6,4 @@ org.gradle.daemon=false modloaderName =forge -minecraftVersion =1.18 \ No newline at end of file +minecraftVersion =1.19 \ No newline at end of file diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index a0ce62b0..5e415c26 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -5,7 +5,7 @@ import co.uk.mommyheather.advancedbackups.core.CoreCommandSystem; import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.Commands; -import net.minecraft.network.chat.TextComponent; +import net.minecraft.network.chat.Component; public class AdvancedBackupsCommand { public static void register(CommandDispatcher stack) { @@ -13,35 +13,35 @@ public static void register(CommandDispatcher stack) { return runner.hasPermission(3); }).then(Commands.literal("check").executes((runner) -> { CoreCommandSystem.checkBackups((response) -> { - runner.getSource().sendSuccess(new TextComponent(response), true); + runner.getSource().sendSuccess(Component.literal(response), true); }); return 1; })) .then(Commands.literal("start").executes((runner) -> { CoreCommandSystem.startBackup((response) -> { - runner.getSource().sendSuccess(new TextComponent(response), true); + runner.getSource().sendSuccess(Component.literal(response), true); }); return 1; })) .then(Commands.literal("force-backup").executes((runner) -> { CoreCommandSystem.forceBackup((response) -> { - runner.getSource().sendSuccess(new TextComponent(response), true); + runner.getSource().sendSuccess(Component.literal(response), true); }); return 1; })) .then(Commands.literal("reload").executes((runner) -> { CoreCommandSystem.reloadConfig((response) -> { - runner.getSource().sendSuccess(new TextComponent(response), true); + runner.getSource().sendSuccess(Component.literal(response), true); }); return 1; })) .then(Commands.literal("reset-chain").executes((runner) -> { CoreCommandSystem.resetChainLength((response) -> { - runner.getSource().sendSuccess(new TextComponent(response), true); + runner.getSource().sendSuccess(Component.literal(response), true); }); return 1; })) From 409e64c5d362f619984f5d9b77dfea8d031e3dac Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Wed, 23 Aug 2023 19:20:10 +0100 Subject: [PATCH 182/580] Final commit for 1.19 1.0 - finishes #1. --- src/main/resources/META-INF/mods.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/META-INF/mods.toml b/src/main/resources/META-INF/mods.toml index ad0e6ca5..77d5bcd6 100644 --- a/src/main/resources/META-INF/mods.toml +++ b/src/main/resources/META-INF/mods.toml @@ -57,6 +57,6 @@ Config file and github contain documentation. modId="minecraft" mandatory=true # This version range declares a minimum of the current minecraft version up to but not including the next major version - versionRange="[1.18.2,1.19)" + versionRange="[1.19,1.20)" ordering="NONE" side="BOTH" From 2f5d453e4e889cf566008bcdd8e4a450604fcfa8 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Sat, 26 Aug 2023 18:35:05 +0000 Subject: [PATCH 183/580] Update core files --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 8fe67530..06916106 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,8 @@ Many Minecraft versions are supported - request more if the one you want isn't y [Future Plans](#future-plans) ## Current Versions: -- Forge 1.18 +- Forge 1.19 +- Forge 1.19 - Fabric 1.18 - Forge 1.16 - Forge 1.12 From ee5236751d84de15492c02649b50fe4b387132cd Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Sat, 26 Aug 2023 18:35:06 +0000 Subject: [PATCH 184/580] Update core files --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 8fe67530..06916106 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,8 @@ Many Minecraft versions are supported - request more if the one you want isn't y [Future Plans](#future-plans) ## Current Versions: -- Forge 1.18 +- Forge 1.19 +- Forge 1.19 - Fabric 1.18 - Forge 1.16 - Forge 1.12 From 175250ff60cd5a03545b9ebab534e37b2fc3565a Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Sat, 26 Aug 2023 18:35:08 +0000 Subject: [PATCH 185/580] Update core files --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 8fe67530..06916106 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,8 @@ Many Minecraft versions are supported - request more if the one you want isn't y [Future Plans](#future-plans) ## Current Versions: -- Forge 1.18 +- Forge 1.19 +- Forge 1.19 - Fabric 1.18 - Forge 1.16 - Forge 1.12 From f9ae8ea064124aa01c26f4b67db889df6874a9fc Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Sat, 26 Aug 2023 18:35:08 +0000 Subject: [PATCH 186/580] Update core files --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 8fe67530..06916106 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,8 @@ Many Minecraft versions are supported - request more if the one you want isn't y [Future Plans](#future-plans) ## Current Versions: -- Forge 1.18 +- Forge 1.19 +- Forge 1.19 - Fabric 1.18 - Forge 1.16 - Forge 1.12 From 6dec67a5150726548dee2225b853103d8c31b24a Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Sat, 26 Aug 2023 18:35:09 +0000 Subject: [PATCH 187/580] Update core files --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 8fe67530..06916106 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,8 @@ Many Minecraft versions are supported - request more if the one you want isn't y [Future Plans](#future-plans) ## Current Versions: -- Forge 1.18 +- Forge 1.19 +- Forge 1.19 - Fabric 1.18 - Forge 1.16 - Forge 1.12 From 7d934a605f6b822e37aeaf8246c04eaf0c1de08b Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Sat, 26 Aug 2023 18:35:11 +0000 Subject: [PATCH 188/580] Update core files --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 8fe67530..06916106 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,8 @@ Many Minecraft versions are supported - request more if the one you want isn't y [Future Plans](#future-plans) ## Current Versions: -- Forge 1.18 +- Forge 1.19 +- Forge 1.19 - Fabric 1.18 - Forge 1.16 - Forge 1.12 From 3cb943512cb8de69fc95ed37996f91503ce9a632 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Sun, 27 Aug 2023 17:53:09 +0000 Subject: [PATCH 189/580] Update core files --- .../advancedbackups/core/backups/BackupTimingThread.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java index c9cb675e..b346e89c 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java @@ -33,7 +33,7 @@ public void run() { private long calculateNextBackupTime() { long forcedMillis = BackupWrapper.mostRecentBackupTime() + (long) (AVConfig.config.getMaxTimer() * 3600000L); - if (forcedMillis == AVConfig.config.getMaxTimer() * 3600000L) forcedMillis = 300000; //sets it to 5m if no backup exists, to get the chain going + if (forcedMillis == AVConfig.config.getMaxTimer() * 3600000L || forcedMillis <= System.currentTimeMillis()) forcedMillis = 300000; //sets it to 5m if no backup exists or the timer is already execeeded to get the chain going else forcedMillis -= System.currentTimeMillis(); long ret = Long.MAX_VALUE; if (AVConfig.config.getUptimeSchedule() && !BackupWrapper.configuredPlaytime.isEmpty()) { From a63002b48604c03ab81350666862de8a05c2b281 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Sun, 27 Aug 2023 17:53:11 +0000 Subject: [PATCH 190/580] Update core files --- .../advancedbackups/core/backups/BackupTimingThread.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java index c9cb675e..b346e89c 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java @@ -33,7 +33,7 @@ public void run() { private long calculateNextBackupTime() { long forcedMillis = BackupWrapper.mostRecentBackupTime() + (long) (AVConfig.config.getMaxTimer() * 3600000L); - if (forcedMillis == AVConfig.config.getMaxTimer() * 3600000L) forcedMillis = 300000; //sets it to 5m if no backup exists, to get the chain going + if (forcedMillis == AVConfig.config.getMaxTimer() * 3600000L || forcedMillis <= System.currentTimeMillis()) forcedMillis = 300000; //sets it to 5m if no backup exists or the timer is already execeeded to get the chain going else forcedMillis -= System.currentTimeMillis(); long ret = Long.MAX_VALUE; if (AVConfig.config.getUptimeSchedule() && !BackupWrapper.configuredPlaytime.isEmpty()) { From 2d290c0209efe9ce7d63f430379660345e406bbd Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Sun, 27 Aug 2023 17:53:12 +0000 Subject: [PATCH 191/580] Update core files --- .../advancedbackups/core/backups/BackupTimingThread.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java index c9cb675e..b346e89c 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java @@ -33,7 +33,7 @@ public void run() { private long calculateNextBackupTime() { long forcedMillis = BackupWrapper.mostRecentBackupTime() + (long) (AVConfig.config.getMaxTimer() * 3600000L); - if (forcedMillis == AVConfig.config.getMaxTimer() * 3600000L) forcedMillis = 300000; //sets it to 5m if no backup exists, to get the chain going + if (forcedMillis == AVConfig.config.getMaxTimer() * 3600000L || forcedMillis <= System.currentTimeMillis()) forcedMillis = 300000; //sets it to 5m if no backup exists or the timer is already execeeded to get the chain going else forcedMillis -= System.currentTimeMillis(); long ret = Long.MAX_VALUE; if (AVConfig.config.getUptimeSchedule() && !BackupWrapper.configuredPlaytime.isEmpty()) { From 5e680e0e4315128aeb5dc6cf23ac8c6de1ef0dfe Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Sun, 27 Aug 2023 17:53:14 +0000 Subject: [PATCH 192/580] Update core files --- .../advancedbackups/core/backups/BackupTimingThread.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java index c9cb675e..b346e89c 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java @@ -33,7 +33,7 @@ public void run() { private long calculateNextBackupTime() { long forcedMillis = BackupWrapper.mostRecentBackupTime() + (long) (AVConfig.config.getMaxTimer() * 3600000L); - if (forcedMillis == AVConfig.config.getMaxTimer() * 3600000L) forcedMillis = 300000; //sets it to 5m if no backup exists, to get the chain going + if (forcedMillis == AVConfig.config.getMaxTimer() * 3600000L || forcedMillis <= System.currentTimeMillis()) forcedMillis = 300000; //sets it to 5m if no backup exists or the timer is already execeeded to get the chain going else forcedMillis -= System.currentTimeMillis(); long ret = Long.MAX_VALUE; if (AVConfig.config.getUptimeSchedule() && !BackupWrapper.configuredPlaytime.isEmpty()) { From 84c56e65140b918715c3df0a3c2c6b6582322303 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Sun, 27 Aug 2023 17:53:15 +0000 Subject: [PATCH 193/580] Update core files --- .../advancedbackups/core/backups/BackupTimingThread.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java index c9cb675e..b346e89c 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java @@ -33,7 +33,7 @@ public void run() { private long calculateNextBackupTime() { long forcedMillis = BackupWrapper.mostRecentBackupTime() + (long) (AVConfig.config.getMaxTimer() * 3600000L); - if (forcedMillis == AVConfig.config.getMaxTimer() * 3600000L) forcedMillis = 300000; //sets it to 5m if no backup exists, to get the chain going + if (forcedMillis == AVConfig.config.getMaxTimer() * 3600000L || forcedMillis <= System.currentTimeMillis()) forcedMillis = 300000; //sets it to 5m if no backup exists or the timer is already execeeded to get the chain going else forcedMillis -= System.currentTimeMillis(); long ret = Long.MAX_VALUE; if (AVConfig.config.getUptimeSchedule() && !BackupWrapper.configuredPlaytime.isEmpty()) { From 85d7c54c838c4cb4bd5c6b2e5d1a739bbde6cab9 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Sun, 27 Aug 2023 17:53:16 +0000 Subject: [PATCH 194/580] Update core files --- .../advancedbackups/core/backups/BackupTimingThread.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java index c9cb675e..b346e89c 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java @@ -33,7 +33,7 @@ public void run() { private long calculateNextBackupTime() { long forcedMillis = BackupWrapper.mostRecentBackupTime() + (long) (AVConfig.config.getMaxTimer() * 3600000L); - if (forcedMillis == AVConfig.config.getMaxTimer() * 3600000L) forcedMillis = 300000; //sets it to 5m if no backup exists, to get the chain going + if (forcedMillis == AVConfig.config.getMaxTimer() * 3600000L || forcedMillis <= System.currentTimeMillis()) forcedMillis = 300000; //sets it to 5m if no backup exists or the timer is already execeeded to get the chain going else forcedMillis -= System.currentTimeMillis(); long ret = Long.MAX_VALUE; if (AVConfig.config.getUptimeSchedule() && !BackupWrapper.configuredPlaytime.isEmpty()) { From 1b89476d71d2c4b1ca59fee47198bd14aaecc829 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Sun, 27 Aug 2023 22:23:33 +0000 Subject: [PATCH 195/580] Update core files --- .../core/backups/BackupWrapper.java | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java index f53771a2..f5960e0d 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java @@ -1,6 +1,12 @@ package co.uk.mommyheather.advancedbackups.core.backups; import java.io.File; +import java.io.FileOutputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.StringReader; import java.util.ArrayList; import java.util.Date; @@ -55,6 +61,8 @@ private static void prepareBackupDestination() { if (!file.exists()) { file.mkdirs(); } + prepareReadMe(file); + File zipFile = new File(file, "/zips/"); if (!zipFile.exists()) { zipFile.mkdirs(); @@ -69,6 +77,29 @@ private static void prepareBackupDestination() { } } + private static void prepareReadMe(File path) { + File readme = new File(path, "README-BEFORE-RESTORING.txt"); + if (!readme.exists()) { + try { + InputStream is = BackupWrapper.class.getClassLoader().getResourceAsStream("advancedbackups-readme.txt"); + readme.createNewFile(); + FileOutputStream outputStream = new FileOutputStream(readme); + byte[] buf = new byte[1028]; + int n; + while ((n = is.read(buf)) > 0) { + outputStream.write(buf, 0, n); + } + outputStream.flush(); + outputStream.close(); + + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + } + } + public static boolean checkMostRecentBackup() { // Return true if the time difference between the most recent backup and the backup-to-be From 82237b300d0fe29e24f5da43cdde1fa231fdd892 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Sun, 27 Aug 2023 22:23:34 +0000 Subject: [PATCH 196/580] Update core files --- .../core/backups/BackupWrapper.java | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java index f53771a2..f5960e0d 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java @@ -1,6 +1,12 @@ package co.uk.mommyheather.advancedbackups.core.backups; import java.io.File; +import java.io.FileOutputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.StringReader; import java.util.ArrayList; import java.util.Date; @@ -55,6 +61,8 @@ private static void prepareBackupDestination() { if (!file.exists()) { file.mkdirs(); } + prepareReadMe(file); + File zipFile = new File(file, "/zips/"); if (!zipFile.exists()) { zipFile.mkdirs(); @@ -69,6 +77,29 @@ private static void prepareBackupDestination() { } } + private static void prepareReadMe(File path) { + File readme = new File(path, "README-BEFORE-RESTORING.txt"); + if (!readme.exists()) { + try { + InputStream is = BackupWrapper.class.getClassLoader().getResourceAsStream("advancedbackups-readme.txt"); + readme.createNewFile(); + FileOutputStream outputStream = new FileOutputStream(readme); + byte[] buf = new byte[1028]; + int n; + while ((n = is.read(buf)) > 0) { + outputStream.write(buf, 0, n); + } + outputStream.flush(); + outputStream.close(); + + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + } + } + public static boolean checkMostRecentBackup() { // Return true if the time difference between the most recent backup and the backup-to-be From 5b466d2c8fb9a9790f5baa0fadc2ecf01a8b534b Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Sun, 27 Aug 2023 22:23:35 +0000 Subject: [PATCH 197/580] Update core files --- .../core/backups/BackupWrapper.java | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java index f53771a2..f5960e0d 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java @@ -1,6 +1,12 @@ package co.uk.mommyheather.advancedbackups.core.backups; import java.io.File; +import java.io.FileOutputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.StringReader; import java.util.ArrayList; import java.util.Date; @@ -55,6 +61,8 @@ private static void prepareBackupDestination() { if (!file.exists()) { file.mkdirs(); } + prepareReadMe(file); + File zipFile = new File(file, "/zips/"); if (!zipFile.exists()) { zipFile.mkdirs(); @@ -69,6 +77,29 @@ private static void prepareBackupDestination() { } } + private static void prepareReadMe(File path) { + File readme = new File(path, "README-BEFORE-RESTORING.txt"); + if (!readme.exists()) { + try { + InputStream is = BackupWrapper.class.getClassLoader().getResourceAsStream("advancedbackups-readme.txt"); + readme.createNewFile(); + FileOutputStream outputStream = new FileOutputStream(readme); + byte[] buf = new byte[1028]; + int n; + while ((n = is.read(buf)) > 0) { + outputStream.write(buf, 0, n); + } + outputStream.flush(); + outputStream.close(); + + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + } + } + public static boolean checkMostRecentBackup() { // Return true if the time difference between the most recent backup and the backup-to-be From 8a8141430842844dc240fe0ef6e7a7655f256f4f Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Sun, 27 Aug 2023 22:23:36 +0000 Subject: [PATCH 198/580] Update core files --- .../core/backups/BackupWrapper.java | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java index f53771a2..f5960e0d 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java @@ -1,6 +1,12 @@ package co.uk.mommyheather.advancedbackups.core.backups; import java.io.File; +import java.io.FileOutputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.StringReader; import java.util.ArrayList; import java.util.Date; @@ -55,6 +61,8 @@ private static void prepareBackupDestination() { if (!file.exists()) { file.mkdirs(); } + prepareReadMe(file); + File zipFile = new File(file, "/zips/"); if (!zipFile.exists()) { zipFile.mkdirs(); @@ -69,6 +77,29 @@ private static void prepareBackupDestination() { } } + private static void prepareReadMe(File path) { + File readme = new File(path, "README-BEFORE-RESTORING.txt"); + if (!readme.exists()) { + try { + InputStream is = BackupWrapper.class.getClassLoader().getResourceAsStream("advancedbackups-readme.txt"); + readme.createNewFile(); + FileOutputStream outputStream = new FileOutputStream(readme); + byte[] buf = new byte[1028]; + int n; + while ((n = is.read(buf)) > 0) { + outputStream.write(buf, 0, n); + } + outputStream.flush(); + outputStream.close(); + + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + } + } + public static boolean checkMostRecentBackup() { // Return true if the time difference between the most recent backup and the backup-to-be From b422e157c7904276b15f2f13a7e914c699ccfdc8 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Sun, 27 Aug 2023 22:23:37 +0000 Subject: [PATCH 199/580] Update core files --- .../core/backups/BackupWrapper.java | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java index f53771a2..f5960e0d 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java @@ -1,6 +1,12 @@ package co.uk.mommyheather.advancedbackups.core.backups; import java.io.File; +import java.io.FileOutputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.StringReader; import java.util.ArrayList; import java.util.Date; @@ -55,6 +61,8 @@ private static void prepareBackupDestination() { if (!file.exists()) { file.mkdirs(); } + prepareReadMe(file); + File zipFile = new File(file, "/zips/"); if (!zipFile.exists()) { zipFile.mkdirs(); @@ -69,6 +77,29 @@ private static void prepareBackupDestination() { } } + private static void prepareReadMe(File path) { + File readme = new File(path, "README-BEFORE-RESTORING.txt"); + if (!readme.exists()) { + try { + InputStream is = BackupWrapper.class.getClassLoader().getResourceAsStream("advancedbackups-readme.txt"); + readme.createNewFile(); + FileOutputStream outputStream = new FileOutputStream(readme); + byte[] buf = new byte[1028]; + int n; + while ((n = is.read(buf)) > 0) { + outputStream.write(buf, 0, n); + } + outputStream.flush(); + outputStream.close(); + + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + } + } + public static boolean checkMostRecentBackup() { // Return true if the time difference between the most recent backup and the backup-to-be From 8958f0627250afc86972cb74a168d312a0b2602a Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Sun, 27 Aug 2023 22:23:38 +0000 Subject: [PATCH 200/580] Update core files --- .../core/backups/BackupWrapper.java | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java index f53771a2..f5960e0d 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java @@ -1,6 +1,12 @@ package co.uk.mommyheather.advancedbackups.core.backups; import java.io.File; +import java.io.FileOutputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.StringReader; import java.util.ArrayList; import java.util.Date; @@ -55,6 +61,8 @@ private static void prepareBackupDestination() { if (!file.exists()) { file.mkdirs(); } + prepareReadMe(file); + File zipFile = new File(file, "/zips/"); if (!zipFile.exists()) { zipFile.mkdirs(); @@ -69,6 +77,29 @@ private static void prepareBackupDestination() { } } + private static void prepareReadMe(File path) { + File readme = new File(path, "README-BEFORE-RESTORING.txt"); + if (!readme.exists()) { + try { + InputStream is = BackupWrapper.class.getClassLoader().getResourceAsStream("advancedbackups-readme.txt"); + readme.createNewFile(); + FileOutputStream outputStream = new FileOutputStream(readme); + byte[] buf = new byte[1028]; + int n; + while ((n = is.read(buf)) > 0) { + outputStream.write(buf, 0, n); + } + outputStream.flush(); + outputStream.close(); + + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + } + } + public static boolean checkMostRecentBackup() { // Return true if the time difference between the most recent backup and the backup-to-be From 1bf8713b7932e09c9f029c87ffba85a2f2f4a68a Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Sun, 27 Aug 2023 22:30:15 +0000 Subject: [PATCH 201/580] Update core files --- .../cli/AdvancedBackupsCLI.java | 12 +++++++----- .../core/backups/ThreadedBackup.java | 19 +++++++++++-------- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java index b12d13d2..79f1afc1 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java @@ -41,6 +41,7 @@ public class AdvancedBackupsCLI { private static Scanner input = new Scanner(System.in); private static ArrayList fileNames = new ArrayList<>(); private static File worldFile; + private static String worldPath; public static void main(String args[]){ if (System.console() != null) { @@ -327,6 +328,7 @@ private static String getWorldName(File dir) { return getWorldName(dir); } + worldPath = worlds.get(worldIndex -1).replaceAll(" ", "_"); return worlds.get(worldIndex - 1); } @@ -339,11 +341,11 @@ private static int getBackupDate(File backupDir) throws IOException { info("Select a backup to restore."); for (File file : backupDir.listFiles()) { - if (file.getName().contains("manifest.json")) continue; + if (!file.getName().contains(worldPath)) continue; fileNames.add(file.getAbsolutePath()); String out = file.getName(); out = out.replaceAll(".zip", ""); - out = out.replaceAll("backup-", ": "); + out = out.replaceAll(worldPath + "_", ": "); out = out.replaceAll("-partial", "\u001B[33m partial\u001B[0m"); out = out.replaceAll("-full", "\u001B[32m full\u001B[0m"); info(fileNames.size() + out); @@ -781,7 +783,7 @@ public FileVisitResult postVisitDirectory(Path file, java.io.IOException arg1) { private static void backupExistingWorld(File worldDir) { try { - File out = new File(worldDir, "../cli" + ThreadedBackup.serialiseBackupName() + ".zip"); + File out = new File(worldDir, "../cli" + ThreadedBackup.serialiseBackupName("backup") + ".zip"); FileOutputStream outputStream = new FileOutputStream(out); ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream); zipOutputStream.setLevel(4); @@ -918,7 +920,7 @@ private static void addBackupNamesToLists(File file, HashMap en dates.put(entry.toString().replace("\\", "/"), "\u001b[31m" + backupName .substring(backupName.toString().lastIndexOf("/") + 1) - .replace("backup-", "") + .replace(worldPath + "_", "") .replace("-full.zip", "") .replace("-partial.zip", "") + "\u001B[0m"); @@ -935,7 +937,7 @@ public FileVisitResult visitFile(Path path, BasicFileAttributes attributes) thro dates.put(file.toPath().relativize(path).toString().replace("\\", "/"), "\u001b[31m" + backupName .substring(backupName.toString().lastIndexOf("/") + 1) - .replace("backup-", "") + .replace(worldPath + "_", "") .replace("-full", "") .replace("-partial", "") + "\u001B[0m"); diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java index 5165f7a7..b331c31b 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java @@ -31,6 +31,7 @@ public class ThreadedBackup extends Thread { private static float partialSize; private static float completeSize; public static boolean running = false; + private static String backupName; static { builder.setPrettyPrinting(); @@ -58,6 +59,7 @@ public void run() { running = true; File file = new File(AVConfig.config.getPath()); + backupName = serialiseBackupName(PlatformMethodWrapper.worldDir.getParent().toFile().getName().replaceAll(" ", "_")); switch(AVConfig.config.getBackupType()) { case "zip" : { @@ -81,7 +83,8 @@ public void run() { private static void makeZipBackup(File file) { try { - File zip = new File(file.toString() + "/zips/", serialiseBackupName() + ".zip"); + File zip = new File(file.toString() + "/zips/", backupName + ".zip"); + PlatformMethodWrapper.infoLogger.accept("Preparing zip backup name: " + zip.getName()); FileOutputStream outputStream = new FileOutputStream(zip); ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream); zipOutputStream.setLevel(AVConfig.config.getCompressionLevel()); @@ -122,7 +125,7 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { private static void makeDifferentialOrIncrementalBackup(File location, boolean differential) { try { - String name = serialiseBackupName(); + PlatformMethodWrapper.infoLogger.accept("Preparing " + (differential ? "differential" : "incremental") + " backup name: " + backupName); long time = 0; File manifestFile = differential ? new File(location.toString() + "/differential/manifest.json") : new File(location.toString() + "/incremental/manifest.json"); DifferentialManifest manifest; @@ -168,12 +171,12 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { toBackup.addAll(completeBackup); } - name += complete? "-full":"-partial"; + backupName += complete? "-full":"-partial"; if (AVConfig.config.getCompressChains()) { - File zip = differential ? new File(location.toString() + "/differential/", name +".zip") : new File(location.toString() + "/incremental/", name +".zip"); + File zip = differential ? new File(location.toString() + "/differential/", backupName +".zip") : new File(location.toString() + "/incremental/", backupName +".zip"); FileOutputStream outputStream = new FileOutputStream(zip); ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream); zipOutputStream.setLevel(AVConfig.config.getCompressionLevel()); @@ -190,7 +193,7 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { time = zip.lastModified(); } else { - File dest = differential ? new File(location.toString() + "/differential/", name + "/") :new File(location.toString() + "/incremental/", name + "/"); + File dest = differential ? new File(location.toString() + "/differential/", backupName + "/") :new File(location.toString() + "/incremental/", backupName + "/"); dest.mkdirs(); for (Path path : toBackup) { File out = new File(dest, path.toString()); @@ -228,10 +231,10 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { } - public static String serialiseBackupName() { + public static String serialiseBackupName(String in) { Date date = new Date(); - String pattern = "yyyy-MM-dd hh-mm-ss"; + String pattern = "yyyy-MM-dd_hh-mm-ss"; - return "backup-" + new SimpleDateFormat(pattern).format(date); + return in + "_" + new SimpleDateFormat(pattern).format(date); } } From 5b1cef937fc548f020139f145880eebeff6878f4 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Sun, 27 Aug 2023 22:30:16 +0000 Subject: [PATCH 202/580] Update core files --- .../cli/AdvancedBackupsCLI.java | 12 +++++++----- .../core/backups/ThreadedBackup.java | 19 +++++++++++-------- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java index b12d13d2..79f1afc1 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java @@ -41,6 +41,7 @@ public class AdvancedBackupsCLI { private static Scanner input = new Scanner(System.in); private static ArrayList fileNames = new ArrayList<>(); private static File worldFile; + private static String worldPath; public static void main(String args[]){ if (System.console() != null) { @@ -327,6 +328,7 @@ private static String getWorldName(File dir) { return getWorldName(dir); } + worldPath = worlds.get(worldIndex -1).replaceAll(" ", "_"); return worlds.get(worldIndex - 1); } @@ -339,11 +341,11 @@ private static int getBackupDate(File backupDir) throws IOException { info("Select a backup to restore."); for (File file : backupDir.listFiles()) { - if (file.getName().contains("manifest.json")) continue; + if (!file.getName().contains(worldPath)) continue; fileNames.add(file.getAbsolutePath()); String out = file.getName(); out = out.replaceAll(".zip", ""); - out = out.replaceAll("backup-", ": "); + out = out.replaceAll(worldPath + "_", ": "); out = out.replaceAll("-partial", "\u001B[33m partial\u001B[0m"); out = out.replaceAll("-full", "\u001B[32m full\u001B[0m"); info(fileNames.size() + out); @@ -781,7 +783,7 @@ public FileVisitResult postVisitDirectory(Path file, java.io.IOException arg1) { private static void backupExistingWorld(File worldDir) { try { - File out = new File(worldDir, "../cli" + ThreadedBackup.serialiseBackupName() + ".zip"); + File out = new File(worldDir, "../cli" + ThreadedBackup.serialiseBackupName("backup") + ".zip"); FileOutputStream outputStream = new FileOutputStream(out); ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream); zipOutputStream.setLevel(4); @@ -918,7 +920,7 @@ private static void addBackupNamesToLists(File file, HashMap en dates.put(entry.toString().replace("\\", "/"), "\u001b[31m" + backupName .substring(backupName.toString().lastIndexOf("/") + 1) - .replace("backup-", "") + .replace(worldPath + "_", "") .replace("-full.zip", "") .replace("-partial.zip", "") + "\u001B[0m"); @@ -935,7 +937,7 @@ public FileVisitResult visitFile(Path path, BasicFileAttributes attributes) thro dates.put(file.toPath().relativize(path).toString().replace("\\", "/"), "\u001b[31m" + backupName .substring(backupName.toString().lastIndexOf("/") + 1) - .replace("backup-", "") + .replace(worldPath + "_", "") .replace("-full", "") .replace("-partial", "") + "\u001B[0m"); diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java index 5165f7a7..b331c31b 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java @@ -31,6 +31,7 @@ public class ThreadedBackup extends Thread { private static float partialSize; private static float completeSize; public static boolean running = false; + private static String backupName; static { builder.setPrettyPrinting(); @@ -58,6 +59,7 @@ public void run() { running = true; File file = new File(AVConfig.config.getPath()); + backupName = serialiseBackupName(PlatformMethodWrapper.worldDir.getParent().toFile().getName().replaceAll(" ", "_")); switch(AVConfig.config.getBackupType()) { case "zip" : { @@ -81,7 +83,8 @@ public void run() { private static void makeZipBackup(File file) { try { - File zip = new File(file.toString() + "/zips/", serialiseBackupName() + ".zip"); + File zip = new File(file.toString() + "/zips/", backupName + ".zip"); + PlatformMethodWrapper.infoLogger.accept("Preparing zip backup name: " + zip.getName()); FileOutputStream outputStream = new FileOutputStream(zip); ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream); zipOutputStream.setLevel(AVConfig.config.getCompressionLevel()); @@ -122,7 +125,7 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { private static void makeDifferentialOrIncrementalBackup(File location, boolean differential) { try { - String name = serialiseBackupName(); + PlatformMethodWrapper.infoLogger.accept("Preparing " + (differential ? "differential" : "incremental") + " backup name: " + backupName); long time = 0; File manifestFile = differential ? new File(location.toString() + "/differential/manifest.json") : new File(location.toString() + "/incremental/manifest.json"); DifferentialManifest manifest; @@ -168,12 +171,12 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { toBackup.addAll(completeBackup); } - name += complete? "-full":"-partial"; + backupName += complete? "-full":"-partial"; if (AVConfig.config.getCompressChains()) { - File zip = differential ? new File(location.toString() + "/differential/", name +".zip") : new File(location.toString() + "/incremental/", name +".zip"); + File zip = differential ? new File(location.toString() + "/differential/", backupName +".zip") : new File(location.toString() + "/incremental/", backupName +".zip"); FileOutputStream outputStream = new FileOutputStream(zip); ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream); zipOutputStream.setLevel(AVConfig.config.getCompressionLevel()); @@ -190,7 +193,7 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { time = zip.lastModified(); } else { - File dest = differential ? new File(location.toString() + "/differential/", name + "/") :new File(location.toString() + "/incremental/", name + "/"); + File dest = differential ? new File(location.toString() + "/differential/", backupName + "/") :new File(location.toString() + "/incremental/", backupName + "/"); dest.mkdirs(); for (Path path : toBackup) { File out = new File(dest, path.toString()); @@ -228,10 +231,10 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { } - public static String serialiseBackupName() { + public static String serialiseBackupName(String in) { Date date = new Date(); - String pattern = "yyyy-MM-dd hh-mm-ss"; + String pattern = "yyyy-MM-dd_hh-mm-ss"; - return "backup-" + new SimpleDateFormat(pattern).format(date); + return in + "_" + new SimpleDateFormat(pattern).format(date); } } From fc8fe7f3b5ddcafa0c04806e6c6476535406de17 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Sun, 27 Aug 2023 22:30:18 +0000 Subject: [PATCH 203/580] Update core files --- .../cli/AdvancedBackupsCLI.java | 12 +++++++----- .../core/backups/ThreadedBackup.java | 19 +++++++++++-------- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java index b12d13d2..79f1afc1 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java @@ -41,6 +41,7 @@ public class AdvancedBackupsCLI { private static Scanner input = new Scanner(System.in); private static ArrayList fileNames = new ArrayList<>(); private static File worldFile; + private static String worldPath; public static void main(String args[]){ if (System.console() != null) { @@ -327,6 +328,7 @@ private static String getWorldName(File dir) { return getWorldName(dir); } + worldPath = worlds.get(worldIndex -1).replaceAll(" ", "_"); return worlds.get(worldIndex - 1); } @@ -339,11 +341,11 @@ private static int getBackupDate(File backupDir) throws IOException { info("Select a backup to restore."); for (File file : backupDir.listFiles()) { - if (file.getName().contains("manifest.json")) continue; + if (!file.getName().contains(worldPath)) continue; fileNames.add(file.getAbsolutePath()); String out = file.getName(); out = out.replaceAll(".zip", ""); - out = out.replaceAll("backup-", ": "); + out = out.replaceAll(worldPath + "_", ": "); out = out.replaceAll("-partial", "\u001B[33m partial\u001B[0m"); out = out.replaceAll("-full", "\u001B[32m full\u001B[0m"); info(fileNames.size() + out); @@ -781,7 +783,7 @@ public FileVisitResult postVisitDirectory(Path file, java.io.IOException arg1) { private static void backupExistingWorld(File worldDir) { try { - File out = new File(worldDir, "../cli" + ThreadedBackup.serialiseBackupName() + ".zip"); + File out = new File(worldDir, "../cli" + ThreadedBackup.serialiseBackupName("backup") + ".zip"); FileOutputStream outputStream = new FileOutputStream(out); ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream); zipOutputStream.setLevel(4); @@ -918,7 +920,7 @@ private static void addBackupNamesToLists(File file, HashMap en dates.put(entry.toString().replace("\\", "/"), "\u001b[31m" + backupName .substring(backupName.toString().lastIndexOf("/") + 1) - .replace("backup-", "") + .replace(worldPath + "_", "") .replace("-full.zip", "") .replace("-partial.zip", "") + "\u001B[0m"); @@ -935,7 +937,7 @@ public FileVisitResult visitFile(Path path, BasicFileAttributes attributes) thro dates.put(file.toPath().relativize(path).toString().replace("\\", "/"), "\u001b[31m" + backupName .substring(backupName.toString().lastIndexOf("/") + 1) - .replace("backup-", "") + .replace(worldPath + "_", "") .replace("-full", "") .replace("-partial", "") + "\u001B[0m"); diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java index 5165f7a7..b331c31b 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java @@ -31,6 +31,7 @@ public class ThreadedBackup extends Thread { private static float partialSize; private static float completeSize; public static boolean running = false; + private static String backupName; static { builder.setPrettyPrinting(); @@ -58,6 +59,7 @@ public void run() { running = true; File file = new File(AVConfig.config.getPath()); + backupName = serialiseBackupName(PlatformMethodWrapper.worldDir.getParent().toFile().getName().replaceAll(" ", "_")); switch(AVConfig.config.getBackupType()) { case "zip" : { @@ -81,7 +83,8 @@ public void run() { private static void makeZipBackup(File file) { try { - File zip = new File(file.toString() + "/zips/", serialiseBackupName() + ".zip"); + File zip = new File(file.toString() + "/zips/", backupName + ".zip"); + PlatformMethodWrapper.infoLogger.accept("Preparing zip backup name: " + zip.getName()); FileOutputStream outputStream = new FileOutputStream(zip); ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream); zipOutputStream.setLevel(AVConfig.config.getCompressionLevel()); @@ -122,7 +125,7 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { private static void makeDifferentialOrIncrementalBackup(File location, boolean differential) { try { - String name = serialiseBackupName(); + PlatformMethodWrapper.infoLogger.accept("Preparing " + (differential ? "differential" : "incremental") + " backup name: " + backupName); long time = 0; File manifestFile = differential ? new File(location.toString() + "/differential/manifest.json") : new File(location.toString() + "/incremental/manifest.json"); DifferentialManifest manifest; @@ -168,12 +171,12 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { toBackup.addAll(completeBackup); } - name += complete? "-full":"-partial"; + backupName += complete? "-full":"-partial"; if (AVConfig.config.getCompressChains()) { - File zip = differential ? new File(location.toString() + "/differential/", name +".zip") : new File(location.toString() + "/incremental/", name +".zip"); + File zip = differential ? new File(location.toString() + "/differential/", backupName +".zip") : new File(location.toString() + "/incremental/", backupName +".zip"); FileOutputStream outputStream = new FileOutputStream(zip); ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream); zipOutputStream.setLevel(AVConfig.config.getCompressionLevel()); @@ -190,7 +193,7 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { time = zip.lastModified(); } else { - File dest = differential ? new File(location.toString() + "/differential/", name + "/") :new File(location.toString() + "/incremental/", name + "/"); + File dest = differential ? new File(location.toString() + "/differential/", backupName + "/") :new File(location.toString() + "/incremental/", backupName + "/"); dest.mkdirs(); for (Path path : toBackup) { File out = new File(dest, path.toString()); @@ -228,10 +231,10 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { } - public static String serialiseBackupName() { + public static String serialiseBackupName(String in) { Date date = new Date(); - String pattern = "yyyy-MM-dd hh-mm-ss"; + String pattern = "yyyy-MM-dd_hh-mm-ss"; - return "backup-" + new SimpleDateFormat(pattern).format(date); + return in + "_" + new SimpleDateFormat(pattern).format(date); } } From b830fd9cac41279419692cafc901de765ad39200 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Sun, 27 Aug 2023 22:30:19 +0000 Subject: [PATCH 204/580] Update core files --- .../cli/AdvancedBackupsCLI.java | 12 +++++++----- .../core/backups/ThreadedBackup.java | 19 +++++++++++-------- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java index b12d13d2..79f1afc1 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java @@ -41,6 +41,7 @@ public class AdvancedBackupsCLI { private static Scanner input = new Scanner(System.in); private static ArrayList fileNames = new ArrayList<>(); private static File worldFile; + private static String worldPath; public static void main(String args[]){ if (System.console() != null) { @@ -327,6 +328,7 @@ private static String getWorldName(File dir) { return getWorldName(dir); } + worldPath = worlds.get(worldIndex -1).replaceAll(" ", "_"); return worlds.get(worldIndex - 1); } @@ -339,11 +341,11 @@ private static int getBackupDate(File backupDir) throws IOException { info("Select a backup to restore."); for (File file : backupDir.listFiles()) { - if (file.getName().contains("manifest.json")) continue; + if (!file.getName().contains(worldPath)) continue; fileNames.add(file.getAbsolutePath()); String out = file.getName(); out = out.replaceAll(".zip", ""); - out = out.replaceAll("backup-", ": "); + out = out.replaceAll(worldPath + "_", ": "); out = out.replaceAll("-partial", "\u001B[33m partial\u001B[0m"); out = out.replaceAll("-full", "\u001B[32m full\u001B[0m"); info(fileNames.size() + out); @@ -781,7 +783,7 @@ public FileVisitResult postVisitDirectory(Path file, java.io.IOException arg1) { private static void backupExistingWorld(File worldDir) { try { - File out = new File(worldDir, "../cli" + ThreadedBackup.serialiseBackupName() + ".zip"); + File out = new File(worldDir, "../cli" + ThreadedBackup.serialiseBackupName("backup") + ".zip"); FileOutputStream outputStream = new FileOutputStream(out); ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream); zipOutputStream.setLevel(4); @@ -918,7 +920,7 @@ private static void addBackupNamesToLists(File file, HashMap en dates.put(entry.toString().replace("\\", "/"), "\u001b[31m" + backupName .substring(backupName.toString().lastIndexOf("/") + 1) - .replace("backup-", "") + .replace(worldPath + "_", "") .replace("-full.zip", "") .replace("-partial.zip", "") + "\u001B[0m"); @@ -935,7 +937,7 @@ public FileVisitResult visitFile(Path path, BasicFileAttributes attributes) thro dates.put(file.toPath().relativize(path).toString().replace("\\", "/"), "\u001b[31m" + backupName .substring(backupName.toString().lastIndexOf("/") + 1) - .replace("backup-", "") + .replace(worldPath + "_", "") .replace("-full", "") .replace("-partial", "") + "\u001B[0m"); diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java index 5165f7a7..b331c31b 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java @@ -31,6 +31,7 @@ public class ThreadedBackup extends Thread { private static float partialSize; private static float completeSize; public static boolean running = false; + private static String backupName; static { builder.setPrettyPrinting(); @@ -58,6 +59,7 @@ public void run() { running = true; File file = new File(AVConfig.config.getPath()); + backupName = serialiseBackupName(PlatformMethodWrapper.worldDir.getParent().toFile().getName().replaceAll(" ", "_")); switch(AVConfig.config.getBackupType()) { case "zip" : { @@ -81,7 +83,8 @@ public void run() { private static void makeZipBackup(File file) { try { - File zip = new File(file.toString() + "/zips/", serialiseBackupName() + ".zip"); + File zip = new File(file.toString() + "/zips/", backupName + ".zip"); + PlatformMethodWrapper.infoLogger.accept("Preparing zip backup name: " + zip.getName()); FileOutputStream outputStream = new FileOutputStream(zip); ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream); zipOutputStream.setLevel(AVConfig.config.getCompressionLevel()); @@ -122,7 +125,7 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { private static void makeDifferentialOrIncrementalBackup(File location, boolean differential) { try { - String name = serialiseBackupName(); + PlatformMethodWrapper.infoLogger.accept("Preparing " + (differential ? "differential" : "incremental") + " backup name: " + backupName); long time = 0; File manifestFile = differential ? new File(location.toString() + "/differential/manifest.json") : new File(location.toString() + "/incremental/manifest.json"); DifferentialManifest manifest; @@ -168,12 +171,12 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { toBackup.addAll(completeBackup); } - name += complete? "-full":"-partial"; + backupName += complete? "-full":"-partial"; if (AVConfig.config.getCompressChains()) { - File zip = differential ? new File(location.toString() + "/differential/", name +".zip") : new File(location.toString() + "/incremental/", name +".zip"); + File zip = differential ? new File(location.toString() + "/differential/", backupName +".zip") : new File(location.toString() + "/incremental/", backupName +".zip"); FileOutputStream outputStream = new FileOutputStream(zip); ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream); zipOutputStream.setLevel(AVConfig.config.getCompressionLevel()); @@ -190,7 +193,7 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { time = zip.lastModified(); } else { - File dest = differential ? new File(location.toString() + "/differential/", name + "/") :new File(location.toString() + "/incremental/", name + "/"); + File dest = differential ? new File(location.toString() + "/differential/", backupName + "/") :new File(location.toString() + "/incremental/", backupName + "/"); dest.mkdirs(); for (Path path : toBackup) { File out = new File(dest, path.toString()); @@ -228,10 +231,10 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { } - public static String serialiseBackupName() { + public static String serialiseBackupName(String in) { Date date = new Date(); - String pattern = "yyyy-MM-dd hh-mm-ss"; + String pattern = "yyyy-MM-dd_hh-mm-ss"; - return "backup-" + new SimpleDateFormat(pattern).format(date); + return in + "_" + new SimpleDateFormat(pattern).format(date); } } From 238c2aec13217d4b26fc9e476d78bc0925948014 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Sun, 27 Aug 2023 22:30:20 +0000 Subject: [PATCH 205/580] Update core files --- .../cli/AdvancedBackupsCLI.java | 12 +++++++----- .../core/backups/ThreadedBackup.java | 19 +++++++++++-------- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java index b12d13d2..79f1afc1 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java @@ -41,6 +41,7 @@ public class AdvancedBackupsCLI { private static Scanner input = new Scanner(System.in); private static ArrayList fileNames = new ArrayList<>(); private static File worldFile; + private static String worldPath; public static void main(String args[]){ if (System.console() != null) { @@ -327,6 +328,7 @@ private static String getWorldName(File dir) { return getWorldName(dir); } + worldPath = worlds.get(worldIndex -1).replaceAll(" ", "_"); return worlds.get(worldIndex - 1); } @@ -339,11 +341,11 @@ private static int getBackupDate(File backupDir) throws IOException { info("Select a backup to restore."); for (File file : backupDir.listFiles()) { - if (file.getName().contains("manifest.json")) continue; + if (!file.getName().contains(worldPath)) continue; fileNames.add(file.getAbsolutePath()); String out = file.getName(); out = out.replaceAll(".zip", ""); - out = out.replaceAll("backup-", ": "); + out = out.replaceAll(worldPath + "_", ": "); out = out.replaceAll("-partial", "\u001B[33m partial\u001B[0m"); out = out.replaceAll("-full", "\u001B[32m full\u001B[0m"); info(fileNames.size() + out); @@ -781,7 +783,7 @@ public FileVisitResult postVisitDirectory(Path file, java.io.IOException arg1) { private static void backupExistingWorld(File worldDir) { try { - File out = new File(worldDir, "../cli" + ThreadedBackup.serialiseBackupName() + ".zip"); + File out = new File(worldDir, "../cli" + ThreadedBackup.serialiseBackupName("backup") + ".zip"); FileOutputStream outputStream = new FileOutputStream(out); ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream); zipOutputStream.setLevel(4); @@ -918,7 +920,7 @@ private static void addBackupNamesToLists(File file, HashMap en dates.put(entry.toString().replace("\\", "/"), "\u001b[31m" + backupName .substring(backupName.toString().lastIndexOf("/") + 1) - .replace("backup-", "") + .replace(worldPath + "_", "") .replace("-full.zip", "") .replace("-partial.zip", "") + "\u001B[0m"); @@ -935,7 +937,7 @@ public FileVisitResult visitFile(Path path, BasicFileAttributes attributes) thro dates.put(file.toPath().relativize(path).toString().replace("\\", "/"), "\u001b[31m" + backupName .substring(backupName.toString().lastIndexOf("/") + 1) - .replace("backup-", "") + .replace(worldPath + "_", "") .replace("-full", "") .replace("-partial", "") + "\u001B[0m"); diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java index 5165f7a7..b331c31b 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java @@ -31,6 +31,7 @@ public class ThreadedBackup extends Thread { private static float partialSize; private static float completeSize; public static boolean running = false; + private static String backupName; static { builder.setPrettyPrinting(); @@ -58,6 +59,7 @@ public void run() { running = true; File file = new File(AVConfig.config.getPath()); + backupName = serialiseBackupName(PlatformMethodWrapper.worldDir.getParent().toFile().getName().replaceAll(" ", "_")); switch(AVConfig.config.getBackupType()) { case "zip" : { @@ -81,7 +83,8 @@ public void run() { private static void makeZipBackup(File file) { try { - File zip = new File(file.toString() + "/zips/", serialiseBackupName() + ".zip"); + File zip = new File(file.toString() + "/zips/", backupName + ".zip"); + PlatformMethodWrapper.infoLogger.accept("Preparing zip backup name: " + zip.getName()); FileOutputStream outputStream = new FileOutputStream(zip); ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream); zipOutputStream.setLevel(AVConfig.config.getCompressionLevel()); @@ -122,7 +125,7 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { private static void makeDifferentialOrIncrementalBackup(File location, boolean differential) { try { - String name = serialiseBackupName(); + PlatformMethodWrapper.infoLogger.accept("Preparing " + (differential ? "differential" : "incremental") + " backup name: " + backupName); long time = 0; File manifestFile = differential ? new File(location.toString() + "/differential/manifest.json") : new File(location.toString() + "/incremental/manifest.json"); DifferentialManifest manifest; @@ -168,12 +171,12 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { toBackup.addAll(completeBackup); } - name += complete? "-full":"-partial"; + backupName += complete? "-full":"-partial"; if (AVConfig.config.getCompressChains()) { - File zip = differential ? new File(location.toString() + "/differential/", name +".zip") : new File(location.toString() + "/incremental/", name +".zip"); + File zip = differential ? new File(location.toString() + "/differential/", backupName +".zip") : new File(location.toString() + "/incremental/", backupName +".zip"); FileOutputStream outputStream = new FileOutputStream(zip); ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream); zipOutputStream.setLevel(AVConfig.config.getCompressionLevel()); @@ -190,7 +193,7 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { time = zip.lastModified(); } else { - File dest = differential ? new File(location.toString() + "/differential/", name + "/") :new File(location.toString() + "/incremental/", name + "/"); + File dest = differential ? new File(location.toString() + "/differential/", backupName + "/") :new File(location.toString() + "/incremental/", backupName + "/"); dest.mkdirs(); for (Path path : toBackup) { File out = new File(dest, path.toString()); @@ -228,10 +231,10 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { } - public static String serialiseBackupName() { + public static String serialiseBackupName(String in) { Date date = new Date(); - String pattern = "yyyy-MM-dd hh-mm-ss"; + String pattern = "yyyy-MM-dd_hh-mm-ss"; - return "backup-" + new SimpleDateFormat(pattern).format(date); + return in + "_" + new SimpleDateFormat(pattern).format(date); } } From ca38a8a9f7f1ccdd154fc8518d5aa3580ff86c15 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Sun, 27 Aug 2023 22:30:21 +0000 Subject: [PATCH 206/580] Update core files --- .../cli/AdvancedBackupsCLI.java | 12 +++++++----- .../core/backups/ThreadedBackup.java | 19 +++++++++++-------- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java index b12d13d2..79f1afc1 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java @@ -41,6 +41,7 @@ public class AdvancedBackupsCLI { private static Scanner input = new Scanner(System.in); private static ArrayList fileNames = new ArrayList<>(); private static File worldFile; + private static String worldPath; public static void main(String args[]){ if (System.console() != null) { @@ -327,6 +328,7 @@ private static String getWorldName(File dir) { return getWorldName(dir); } + worldPath = worlds.get(worldIndex -1).replaceAll(" ", "_"); return worlds.get(worldIndex - 1); } @@ -339,11 +341,11 @@ private static int getBackupDate(File backupDir) throws IOException { info("Select a backup to restore."); for (File file : backupDir.listFiles()) { - if (file.getName().contains("manifest.json")) continue; + if (!file.getName().contains(worldPath)) continue; fileNames.add(file.getAbsolutePath()); String out = file.getName(); out = out.replaceAll(".zip", ""); - out = out.replaceAll("backup-", ": "); + out = out.replaceAll(worldPath + "_", ": "); out = out.replaceAll("-partial", "\u001B[33m partial\u001B[0m"); out = out.replaceAll("-full", "\u001B[32m full\u001B[0m"); info(fileNames.size() + out); @@ -781,7 +783,7 @@ public FileVisitResult postVisitDirectory(Path file, java.io.IOException arg1) { private static void backupExistingWorld(File worldDir) { try { - File out = new File(worldDir, "../cli" + ThreadedBackup.serialiseBackupName() + ".zip"); + File out = new File(worldDir, "../cli" + ThreadedBackup.serialiseBackupName("backup") + ".zip"); FileOutputStream outputStream = new FileOutputStream(out); ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream); zipOutputStream.setLevel(4); @@ -918,7 +920,7 @@ private static void addBackupNamesToLists(File file, HashMap en dates.put(entry.toString().replace("\\", "/"), "\u001b[31m" + backupName .substring(backupName.toString().lastIndexOf("/") + 1) - .replace("backup-", "") + .replace(worldPath + "_", "") .replace("-full.zip", "") .replace("-partial.zip", "") + "\u001B[0m"); @@ -935,7 +937,7 @@ public FileVisitResult visitFile(Path path, BasicFileAttributes attributes) thro dates.put(file.toPath().relativize(path).toString().replace("\\", "/"), "\u001b[31m" + backupName .substring(backupName.toString().lastIndexOf("/") + 1) - .replace("backup-", "") + .replace(worldPath + "_", "") .replace("-full", "") .replace("-partial", "") + "\u001B[0m"); diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java index 5165f7a7..b331c31b 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java @@ -31,6 +31,7 @@ public class ThreadedBackup extends Thread { private static float partialSize; private static float completeSize; public static boolean running = false; + private static String backupName; static { builder.setPrettyPrinting(); @@ -58,6 +59,7 @@ public void run() { running = true; File file = new File(AVConfig.config.getPath()); + backupName = serialiseBackupName(PlatformMethodWrapper.worldDir.getParent().toFile().getName().replaceAll(" ", "_")); switch(AVConfig.config.getBackupType()) { case "zip" : { @@ -81,7 +83,8 @@ public void run() { private static void makeZipBackup(File file) { try { - File zip = new File(file.toString() + "/zips/", serialiseBackupName() + ".zip"); + File zip = new File(file.toString() + "/zips/", backupName + ".zip"); + PlatformMethodWrapper.infoLogger.accept("Preparing zip backup name: " + zip.getName()); FileOutputStream outputStream = new FileOutputStream(zip); ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream); zipOutputStream.setLevel(AVConfig.config.getCompressionLevel()); @@ -122,7 +125,7 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { private static void makeDifferentialOrIncrementalBackup(File location, boolean differential) { try { - String name = serialiseBackupName(); + PlatformMethodWrapper.infoLogger.accept("Preparing " + (differential ? "differential" : "incremental") + " backup name: " + backupName); long time = 0; File manifestFile = differential ? new File(location.toString() + "/differential/manifest.json") : new File(location.toString() + "/incremental/manifest.json"); DifferentialManifest manifest; @@ -168,12 +171,12 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { toBackup.addAll(completeBackup); } - name += complete? "-full":"-partial"; + backupName += complete? "-full":"-partial"; if (AVConfig.config.getCompressChains()) { - File zip = differential ? new File(location.toString() + "/differential/", name +".zip") : new File(location.toString() + "/incremental/", name +".zip"); + File zip = differential ? new File(location.toString() + "/differential/", backupName +".zip") : new File(location.toString() + "/incremental/", backupName +".zip"); FileOutputStream outputStream = new FileOutputStream(zip); ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream); zipOutputStream.setLevel(AVConfig.config.getCompressionLevel()); @@ -190,7 +193,7 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { time = zip.lastModified(); } else { - File dest = differential ? new File(location.toString() + "/differential/", name + "/") :new File(location.toString() + "/incremental/", name + "/"); + File dest = differential ? new File(location.toString() + "/differential/", backupName + "/") :new File(location.toString() + "/incremental/", backupName + "/"); dest.mkdirs(); for (Path path : toBackup) { File out = new File(dest, path.toString()); @@ -228,10 +231,10 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { } - public static String serialiseBackupName() { + public static String serialiseBackupName(String in) { Date date = new Date(); - String pattern = "yyyy-MM-dd hh-mm-ss"; + String pattern = "yyyy-MM-dd_hh-mm-ss"; - return "backup-" + new SimpleDateFormat(pattern).format(date); + return in + "_" + new SimpleDateFormat(pattern).format(date); } } From eefe4be51f35a3f27ca2fee9d2f72969e66a4969 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Mon, 28 Aug 2023 01:31:29 +0000 Subject: [PATCH 207/580] Update core files --- .../advancedbackups/cli/AdvancedBackupsCLI.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java index 79f1afc1..5787b961 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java @@ -42,7 +42,11 @@ public class AdvancedBackupsCLI { private static ArrayList fileNames = new ArrayList<>(); private static File worldFile; private static String worldPath; - public static void main(String args[]){ + public static void main(String args[]){ + + + System.out.print("\033[H\033[2J"); + System.out.flush(); if (System.console() != null) { AnsiConsole.systemInstall(); //this gets ansi escape codes working on windows. this was a FUCKING PAIN IN MY ASS From d6f7a7cf04c7fe2805feba2dbead685d6f58d5c3 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Mon, 28 Aug 2023 01:31:30 +0000 Subject: [PATCH 208/580] Update core files --- .../advancedbackups/cli/AdvancedBackupsCLI.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java index 79f1afc1..5787b961 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java @@ -42,7 +42,11 @@ public class AdvancedBackupsCLI { private static ArrayList fileNames = new ArrayList<>(); private static File worldFile; private static String worldPath; - public static void main(String args[]){ + public static void main(String args[]){ + + + System.out.print("\033[H\033[2J"); + System.out.flush(); if (System.console() != null) { AnsiConsole.systemInstall(); //this gets ansi escape codes working on windows. this was a FUCKING PAIN IN MY ASS From a0a6d0ade275983af982a230199d15e6f8869b53 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Mon, 28 Aug 2023 01:31:31 +0000 Subject: [PATCH 209/580] Update core files --- .../advancedbackups/cli/AdvancedBackupsCLI.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java index 79f1afc1..5787b961 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java @@ -42,7 +42,11 @@ public class AdvancedBackupsCLI { private static ArrayList fileNames = new ArrayList<>(); private static File worldFile; private static String worldPath; - public static void main(String args[]){ + public static void main(String args[]){ + + + System.out.print("\033[H\033[2J"); + System.out.flush(); if (System.console() != null) { AnsiConsole.systemInstall(); //this gets ansi escape codes working on windows. this was a FUCKING PAIN IN MY ASS From 4852aa1492d3a0057904d33410c3024d38d87220 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Mon, 28 Aug 2023 01:31:32 +0000 Subject: [PATCH 210/580] Update core files --- .../advancedbackups/cli/AdvancedBackupsCLI.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java index 79f1afc1..5787b961 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java @@ -42,7 +42,11 @@ public class AdvancedBackupsCLI { private static ArrayList fileNames = new ArrayList<>(); private static File worldFile; private static String worldPath; - public static void main(String args[]){ + public static void main(String args[]){ + + + System.out.print("\033[H\033[2J"); + System.out.flush(); if (System.console() != null) { AnsiConsole.systemInstall(); //this gets ansi escape codes working on windows. this was a FUCKING PAIN IN MY ASS From a3c10b210d70bf85081df60310ad36e3193c8de6 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Mon, 28 Aug 2023 01:31:33 +0000 Subject: [PATCH 211/580] Update core files --- .../advancedbackups/cli/AdvancedBackupsCLI.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java index 79f1afc1..5787b961 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java @@ -42,7 +42,11 @@ public class AdvancedBackupsCLI { private static ArrayList fileNames = new ArrayList<>(); private static File worldFile; private static String worldPath; - public static void main(String args[]){ + public static void main(String args[]){ + + + System.out.print("\033[H\033[2J"); + System.out.flush(); if (System.console() != null) { AnsiConsole.systemInstall(); //this gets ansi escape codes working on windows. this was a FUCKING PAIN IN MY ASS From dd2be31fb110080445f4f94efd82d67e0881bafa Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Mon, 28 Aug 2023 01:31:33 +0000 Subject: [PATCH 212/580] Update core files --- .../advancedbackups/cli/AdvancedBackupsCLI.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java index 79f1afc1..5787b961 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java @@ -42,7 +42,11 @@ public class AdvancedBackupsCLI { private static ArrayList fileNames = new ArrayList<>(); private static File worldFile; private static String worldPath; - public static void main(String args[]){ + public static void main(String args[]){ + + + System.out.print("\033[H\033[2J"); + System.out.flush(); if (System.console() != null) { AnsiConsole.systemInstall(); //this gets ansi escape codes working on windows. this was a FUCKING PAIN IN MY ASS From 329182beaebc9b479f99b887adfdecafc64c0e7a Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Tue, 29 Aug 2023 23:06:47 +0000 Subject: [PATCH 213/580] Update core files --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 06916106..08708d53 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Many Minecraft versions are supported - request more if the one you want isn't y ## Current Versions: - Forge 1.19 -- Forge 1.19 +- Forge 1.18 - Fabric 1.18 - Forge 1.16 - Forge 1.12 From 260388e7576964a8bed0e27f8ad95f0a89b66958 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Tue, 29 Aug 2023 23:06:48 +0000 Subject: [PATCH 214/580] Update core files --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 06916106..08708d53 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Many Minecraft versions are supported - request more if the one you want isn't y ## Current Versions: - Forge 1.19 -- Forge 1.19 +- Forge 1.18 - Fabric 1.18 - Forge 1.16 - Forge 1.12 From 82f4dfde9b5c2f587acbea642ae753c33fcd0ec7 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Tue, 29 Aug 2023 23:06:49 +0000 Subject: [PATCH 215/580] Update core files --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 06916106..08708d53 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Many Minecraft versions are supported - request more if the one you want isn't y ## Current Versions: - Forge 1.19 -- Forge 1.19 +- Forge 1.18 - Fabric 1.18 - Forge 1.16 - Forge 1.12 From d766bc055db566fa1c16c8e92ff4eef2ff18895c Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Tue, 29 Aug 2023 23:06:50 +0000 Subject: [PATCH 216/580] Update core files --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 06916106..08708d53 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Many Minecraft versions are supported - request more if the one you want isn't y ## Current Versions: - Forge 1.19 -- Forge 1.19 +- Forge 1.18 - Fabric 1.18 - Forge 1.16 - Forge 1.12 From 3089aa5653a88e24a5798eb45164d8fe696a0f7e Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Tue, 29 Aug 2023 23:06:52 +0000 Subject: [PATCH 217/580] Update core files --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 06916106..08708d53 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Many Minecraft versions are supported - request more if the one you want isn't y ## Current Versions: - Forge 1.19 -- Forge 1.19 +- Forge 1.18 - Fabric 1.18 - Forge 1.16 - Forge 1.12 From 49bc86e1cea844effb13fea2d243a08cdc36f308 Mon Sep 17 00:00:00 2001 From: MommyHeather <> Date: Tue, 29 Aug 2023 23:06:53 +0000 Subject: [PATCH 218/580] Update core files --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 06916106..08708d53 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Many Minecraft versions are supported - request more if the one you want isn't y ## Current Versions: - Forge 1.19 -- Forge 1.19 +- Forge 1.18 - Fabric 1.18 - Forge 1.16 - Forge 1.12 From 6d14ea65ff0aa45a4cb03d358f3437cfb54f88ba Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Wed, 30 Aug 2023 20:27:43 +0100 Subject: [PATCH 219/580] Port to the new system of having core compiled separately. --- build.gradle | 9 +- .../advancedbackups/AdvancedBackups.java | 72 +- .../PlatformMethodWrapper.java | 67 -- .../cli/AdvancedBackupsCLI.java | 948 ------------------ .../core/CoreCommandSystem.java | 77 -- .../core/backups/BackupCheckEnum.java | 38 - .../core/backups/BackupTimingThread.java | 74 -- .../core/backups/BackupWrapper.java | 242 ----- .../core/backups/ThreadedBackup.java | 237 ----- .../backups/gson/DifferentialManifest.java | 73 -- .../advancedbackups/core/config/AVConfig.java | 165 --- .../core/config/ConfigData.java | 378 ------- 12 files changed, 73 insertions(+), 2307 deletions(-) delete mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/PlatformMethodWrapper.java delete mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java delete mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java delete mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupCheckEnum.java delete mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java delete mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java delete mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java delete mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/core/backups/gson/DifferentialManifest.java delete mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java delete mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java diff --git a/build.gradle b/build.gradle index 8f716f15..a6bb7622 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ plugins { -version = '1.0' +version = '2.0' group = 'co.uk.mommyheather.advancedbackups' // http://maven.apache.org/guides/mini/guide-naming-conventions.html archivesBaseName = 'AdvancedBackups-' + modloaderName + "-" + minecraftVersion @@ -119,8 +119,11 @@ dependencies { // that the dep is a ForgeGradle 'patcher' dependency, and its patches will be applied. // The userdev artifact is a special name and will get all sorts of transformations applied to it. minecraft 'net.minecraftforge:forge:1.19.2-43.2.0' - implementation files('dependencies/jansi-2.4.0.jar') - extraLibs files('dependencies/jansi-2.4.0.jar') + //implementation files('dependencies/jansi-2.4.0.jar') + //extraLibs files('dependencies/jansi-2.4.0.jar') + + minecraftLibrary files ('../advancedbackups-corelib.jar') + extraLibs files ('../advancedbackups-corelib.jar') // Real mod deobf dependency examples - these get remapped to your current mappings // compileOnly fg.deobf("mezz.jei:jei-${mc_version}:${jei_version}:api") // Adds JEI API as a compile dependency diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 9d35e69e..17859990 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -2,12 +2,16 @@ import com.mojang.logging.LogUtils; +import co.uk.mommyheather.advancedbackups.core.ABCore; import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; -import co.uk.mommyheather.advancedbackups.core.config.AVConfig; +import co.uk.mommyheather.advancedbackups.core.config.ABConfig; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.storage.LevelResource; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.server.ServerLifecycleHooks; import net.minecraftforge.event.RegisterCommandsEvent; import net.minecraftforge.event.entity.player.PlayerEvent; import net.minecraftforge.event.server.ServerStartedEvent; @@ -39,10 +43,18 @@ public AdvancedBackups() public void onServerStarting(ServerStartingEvent event) { // Do something when the server starts - AVConfig.loadOrCreateConfig(); + ABConfig.loadOrCreateConfig(); LOGGER.info("Config loaded!!"); - PlatformMethodWrapper.worldName = event.getServer().getWorldData().getLevelName(); - PlatformMethodWrapper.worldDir = event.getServer().getWorldPath(LevelResource.ROOT); + ABCore.worldName = event.getServer().getWorldData().getLevelName(); + ABCore.worldDir = event.getServer().getWorldPath(LevelResource.ROOT); + + ABCore.disableSaving = AdvancedBackups::disableSaving; + ABCore.enableSaving = AdvancedBackups::enableSaving; + ABCore.saveOnce = AdvancedBackups::saveOnce; + + ABCore.infoLogger = infoLogger; + ABCore.warningLogger = warningLogger; + ABCore.errorLogger = errorLogger; } @@ -59,7 +71,7 @@ public void onServerStopping(ServerStoppingEvent event) { @SubscribeEvent public void onPlayerJoined(PlayerEvent.PlayerLoggedInEvent event) { - PlatformMethodWrapper.activity = true; + ABCore.setActivity(); } @SubscribeEvent @@ -67,4 +79,54 @@ public void registerCommands(RegisterCommandsEvent event){ AdvancedBackupsCommand.register(event.getDispatcher()); } + + public static final String savesDisabledMessage = """ + + + *************************************** + SAVING DISABLED - PREPARING FOR BACKUP! + *************************************** + """; + public static final String savesEnabledMessage = """ + + + ********************************* + SAVING ENABLED - BACKUP COMPLETE! + ********************************* + """; + public static final String saveCompleteMessage = """ + + + ************************************* + SAVE COMPLETE - PREPARING FOR BACKUP! + ************************************* + """; + + + public static void disableSaving() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + for (ServerLevel level : server.getAllLevels()) { + if (level != null && !level.noSave) { + level.noSave = true; + } + } + warningLogger.accept(savesDisabledMessage); + } + + public static void enableSaving() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + for (ServerLevel level : server.getAllLevels()) { + if (level != null && !level.noSave) { + level.noSave = false; + } + } + warningLogger.accept(savesEnabledMessage); + } + + public static void saveOnce() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + server.saveEverything(true, true, true); + warningLogger.accept(saveCompleteMessage); + } + } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/PlatformMethodWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/PlatformMethodWrapper.java deleted file mode 100644 index b47a0d95..00000000 --- a/src/main/java/co/uk/mommyheather/advancedbackups/PlatformMethodWrapper.java +++ /dev/null @@ -1,67 +0,0 @@ -package co.uk.mommyheather.advancedbackups; - -import java.nio.file.Path; -import java.util.function.Consumer; - -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ServerLevel; -import net.minecraftforge.server.ServerLifecycleHooks; - -public class PlatformMethodWrapper { - - public static String worldName = ""; - public static Path worldDir = null; - public static Boolean activity = false; - public static final Consumer infoLogger = AdvancedBackups.infoLogger; - public static final Consumer warningLogger = AdvancedBackups.warningLogger; - public static final Consumer errorLogger = AdvancedBackups.errorLogger; - - public static final String savesDisabledMessage = """ - - -*************************************** -SAVING DISABLED - PREPARING FOR BACKUP! -*************************************** -"""; - public static final String savesEnabledMessage = """ - - -********************************* -SAVING ENABLED - BACKUP COMPLETE! -********************************* -"""; - public static final String saveCompleteMessage = """ - - -************************************* -SAVE COMPLETE - PREPARING FOR BACKUP! -************************************* -"""; - - - public static void disableSaving() { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - for (ServerLevel level : server.getAllLevels()) { - if (level != null && !level.noSave) { - level.noSave = true; - } - } - warningLogger.accept(savesDisabledMessage); - } - - public static void enableSaving() { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - for (ServerLevel level : server.getAllLevels()) { - if (level != null && !level.noSave) { - level.noSave = false; - } - } - warningLogger.accept(savesEnabledMessage); - } - - public static void saveOnce() { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - server.saveEverything(true, true, true); - warningLogger.accept(saveCompleteMessage); - } -} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java deleted file mode 100644 index b12d13d2..00000000 --- a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java +++ /dev/null @@ -1,948 +0,0 @@ -package co.uk.mommyheather.advancedbackups.cli; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.FileReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.nio.file.FileSystem; -import java.nio.file.FileSystems; -import java.nio.file.FileVisitResult; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.SimpleFileVisitor; -import java.nio.file.StandardCopyOption; -import java.nio.file.attribute.BasicFileAttributes; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.InputMismatchException; -import java.util.Properties; -import java.util.Scanner; -import java.util.regex.Pattern; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; -import java.util.zip.ZipInputStream; -import java.util.zip.ZipOutputStream; - -import org.fusesource.jansi.AnsiConsole; - -import co.uk.mommyheather.advancedbackups.core.backups.ThreadedBackup; - -public class AdvancedBackupsCLI { - - private static String backupLocation; - private static File serverDir = new File(new File("").toPath().toAbsolutePath().getParent().toString()); - private static String type; - private static Scanner input = new Scanner(System.in); - private static ArrayList fileNames = new ArrayList<>(); - private static File worldFile; - public static void main(String args[]){ - - if (System.console() != null) { - AnsiConsole.systemInstall(); //this gets ansi escape codes working on windows. this was a FUCKING PAIN IN MY ASS - } - - - info("Advanced Backups - Version " + AdvancedBackupsCLI.class.getPackage().getImplementationVersion()); - info("Searching for properties...", false); - - Properties props = new Properties(); - File file = new File(serverDir, "AdvancedBackups.properties"); - FileReader reader; - try { - reader = new FileReader(file); - props.load(reader); - - backupLocation = props.getProperty("config.advancedbackups.path"); - type = props.getProperty("config.advancedbackups.type"); - } catch (Exception e) { - error("ERROR LOADING PROPERTIES!"); - error(getStackTrace(e)); - error(""); - error(""); - error("Ensure you're running this from within the mods directory, and the config file is in the parent directory!"); - // Fatal, cannot proceed - return; - } - - if (backupLocation == null || type == null) { - error("ERROR LOADING PROPERTIES!"); - error("Backup location : " + backupLocation); - error("Type : " + type); - // Fatal, cannot proceed - return; - } - - info("Config loaded!"); - - type = getBackupType(); - - worldFile = getWorldFile(); - - if (!worldFile.exists()) { - error("Unable to find world folder!"); - error(worldFile.getAbsolutePath()); - error("Check if the location exists and the name is correct and try again."); - return; - - } - - - File backupDir; - - if (backupLocation.startsWith(Pattern.quote(File.separator))) { - backupDir = new File(backupLocation, File.separator + type + File.separator); - } - else { - backupDir = new File(serverDir, backupLocation.replaceAll(Pattern.quote("." + File.separator), "") + File.separator + type + File.separator); - } - - if (!backupDir.exists()) { - error("Could not find backup directory!"); - error(backupDir.getAbsolutePath()); - error("Have you made any backups before?"); - //Fatal, cannot continue - return; - } - - int backupDateIndex; - try { - backupDateIndex = getBackupDate(backupDir); - } catch (IOException e) { - error("ERROR VIEWING BACKUPS!"); - e.printStackTrace(); - return; - } - - - String restore = restoreWorldOrFile(); - - if (!confirmWarningMessage()) { - error("ABORTED - WILL NOT PROCEED."); - return; - } - - info("Preparing..."); - - - - switch(restore) { - case "world" : { - //No going back now! - //TODO : make a backup of current world state. - deleteEntireWorld(worldFile); - switch(type) { - case "zips" : { - restoreFullZip(backupDateIndex, worldFile); - return; - } - case "differential" : { - restoreFullDifferential(backupDateIndex, worldFile); - return; - } - case "incremental" : { - restoreFullIncremental(backupDateIndex, worldFile); - return; - } - } - } - case "file" : { - switch(type) { - case "zips" : { - restorePartialZip(backupDateIndex, worldFile); - return; - } - case "differential" : { - restorePartialDifferential(backupDateIndex, worldFile); - return; - } - case "incremental" : { - restorePartialIncremental(backupDateIndex, worldFile); - return; - } - } - } - } - - - } - - - - - - - - - - - - - - - - - - - //HELPER METHODS! - private static void info(String out, boolean line) { - if (line) System.out.println(out); - else System.out.print(out); - - } - - private static void warn(String out, boolean line) { - if (line) System.out.println("\u001B[33m" + out + "\u001B[0m"); - else System.out.print("\u001B[33m" + out + "\u001B[0m"); - - } - - private static void error(String out, boolean line) { - if (line) System.out.println("\u001B[31m" + out + "\u001B[0m"); - else System.out.print("\u001B[31m" + out + "\u001B[0m"); - - } - - private static void info(String out) { - info(out, true); - } - - private static void warn(String out) { - warn(out, true); - } - - private static void error(String out) { - error(out, true); - } - - - private static String getStackTrace(final Throwable throwable) { - final StringWriter sw = new StringWriter(); - final PrintWriter pw = new PrintWriter(sw, true); - throwable.printStackTrace(pw); - return sw.getBuffer().toString(); - } - - private static String getBackupType() { - // Select a type of backup to restore - info("Select a backup type to restore. Your server is currently set to use " + type + " backups."); - info("1: zip\n2: differential\n3: incremental"); - info("Enter a number or leave blank for " + type + "."); - int inputType; - try { - String line = input.nextLine(); - if (line == "") { - return type; - } - inputType = Integer.parseInt(line); - } catch (InputMismatchException | NumberFormatException e) { - warn("That was not a number. Please enter a number."); - return getBackupType(); - } - switch (inputType) { - case 1 : return "zips"; - case 2 : return "differential"; - case 3 : return "incremental"; - default : { - warn("Please pick an option between 1 and 3 inclusive."); - return getBackupType(); - } - } - } - - - private static File getWorldFile() { - info("Are you on a client or server?"); - info("1: Client\n2: Server"); - info("Enter a number."); - - int inputType; - File ret = new File(serverDir.getAbsolutePath()); - - try { - String line = input.nextLine(); - if (line == "") { - warn("Please enter a number."); - return getWorldFile(); - } - inputType = Integer.parseInt(line); - } catch (InputMismatchException | NumberFormatException e) { - warn("That was not a number. Please enter a number."); - return getWorldFile(); - } - - if (inputType < 1 || inputType > 2) { - warn("Please enter 1 or 2."); - return getWorldFile(); - } - - if (inputType == 1) { - ret = new File(ret, "/saves/"); - } - - ret = new File(ret, getWorldName(ret)); - return ret; - - } - - private static String getWorldName(File dir) { - ArrayList worlds = new ArrayList<>(); - int worldIndex; - for (File file : dir.listFiles()) { - boolean flag = false; - if (!file.isDirectory()) continue; - for (File file2 : file.listFiles()) { - if (file2.getName().contains("level.dat")) { - flag = true; - } - } - if (flag) { - worlds.add(file.getName()); - } - } - info("Please select your world. Default for servers is \"world\"."); - int index = 1; - for (String world : worlds) { - info (index + ". " + world); - index++; - } - try { - String line = input.nextLine(); - if (line == "") { - warn("Please enter a number."); - return getWorldName(dir); - } - worldIndex = Integer.parseInt(line); - } catch (InputMismatchException | NumberFormatException e) { - warn("That was not a number. Please enter a number."); - return getWorldName(dir); - } - if (worldIndex < 1 || worldIndex > worlds.size()) { - warn("Please enter a number between " + worlds.size() + "."); - return getWorldName(dir); - } - - return worlds.get(worldIndex - 1); - - } - - - private static int getBackupDate(File backupDir) throws IOException { - fileNames.clear(); - int inputType; - - info("Select a backup to restore."); - - for (File file : backupDir.listFiles()) { - if (file.getName().contains("manifest.json")) continue; - fileNames.add(file.getAbsolutePath()); - String out = file.getName(); - out = out.replaceAll(".zip", ""); - out = out.replaceAll("backup-", ": "); - out = out.replaceAll("-partial", "\u001B[33m partial\u001B[0m"); - out = out.replaceAll("-full", "\u001B[32m full\u001B[0m"); - info(fileNames.size() + out); - } - - try { - String line = input.nextLine(); - if (line == "") { - warn("Please enter a number."); - return getBackupDate(backupDir); - } - inputType = Integer.parseInt(line); - } catch (InputMismatchException | NumberFormatException e) { - warn("That was not a number. Please enter a number."); - return getBackupDate(backupDir); - } - - if (inputType < 1 || inputType > fileNames.size()) { - warn("Please enter a number between " + fileNames.size() + "."); - return getBackupDate(backupDir); - } - - return inputType - 1; - } - - private static String restoreWorldOrFile() { - info("Do you want to restore the entire world state at this point, or a singular file?"); - info("1: Entire world\n2: Single file"); - info("Enter a number."); - int inputType; - try { - String line = input.nextLine(); - if (line == "") { - return type; - } - inputType = Integer.parseInt(line); - } catch (InputMismatchException | NumberFormatException e) { - warn("That was not a number. Please enter a number."); - return restoreWorldOrFile(); - } - switch (inputType) { - case 1 : return "world"; - case 2 : return "file"; - default : { - warn("Please pick 1 or 2."); - return restoreWorldOrFile(); - } - } - - } - - - - private static boolean confirmWarningMessage() { - warn(""); - warn(""); - warn("WARNING! DOING THIS WHILST THE SERVER IS RUNNING CAN CAUSE SEVERE CORRUPTION, PARTIAL RESTORATION, AND OTHER ISSUES."); - warn("TYPE \"continue\" IF YOU WISH TO CONTINUE...", false); - - - String line = input.nextLine(); - if (line.equals("")) { - return confirmWarningMessage(); - } - return line.equals("continue"); - } - - - private static void restoreFullZip(int index, File worldFile) { - byte[] buffer = new byte[1024]; - //The most basic of the bunch. - ZipEntry entry; - try { - FileInputStream fileInputStream = new FileInputStream(fileNames.get(index)); - ZipInputStream zip = new ZipInputStream(fileInputStream); - while ((entry = zip.getNextEntry()) != null) { - File outputFile; - - //FTB Backups and some other mods need special handling. - if (entry.getName().startsWith(worldFile.getName())) { - outputFile = new File(worldFile.getParentFile(), entry.getName()); - } - else { - outputFile = new File(worldFile, entry.getName()); - } - - if (!outputFile.getParentFile().exists()) { - outputFile.getParentFile().mkdirs(); - } - - FileOutputStream outputStream = new FileOutputStream(outputFile); - int length = 0; - while ((length = zip.read(buffer)) > 0) { - outputStream.write(buffer, 0, length); - } - outputStream.close(); - } - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - - private static void restoreFullDifferential(int index, File worldFile) { - //Do we need to check for past backups? if selected is a full backup, we do not. - File backup = new File(fileNames.get(index)); - if (backup.getName().contains("-full")) { - if (backup.isFile()) { - restoreFullZip(index, worldFile); - return; - } - restoreFolder(index, worldFile); - return; - } - //find last FULL backup - for (int i = index;i>0;i--) { - String name = fileNames.get(i); - if (name.contains("-full")) { - info("Restoring last full backup..."); - File file = new File(name); - if (file.isFile()) { - restoreFullZip(i, worldFile); - } - else { - restoreFolder(i, worldFile); - } - break; - } - } - info("\n\nRestoring selected backup..."); - if (backup.isFile()) { - restoreFullZip(index, worldFile); - } - else { - restoreFolder(index, worldFile); - } - } - - private static void restoreFullIncremental(int index, File worldFile) { - //Do we need to check for past backups? if selected is a full backup, we do not. - File backup = new File(fileNames.get(index)); - if (backup.getName().contains("-full")) { - if (backup.isFile()) { - restoreFullZip(index, worldFile); - return; - } - restoreFolder(index, worldFile); - return; - } - //find last FULL backup - int i = index; - while(i >= 0) { - String name = fileNames.get(i); - if (name.contains("-full")) { - info("Restoring last full backup..."); - File file = new File(name); - if (file.isFile()) { - restoreFullZip(i, worldFile); - } - else { - restoreFolder(i, worldFile); - } - break; - } - i--; - } - //restore backups up until the selected one - while(i < index) { - String name = fileNames.get(i); - info("Restoring chained backup..."); - File file = new File(name); - if (file.isFile()) { - restoreFullZip(i, worldFile); - } - else { - restoreFolder(i, worldFile); - } - i++; - } - - - info("\n\nRestoring selected backup..."); - if (backup.isFile()) { - restoreFullZip(index, worldFile); - } - else { - restoreFolder(index, worldFile); - } - } - - private static void restorePartialZip(int index, File worldFile) { - Path file; - HashMap entries = new HashMap<>(); - - try { - FileSystem zipFs = FileSystems.newFileSystem(new File(fileNames.get(index)).toPath(), AdvancedBackupsCLI.class.getClassLoader()); - Path root = zipFs.getPath(""); - Files.walkFileTree(root, new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) throws IOException { - entries.put(file.toString(), file); - return FileVisitResult.CONTINUE; - } - }); - - file = getFileToRestore(entries, ""); - info("Restoring " + file.toString() + "..."); - Path outputFile = new File(worldFile, file.toString()).toPath(); - Files.copy(file, outputFile, StandardCopyOption.REPLACE_EXISTING); - info("Done."); - - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - return; - } - - } - - private static void restorePartialDifferential(int index, File worldFile) { - //Do we need to check for past backups? if selected is a full backup, we do not. - HashMap filePaths = new HashMap<>(); - HashMap dates = new HashMap<>(); - HashMap entryOwners = new HashMap<>(); - try { - File backup = new File(fileNames.get(index)); - if (!backup.getName().contains("-full")) { - //find last FULL backup - for (int i = index;i>=0;i--) { - String name = fileNames.get(i); - if (name.contains("-full")) { - addBackupNamesToLists(new File(name), entryOwners, filePaths, dates, "\u001b[31m"); - break; - } - } - } - - File file = new File(fileNames.get(index)); - addBackupNamesToLists(file, entryOwners, filePaths, dates, "\u001B[32m"); - - HashMap properMapping = new HashMap<>(); - for (String date : dates.keySet()) { - properMapping.put( - date + " " + dates.get(date), - filePaths.get(date) - ); - } - - Object select = getFileToRestore(properMapping, ""); - if (select instanceof Path) { - Path input = (Path) select; - - - if (select.toString().replace("\\", "/").contains("-full/")) { - select = new File( - select.toString().replace("\\", "/") - .split("-full/")[1] - ).toPath(); - } - if (select.toString().replace("\\", "/").contains("-partial/")) { - select = new File( - select.toString().replace("\\", "/") - .split("-partial/")[1] - ).toPath(); - } - - File outputFile = new File(worldFile, select.toString()); - if (!outputFile.getParentFile().exists()) { - outputFile.getParentFile().mkdirs(); - } - info("\n\nRestoring file : " + select); - Files.copy(input, outputFile.toPath(), StandardCopyOption.REPLACE_EXISTING); - } - else if (select instanceof ZipEntry) { - ZipEntry entry = (ZipEntry) select; - - File outputFile = new File(worldFile, entry.toString()); - FileOutputStream outputStream = new FileOutputStream(outputFile); - - info("Restoring " + entry.toString() + "..."); - - byte[] buffer = new byte[1028]; - InputStream inputSteam = entryOwners.get(entry.toString()).getInputStream(entry); - int length; - while ((length = inputSteam.read(buffer, 0, buffer.length)) > 0) { - outputStream.write(buffer, 0, length); - } - outputStream.flush(); - outputStream.close(); - } - - - } - catch (IOException e){ - //TODO : Scream at user - e.printStackTrace(); - } - } - - private static void restorePartialIncremental(int index, File worldFile) { - //Do we need to check for past backups? if selected is a full backup, we do not. - HashMap filePaths = new HashMap<>(); - HashMap dates = new HashMap<>(); - HashMap entryOwners = new HashMap<>(); - try { - File backup = new File(fileNames.get(index)); - if (!backup.getName().contains("-full")) { - int i; - //find last FULL backup - for (i = index;i>=0;i--) { - String name = fileNames.get(i); - if (name.contains("-full")) { - addBackupNamesToLists(new File(name), entryOwners, filePaths, dates, "\u001b[31m"); - break; - } - } - while (i < index) { - String name = fileNames.get(i); - addBackupNamesToLists(new File(name), entryOwners, filePaths, dates, "\u001b[31m"); - i++; - } - - } - - File file = new File(fileNames.get(index)); - addBackupNamesToLists(file, entryOwners, filePaths, dates, "\u001B[32m"); - - HashMap properMapping = new HashMap<>(); - for (String date : dates.keySet()) { - properMapping.put( - date + " " + dates.get(date), - filePaths.get(date) - ); - } - - Object select = getFileToRestore(properMapping, ""); - if (select instanceof Path) { - Path input = (Path) select; - - - if (select.toString().replace("\\", "/").contains("-full/")) { - select = new File( - select.toString().replace("\\", "/") - .split("-full/")[1] - ).toPath(); - } - if (select.toString().replace("\\", "/").contains("-partial/")) { - select = new File( - select.toString().replace("\\", "/") - .split("-partial/")[1] - ).toPath(); - } - - File outputFile = new File(worldFile, select.toString()); - if (!outputFile.getParentFile().exists()) { - outputFile.getParentFile().mkdirs(); - } - info("\n\nRestoring file : " + select); - Files.copy(input, outputFile.toPath(), StandardCopyOption.REPLACE_EXISTING); - } - else if (select instanceof ZipEntry) { - ZipEntry entry = (ZipEntry) select; - - File outputFile = new File(worldFile, entry.toString()); - FileOutputStream outputStream = new FileOutputStream(outputFile); - - info("Restoring " + entry.toString() + "..."); - - byte[] buffer = new byte[1028]; - InputStream inputSteam = entryOwners.get(entry.toString()).getInputStream(entry); - int length; - while ((length = inputSteam.read(buffer, 0, buffer.length)) > 0) { - outputStream.write(buffer, 0, length); - } - outputStream.flush(); - outputStream.close(); - } - - - } - catch (IOException e){ - //TODO : Scream at user - e.printStackTrace(); - } - } - - - private static void restoreFolder(int index, File worldFile) { - File backup = new File(fileNames.get(index)); - - try { - Files.walkFileTree(backup.toPath(), new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) throws IOException { - File source = backup.toPath().relativize(file).toFile(); - File outputFile = new File(worldFile, source.getPath()); - - if (!outputFile.getParentFile().exists()) { - outputFile.getParentFile().mkdirs(); - } - Files.copy(file, outputFile.toPath()); - return FileVisitResult.CONTINUE; - } - }); - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - - - private static void deleteEntireWorld(File worldDir) { - backupExistingWorld(worldDir); - try { - Files.walkFileTree(worldDir.toPath(), new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { - file.toFile().delete(); - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult postVisitDirectory(Path file, java.io.IOException arg1) { - if (file.toFile().listFiles().length == 0) { - file.toFile().delete(); - } - return FileVisitResult.CONTINUE; - } - }); - } catch (IOException e) { - warn("Failed to delete file :"); - e.printStackTrace(); - } - } - - private static void backupExistingWorld(File worldDir) { - try { - File out = new File(worldDir, "../cli" + ThreadedBackup.serialiseBackupName() + ".zip"); - FileOutputStream outputStream = new FileOutputStream(out); - ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream); - zipOutputStream.setLevel(4); - Files.walkFileTree(worldDir.toPath(), new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { - Path targetFile; - try { - targetFile = worldDir.toPath().relativize(file); - if (targetFile.toFile().getName().compareTo("session.lock") == 0) { - return FileVisitResult.CONTINUE; - } - zipOutputStream.putNextEntry(new ZipEntry(targetFile.toString())); - byte[] bytes = Files.readAllBytes(file); - zipOutputStream.write(bytes, 0, bytes.length); - zipOutputStream.closeEntry(); - - } catch (IOException e) { - // TODO : Scream at user - e.printStackTrace(); - } - - return FileVisitResult.CONTINUE; - } - }); - zipOutputStream.flush(); - zipOutputStream.close(); - } catch (Exception e) { - - } - } - - - private static T getFileToRestore(HashMap files, String directory) { - ArrayList toDisplay = new ArrayList<>(); - HashMap keyMap = new HashMap<>(); - int index = 1; - for (String name : files.keySet()) { - String name2 = name.replace("\\", "/"); // this replacement can fix some problems with wsl, and helps keep code neat. - if (name2.contains(directory)) { - name2 = name2.replace(directory, ""); - if (name2.startsWith(worldFile.getName())) { - name2 = name2.replace(worldFile.getName() + "/", ""); - } - if (name2.contains("/")) { - name2 = "\u001B[33mdirectory\u001B[0m " + name2.split("/")[0]; - } - if (!toDisplay.contains(name2)) { - toDisplay.add(name2); - keyMap.put(name2, name); - } - } - } - toDisplay = sortStringsAlphabeticallyWithDirectoryPriority(toDisplay); - info("Choose a file to restore.\n"); - for (String name : toDisplay) { - if (index < 10) { - info(index + ": " + name); - } - else { - info(index + ": " + name); - } - index++; - } - if (!directory.equals("")) { - info(index + ": ../"); - } - - - int userInput; - try { - String line = input.nextLine(); - if (line == "") { - warn("Please enter a number!"); - return getFileToRestore(files, directory); - } - userInput = Integer.parseInt(line); - } catch (InputMismatchException | NumberFormatException e) { - warn("That was not a number. Please enter a number."); - return getFileToRestore(files, directory); - } - - if (userInput <= 0 || userInput > (directory.equals("") ? toDisplay.size() : toDisplay.size() + 1)) { - warn("Please enter a number in the specified range!"); - return getFileToRestore(files, directory); - } - else if (userInput > toDisplay.size()) { - return null; - } - else if (!toDisplay.get(userInput - 1).contains("\u001B[33mdirectory\u001B[0m ")) { - return files.get(keyMap.get(toDisplay.get(userInput -1))); - } - - T result = getFileToRestore(files, directory + toDisplay.get(userInput -1).replace("\u001B[33mdirectory\u001B[0m ", "") + "/"); - if (result != null) { - return result; - } - else { - return getFileToRestore(files, directory); - } - } - - - private static ArrayList sortStringsAlphabeticallyWithDirectoryPriority(ArrayList in) { - ArrayList out = new ArrayList<>(); - Collections.sort(in); - for (String string : in) { - if (string.contains("\u001B[33mdirectory\u001B[0m")) { - out.add(string); - } - } - for (String string : in) { - if (!string.contains("\u001B[33mdirectory\u001B[0m")) { - out.add(string); - } - } - return out; - } - - - private static void addBackupNamesToLists(File file, HashMap entryOwners, HashMap filePaths, - HashMap dates, String colour) throws IOException { - - if (file.isFile()) { - - ZipFile zipFile = new ZipFile(file); - Enumeration entryEnum = zipFile.entries(); - - while (entryEnum.hasMoreElements()) { - ZipEntry entry = entryEnum.nextElement(); - - String backupName = file.toString().replace("\\", "/"); - filePaths.put(entry.toString().replace("\\", "/"), entry); - dates.put(entry.toString().replace("\\", "/"), "\u001b[31m" - + backupName - .substring(backupName.toString().lastIndexOf("/") + 1) - .replace("backup-", "") - .replace("-full.zip", "") - .replace("-partial.zip", "") - + "\u001B[0m"); - entryOwners.put(entry.toString(), zipFile); - } - } - - else { - Files.walkFileTree(file.toPath(), new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path path, BasicFileAttributes attributes) throws IOException { - String backupName = file.toString().replace("\\", "/"); - filePaths.put(file.toPath().relativize(path).toString().replace("\\", "/"), path); - dates.put(file.toPath().relativize(path).toString().replace("\\", "/"), "\u001b[31m" - + backupName - .substring(backupName.toString().lastIndexOf("/") + 1) - .replace("backup-", "") - .replace("-full", "") - .replace("-partial", "") - + "\u001B[0m"); - return FileVisitResult.CONTINUE; - } - }); - } - } - -} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java deleted file mode 100644 index 76e59aef..00000000 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java +++ /dev/null @@ -1,77 +0,0 @@ -package co.uk.mommyheather.advancedbackups.core; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileWriter; -import java.nio.file.Files; -import java.util.function.Consumer; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; - -import co.uk.mommyheather.advancedbackups.core.backups.BackupCheckEnum; -import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; -import co.uk.mommyheather.advancedbackups.core.backups.gson.DifferentialManifest; -import co.uk.mommyheather.advancedbackups.core.config.AVConfig; - -public class CoreCommandSystem { - private static GsonBuilder builder = new GsonBuilder(); - private static Gson gson; - static { - builder.setPrettyPrinting(); - gson = builder.create(); - } - - - //These methods are all called by relevant command classes in version specific code - public static void checkBackups(Consumer chat) { - BackupCheckEnum check = BackupWrapper.checkBackups(); - chat.accept(check.getCheckMessage()); - } - - public static void startBackup(Consumer chat) { - BackupCheckEnum check = BackupWrapper.checkBackups(); - chat.accept(check.getCheckMessage()); - if (check.success()) { - chat.accept("Starting backup..."); - BackupWrapper.makeSingleBackup(0); - } - } - - public static void forceBackup(Consumer chat) { - chat.accept("Forcing a backup..."); - BackupWrapper.makeSingleBackup(0); - } - - public static void reloadConfig(Consumer chat) { - chat.accept("Reloading config..."); - AVConfig.loadConfig(); - chat.accept("Done!"); - } - - public static void resetChainLength(Consumer chat) { - chat.accept("Resetting chain length... The next backup will be a complete backup."); - boolean differential = AVConfig.config.getBackupType().equals("differential") ? true : false; - File manifestFile = differential ? new File(AVConfig.config.getPath() + "/differential/manifest.json") : new File(AVConfig.config.getPath() + "/incremental/manifest.json"); - DifferentialManifest manifest; - try { - if (manifestFile.exists()) { - manifest = gson.fromJson(new String(Files.readAllBytes(manifestFile.toPath())), DifferentialManifest.class); - manifest.setChain(manifest.getChain() + AVConfig.config.getMaxDepth()); - FileWriter writer = new FileWriter(manifestFile); - writer.write(gson.toJson(manifest)); - writer.flush(); - writer.close(); - chat.accept("Done!"); - return; - } - else { - chat.accept("No manifest file exists!"); - return; - } - } catch (Exception e) { - chat.accept("Error resetting chain length. - check logs for more info."); - e.printStackTrace(); - } - } -} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupCheckEnum.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupCheckEnum.java deleted file mode 100644 index 06e00e14..00000000 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupCheckEnum.java +++ /dev/null @@ -1,38 +0,0 @@ -package co.uk.mommyheather.advancedbackups.core.backups; - -public enum BackupCheckEnum { - SUCCESS, - DISABLED, - NOACTIVITY, - TOORECENT; - - public boolean success() { - switch (this) { - case SUCCESS: { - return true; - } - default : return false; - } - } - - - public String getCheckMessage() { - switch(this) { - case SUCCESS : { - return "Checks successful!"; - } - case DISABLED : { - return "Backups are disabled!"; - } - case NOACTIVITY : { - return "Player activity is required, but none have been active!"; - } - case TOORECENT : { - return "The time since the last backup is less than the minimum time specified in config!"; - } - default : { - return "You should not see this message, report a bug!"; - } - } - } -} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java deleted file mode 100644 index c9cb675e..00000000 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java +++ /dev/null @@ -1,74 +0,0 @@ -package co.uk.mommyheather.advancedbackups.core.backups; - -import java.time.LocalDateTime; -import java.util.ArrayList; - -import co.uk.mommyheather.advancedbackups.core.config.AVConfig; - -public class BackupTimingThread extends Thread { - private int loops = 0; - private int index = 0; - private long prev = 0; - - public BackupTimingThread() { - setName("AB Backup Timing Daemon"); - setDaemon(true); - } - - @Override - public void run() { - while (true) { - try { - long time = calculateNextBackupTime(); - sleep(time); - BackupWrapper.checkAndMakeBackups(); - } catch (InterruptedException e) { - // TODO Scream at user - e.printStackTrace(); - break; - } - } - } - - - private long calculateNextBackupTime() { - long forcedMillis = BackupWrapper.mostRecentBackupTime() + (long) (AVConfig.config.getMaxTimer() * 3600000L); - if (forcedMillis == AVConfig.config.getMaxTimer() * 3600000L) forcedMillis = 300000; //sets it to 5m if no backup exists, to get the chain going - else forcedMillis -= System.currentTimeMillis(); - long ret = Long.MAX_VALUE; - if (AVConfig.config.getUptimeSchedule() && !BackupWrapper.configuredPlaytime.isEmpty()) { - ArrayList timings = new ArrayList(BackupWrapper.configuredPlaytime); - if (index >= timings.size()) { - index = 0; - loops++; - } - ret = (timings.get(index) + (timings.get(timings.size() - 1) * loops)); - ret -= prev; - prev += ret; - index++; - } - - else if (!BackupWrapper.configuredPlaytime.isEmpty()) { - long nextTime = 0; - long currentTime = System.currentTimeMillis(); - ArrayList timings = new ArrayList(BackupWrapper.configuredPlaytime); - for (long time : timings) { - if (time >= currentTime) { - nextTime = time; - break; - } - } - ret = nextTime >= currentTime ? nextTime - currentTime : 86640000 - currentTime; - } - - return Math.min(forcedMillis, ret); - - - - - - - } - - -} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java deleted file mode 100644 index f53771a2..00000000 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java +++ /dev/null @@ -1,242 +0,0 @@ -package co.uk.mommyheather.advancedbackups.core.backups; - -import java.io.File; -import java.util.ArrayList; -import java.util.Date; - - -import co.uk.mommyheather.advancedbackups.PlatformMethodWrapper; -import co.uk.mommyheather.advancedbackups.core.config.AVConfig; - -public class BackupWrapper { - - public static ArrayList configuredPlaytime = new ArrayList<>(); - - - public static void checkStartupBackups () { - if (AVConfig.config.getForceOnStartup()) { - checkAndMakeBackups(Math.max(5000, AVConfig.config.getStartupDelay() * 1000)); - } - - new BackupTimingThread().start(); - } - - public static void checkShutdownBackups() { - if (AVConfig.config.getForceOnShutdown()) { - checkAndMakeBackups(); - } - } - - public static void checkAndMakeBackups(long delay) { - BackupCheckEnum e = checkBackups(); - if (e.success()) { - makeSingleBackup(delay); - } - } - - public static void checkAndMakeBackups() { - checkAndMakeBackups(0); - } - - - public static BackupCheckEnum checkBackups() { - prepareBackupDestination(); - if (!AVConfig.config.getEnabled()) return BackupCheckEnum.DISABLED; - if (AVConfig.config.getRequireActivity() && !PlatformMethodWrapper.activity) return BackupCheckEnum.NOACTIVITY; - if (checkMostRecentBackup()) return BackupCheckEnum.TOORECENT; - - return BackupCheckEnum.SUCCESS; - - } - - private static void prepareBackupDestination() { - File file = new File(AVConfig.config.getPath()); - - if (!file.exists()) { - file.mkdirs(); - } - File zipFile = new File(file, "/zips/"); - if (!zipFile.exists()) { - zipFile.mkdirs(); - } - File differential = new File(file, "/differential/"); - if (!differential.exists()) { - differential.mkdirs(); - } - File incremental = new File(file, "/incremental/"); - if (!incremental.exists()) { - incremental.mkdirs(); - } - } - - - public static boolean checkMostRecentBackup() { - // Return true if the time difference between the most recent backup and the backup-to-be - // is less than specified in the config. - - Date date = new Date(); - long configVal = (long) (3600000F * AVConfig.config.getMinTimer()); - return (date.getTime() - mostRecentBackupTime()) < configVal; - } - - - public static long mostRecentBackupTime() { - - File directory = new File(AVConfig.config.getPath()); - - switch(AVConfig.config.getBackupType()) { - case "zip" : { - directory = new File(directory, "/zips/"); - break; - } - case "differential" : { - directory = new File(directory, "/differential/"); - break; - } - case "incremental" : { - directory = new File(directory, "/incremental/"); - break; - } - - } - - File[] files = directory.listFiles(); - long lastModifiedTime = Long.MIN_VALUE; - if (files == null || files.length == 0) return 0L; - for (File file : files) { - if (file.lastModified() > lastModifiedTime && !file.getName().contains("manifest")) { - lastModifiedTime = file.lastModified(); - } - } - return lastModifiedTime; - } - - - public static void makeSingleBackup(long delay) { - - PlatformMethodWrapper.disableSaving(); - if (AVConfig.config.getSave()) { - PlatformMethodWrapper.saveOnce(); - } - - // Make new thread, run backup utility. - ThreadedBackup threadedBackup = new ThreadedBackup(delay); - threadedBackup.start(); - // Don't re-enable saving - leave that down to the backup thread. - - } - - public static void finishBackup() { - File directory = new File(AVConfig.config.getPath()); - ThreadedBackup.running = false; - PlatformMethodWrapper.enableSaving(); - - switch(AVConfig.config.getBackupType()) { - case "zip" : { - directory = new File(directory, "/zips/"); - long date = Long.MIN_VALUE; - while (true) { - if (calculateDirectorySize(directory) < AVConfig.config.getMaxSize() * 1000000000L) return; - File file = getFirstBackupAfterDate(directory, date); - date = file.lastModified(); - file.delete(); - } - } - case "differential" : { - directory = new File(directory, "/differential/"); - long date = Long.MIN_VALUE; - while (true) { - if (calculateDirectorySize(directory) < AVConfig.config.getMaxSize() * 1000000000L) return; - File file = getFirstBackupAfterDate(directory, date); - date = file.lastModified(); - if (file.getName().contains("full")) { - File nextFile = getFirstBackupAfterDate(directory, date); - if (nextFile.getName().contains("partial")) { - nextFile.delete(); - } - else { - file.delete(); - } - } - else { - file.delete(); - } - - } - } - case "incremental" : { - directory = new File(directory, "/incremental/"); - if (!AVConfig.config.getPurgeIncrementals()) return; - long date = Long.MIN_VALUE; - while (true) { - if (calculateDirectorySize(directory) < AVConfig.config.getMaxSize() * 1000000000L) return; - if (calculateChainCount(directory) < 2) return; - PlatformMethodWrapper.errorLogger.accept("Purging incremental backup chain - too much space taken up!"); - File file = getFirstBackupAfterDate(directory, date); - date = file.lastModified(); - if (file.getName().contains("full")) { - file.delete(); - while (true) { - file = getFirstBackupAfterDate(directory, date); - date = file.lastModified(); - if (file.getName().contains("full")) { - file.delete(); - } - else { - break; - } - } - } - else { - file.delete(); - } - - } - } - - } - } - - - public static long calculateDirectorySize(File directory) { - long size = 0; - File[] files = directory.listFiles(); - if (files == null || files.length == 0) return size; - for (File file : files) { - if (file.isFile()) { - size += file.length(); - } - else { - size += calculateDirectorySize(file); - } - } - return size; - } - - public static File getFirstBackupAfterDate(File directory, long date) { - File[] files = directory.listFiles(); - File oldestFile = null; - long currentDate = Long.MAX_VALUE; - if (files == null || files.length == 0) return null; - for (File file : files) { - if (file.lastModified() < currentDate && file.lastModified() > date) { - currentDate = file.lastModified(); - oldestFile = file; - } - } - - return oldestFile; - } - - public static int calculateChainCount(File directory) { - int count = 0; - File[] files = directory.listFiles(); - if (files == null || files.length == 0) return 0; - for (File file : files) { - if (file.getName().contains("full")) { - count++; - } - } - return count; - } -} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java deleted file mode 100644 index 5165f7a7..00000000 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java +++ /dev/null @@ -1,237 +0,0 @@ -package co.uk.mommyheather.advancedbackups.core.backups; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.FileWriter; -import java.io.IOException; -import java.nio.file.FileVisitResult; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.SimpleFileVisitor; -import java.nio.file.attribute.BasicFileAttributes; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Date; -import java.util.zip.ZipEntry; -import java.util.zip.ZipOutputStream; - - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; - -import co.uk.mommyheather.advancedbackups.PlatformMethodWrapper; -import co.uk.mommyheather.advancedbackups.core.backups.gson.DifferentialManifest; -import co.uk.mommyheather.advancedbackups.core.config.AVConfig; - -public class ThreadedBackup extends Thread { - private static GsonBuilder builder = new GsonBuilder(); - private static Gson gson; - private long delay; - private static int count; - private static float partialSize; - private static float completeSize; - public static boolean running = false; - - static { - builder.setPrettyPrinting(); - gson = builder.create(); - } - - public ThreadedBackup(long delay) { - setName("AB Active Backup Thread"); - this.delay = delay; - count = 0; - partialSize = 0F; - completeSize = 0F; - } - - @Override - public void run() { - try { - sleep(delay); - } catch (InterruptedException e) { - return; - } - if (running) { - return; - } - running = true; - - File file = new File(AVConfig.config.getPath()); - - switch(AVConfig.config.getBackupType()) { - case "zip" : { - makeZipBackup(file); - break; - } - case "differential" : { - makeDifferentialOrIncrementalBackup(file, true); - break; - } - case "incremental" : { - makeDifferentialOrIncrementalBackup(file, false); - break; - } - } - - BackupWrapper.finishBackup(); - } - - - private static void makeZipBackup(File file) { - try { - - File zip = new File(file.toString() + "/zips/", serialiseBackupName() + ".zip"); - FileOutputStream outputStream = new FileOutputStream(zip); - ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream); - zipOutputStream.setLevel(AVConfig.config.getCompressionLevel()); - - Files.walkFileTree(PlatformMethodWrapper.worldDir, new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { - Path targetFile; - try { - targetFile = PlatformMethodWrapper.worldDir.relativize(file); - if (targetFile.toFile().getName().compareTo("session.lock") == 0) { - return FileVisitResult.CONTINUE; - } - zipOutputStream.putNextEntry(new ZipEntry(targetFile.toString())); - byte[] bytes = Files.readAllBytes(file); - zipOutputStream.write(bytes, 0, bytes.length); - zipOutputStream.closeEntry(); - - } catch (IOException e) { - // TODO : Scream at user - e.printStackTrace(); - PlatformMethodWrapper.errorLogger.accept(file.toString()); - } - - return FileVisitResult.CONTINUE; - } - }); - zipOutputStream.flush(); - zipOutputStream.close(); - - } catch (IOException e){ - // TODO : Scream at user - e.printStackTrace(); - } - - } - - - private static void makeDifferentialOrIncrementalBackup(File location, boolean differential) { - try { - String name = serialiseBackupName(); - long time = 0; - File manifestFile = differential ? new File(location.toString() + "/differential/manifest.json") : new File(location.toString() + "/incremental/manifest.json"); - DifferentialManifest manifest; - if (manifestFile.exists()) { - manifest = gson.fromJson(new String(Files.readAllBytes(manifestFile.toPath())), DifferentialManifest.class); - } - else { - manifest = DifferentialManifest.defaultValues(); - } - - long comp = differential ? manifest.getLastFull() : manifest.getLastPartial(); - ArrayList toBackup = new ArrayList<>(); - ArrayList completeBackup = new ArrayList<>(); - - - boolean completeTemp = manifest.getComplete().size() == 0 || manifest.getChain() >= AVConfig.config.getMaxDepth() ? true : false; - - Files.walkFileTree(PlatformMethodWrapper.worldDir, new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { - Path targetFile; - targetFile = PlatformMethodWrapper.worldDir.relativize(file); - if (targetFile.toFile().getName().compareTo("session.lock") == 0) { - return FileVisitResult.CONTINUE; - } - count++; - completeSize += attributes.size(); - completeBackup.add(targetFile); - if (completeTemp || attributes.lastModifiedTime().toMillis() >= comp) { - toBackup.add(targetFile); - partialSize += attributes.size(); - } - return FileVisitResult.CONTINUE; - } - }); - boolean complete = completeTemp; - if (toBackup.size() >= count) { - complete = true; - } - if ((partialSize / completeSize) * 100F > AVConfig.config.getMaxSizePercent()) { - complete = true; - toBackup.clear(); - toBackup.addAll(completeBackup); - } - - name += complete? "-full":"-partial"; - - - - if (AVConfig.config.getCompressChains()) { - File zip = differential ? new File(location.toString() + "/differential/", name +".zip") : new File(location.toString() + "/incremental/", name +".zip"); - FileOutputStream outputStream = new FileOutputStream(zip); - ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream); - zipOutputStream.setLevel(AVConfig.config.getCompressionLevel()); - - for (Path path : toBackup) { - zipOutputStream.putNextEntry(new ZipEntry(path.toString())); - byte[] bytes = Files.readAllBytes(new File(PlatformMethodWrapper.worldDir.toString(), path.toString()).toPath()); - zipOutputStream.write(bytes, 0, bytes.length); - zipOutputStream.closeEntry(); - } - zipOutputStream.flush(); - zipOutputStream.close(); - - time = zip.lastModified(); - } - else { - File dest = differential ? new File(location.toString() + "/differential/", name + "/") :new File(location.toString() + "/incremental/", name + "/"); - dest.mkdirs(); - for (Path path : toBackup) { - File out = new File(dest, path.toString()); - if (!out.getParentFile().exists()) { - out.getParentFile().mkdirs(); - } - Files.copy(new File(PlatformMethodWrapper.worldDir.toString(), path.toString()).toPath(), out.toPath()); - } - time = dest.lastModified(); - } - - //Finally, update + write the manifest - if (complete || toBackup.size() >= count) { - manifest.setChain(0); - manifest.getComplete().add(time); - manifest.setLastFull(time); - } - else { - manifest.setChain(manifest.getChain() + 1); - manifest.getPartial().add(new Date().getTime()); - manifest.setLastPartial(new Date().getTime()); - } - - FileWriter writer = new FileWriter(manifestFile); - writer.write(gson.toJson(manifest)); - writer.flush(); - writer.close(); - - } catch (IOException e) { - // TODO Scream at user - e.printStackTrace(); - } - - - } - - - public static String serialiseBackupName() { - Date date = new Date(); - String pattern = "yyyy-MM-dd hh-mm-ss"; - - return "backup-" + new SimpleDateFormat(pattern).format(date); - } -} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/gson/DifferentialManifest.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/gson/DifferentialManifest.java deleted file mode 100644 index ca1385cc..00000000 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/gson/DifferentialManifest.java +++ /dev/null @@ -1,73 +0,0 @@ -package co.uk.mommyheather.advancedbackups.core.backups.gson; - -import java.util.ArrayList; -import java.util.List; - -public class DifferentialManifest { - private List complete; - private List partial; - private int chain; - private long lastFull; - private long lastPartial; - - - public List getComplete() { - return complete; - } - - - public void setComplete(List complete) { - this.complete = complete; - } - - - public List getPartial() { - return partial; - } - - - public void setPartial(List partial) { - this.partial = partial; - } - - - public int getChain() { - return chain; - } - - - public void setChain(int chain) { - this.chain = chain; - } - - - public long getLastFull() { - return lastFull; - } - - - public void setLastFull(long lastFull) { - this.lastFull = lastFull; - } - - - public long getLastPartial() { - return Math.max(lastFull, lastPartial); - } - - - public void setLastPartial(long lastPartial) { - this.lastPartial = lastPartial; - } - - - public static DifferentialManifest defaultValues() { - DifferentialManifest manifest = new DifferentialManifest(); - manifest.complete = new ArrayList<>(); - manifest.partial = new ArrayList<>(); - manifest.chain = 0; - manifest.lastFull = 0; - manifest.lastPartial = 0; - return manifest; - } -} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java deleted file mode 100644 index b56eed0c..00000000 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java +++ /dev/null @@ -1,165 +0,0 @@ -package co.uk.mommyheather.advancedbackups.core.config; - -import java.io.File; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Properties; - -import co.uk.mommyheather.advancedbackups.PlatformMethodWrapper; -import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; - -public class AVConfig { - - private static final String[] supportedProps = { - "config.advancedbackups.enabled", - "config.advancedbackups.save", - "config.advancedbackups.activity", - "config.advancedbackups.type", - "config.advancedbackups.path", - "config.advancedbackups.size", - "config.advancedbackups.frequency.min", - "config.advancedbackups.frequency.max", - "config.advancedbackups.frequency.uptime", - "config.advancedbackups.frequency.schedule", - "config.advancedbackups.frequency.shutdown", - "config.advancedbackups.frequency.startup", - "config.advancedbackups.frequency.delay", - "config.advancedbackups.logging.silent", - - "config.advancedbackups.zips.compression", - - "config.advancedbackups.chains.length", - "config.advancedbackups.chains.compress", - "config.advancedbackups.chains.smart", - "config.advancedbackups.chains.maxpercent", - - "config.advancedbackups.purge.incrementals" - - }; - - public static ConfigData config; - - public static void loadOrCreateConfig() { - // Called when the config needs to be loaded, but one may not exist. - // Creates a new config it one doesn't exist, then loads it. - File file = new File("./AdvancedBackups.properties"); - if (!file.exists()) { - initConfig(); - } - loadConfig(); - } - - public static void initConfig() { - // Called when no config file is present. - // Create a complete properties file in the cwd - File file = new File("./AdvancedBackups.properties"); - try { - if (!file.exists()) { - file.createNewFile(); - file.setWritable(true); - } - FileWriter writer = new FileWriter(file); - writer.write(ConfigData.defaults()); - writer.close(); - } catch (IOException e) { - // TODO : Scream to user - e.printStackTrace(); - } - - - } - - public static void loadConfig() { - // Called when the config needs to be loaded. - // Populates all values of ConfigData.class - - Properties props = new Properties(); - File file = new File("./AdvancedBackups.properties"); - FileReader reader; - try { - reader = new FileReader(file); - props.load(reader); - } catch (IOException e) { - // TODO : Scream to user - e.printStackTrace(); - } - - config = new ConfigData(); - - config.setEnabled(props.getProperty("config.advancedbackups.enabled", "true")); - config.setSave(props.getProperty("config.advancedbackups.save", "false")); - config.setRequireActivity(props.getProperty("config.advancedbackups.activity", "false")); - config.setBackupType(props.getProperty("config.advancedbackups.type", "differential")); - config.setPath(props.getProperty("config.advancedbackups.path", "./backups")); - config.setMaxSize(props.getProperty("config.advancedbackups.size", "50")); - config.setMinTimer(props.getProperty("config.advancedbackups.frequency.min", "0.5")); - config.setMaxTimer(props.getProperty("config.advancedbackups.frequency.max", "24")); - config.setUptimeSchedule(props.getProperty("config.advancedbackups.frequency.uptime", "true")); - config.setSchedule(props.getProperty("config.advancedbackups.frequency.schedule", "12:00")); - config.setForceOnShutdown(props.getProperty("config.advancedbackups.frequency.shutdown", "false")); - config.setForceOnStartup(props.getProperty("config.advancedbackups.frequency.startup", "false")); - config.setStartupDelay(props.getProperty("config.advancedbackups.frequency.delay", "5")); - config.setSilent(props.getProperty("config.advancedbackups.logging.silent", "false")); - - config.setCompressionLevel(props.getProperty("config.advancedbackups.zips.compression", "5")); - - config.setMaxDepth(props.getProperty("config.advancedbackups.chains.length", "50")); - config.setCompressChains(props.getProperty("config.advancedbackups.chains.compress", "true")); - config.setSmartChains(props.getProperty("config.advancedbackups.chains.smart", "true")); - config.setMaxSizePercent(props.getProperty("config.advancedbackups.chains.maxpercent", "75")); - - config.setPurgeIncrementals(props.getProperty("config.advancedbackups.purge.incrementals", "false")); - - - - String timingsString = config.getSchedule(); - if (timingsString.length() != 0) { - BackupWrapper.configuredPlaytime = new ArrayList<>(); - for (String time : timingsString.split(",")) { - String[] hm = time.split(":"); - long hours = Long.parseLong(hm[0]) * 3600000L; - long mins = Long.parseLong(hm[1]) * 60000; - BackupWrapper.configuredPlaytime.add(hours + mins); - } - } - - boolean flag = false; - - for (String prop : supportedProps) { - if (!props.containsKey(prop)) { - flag = true; - break; - } - } - - if (flag) { - PlatformMethodWrapper.warningLogger.accept("Broken, incomplete or misising config found! Generating new file whilst preserving any existing config values..."); - - File newPropsFile = new File("./AdvancedBackups.properties"); - try { - if (!newPropsFile.exists()) { - newPropsFile.createNewFile(); - } - FileWriter writer = new FileWriter(newPropsFile); - writer.write(ConfigData.config(config.getEnabled(), config.getSave(), - config.getRequireActivity(), config.getBackupType(), config.getPath(), - config.getMaxSize(), config.getMinTimer(), config.getMaxTimer(), - config.getUptimeSchedule(), config.getSchedule(), config.getForceOnShutdown(), - config.getForceOnStartup(), config.getStartupDelay(), config.getSilent(), - config.getCompressionLevel(), config.getMaxDepth(), config.getCompressChains(), - config.getSmartChains(), config.getMaxSizePercent(), config.getPurgeIncrementals() - )); - writer.close(); - } catch (IOException e) { - // TODO : Scream to user - e.printStackTrace(); - - } - loadConfig(); - } - - } - -} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java deleted file mode 100644 index ecf162c9..00000000 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java +++ /dev/null @@ -1,378 +0,0 @@ -package co.uk.mommyheather.advancedbackups.core.config; - -public class ConfigData { - - private Boolean enabled; - //Allows outright disabling of backups. - //OPTIONS = "TRUE", "FALSE" - - private Boolean save; - //Whether to save before a backup. - //OPTIONS = "TRUE", "FALSE" - - private Boolean requireActivity; - //Whether to require player activity between backups. - //OPTIONS = "TRUE", "FALSE" - - private String backupType; - //The type of backup to make. Each has a separate file structure, but only the currently selected backup type is scanned for. - //OPTIONS = "ZIP", "DIFFERENTIAL", "INCREMENTAL" - - private long maxSize; - //Maximum size of backups. With zips, deletes the absolute oldest file if size is exceeded after making a backup, and repeats until below max size. - //RANGE = 5GB - 9999GB - - private float minTimer; - //Ensure this amount of time is waited between backups, in hours. - //RANGE = 0.5 - 500 - - private float maxTimer; - //Triggers a backup if none has already happened within this time. Can be combined with an uptime-based schedule. - //RANGE = 0.5 - 500 - - private boolean uptimeSchedule; - //Whether the schedule is based off of server uptime (true) or world-time (false). - - private String schedule; - //A comma seperated schedule. About it. - - private String path; - //The path for backups. Defaults to ./backups. Can be absolute or relative. - //ANY STRING IS TESTED, WILL CREATE DIRECTORIES IF MISSING - - private Boolean silent; - //Whether to supress all information. Does not affect debug.log. - // TRUE OR FALSE - - private Boolean forceOnShutdown; - //Whether to build a backup when the server shuts down. - // TRUE OR FALSE - - private Boolean forceOnStartup; - //Whether to build a backup when the server starts up. - // TRUE OR FALSE - - //Startup backup delay, in seconds. - private long startupDelay; - - - //BELOW ONLY APPLIES TO ZIP FILES! (affects export command) - private int compressionLevel; - //The compression level to be passed to zip streams. - // RANGE = 1 - 9 - - - //BELOW ONLY APPLIES TO INCREMENTAL AND DIFFERENTIAL BACKUPS! - private int maxDepth; - //The maximum "depth" of partial backups to create before creating a full backup. Higher numbers are reccomended if using incremental. Lower numbers increase storage usage but reduce restoration times. - // RANGE = 5 - 500 - - private boolean compressChains; - //Whether to compress chains. Useful for size reduction and manual restoration. - // TRUE OR FALSE - - private boolean smartChains; - // Smart chain resetting. - // TRUE OR FALSE - - private int maxSizePercent; - // Resets chain length if what gets backed up is over the defined % size. - // 1-100 range. - - private boolean purgeIncrementals; - // Whether to purge incremental backups if over the limit. - // TRUE OR FALSE - - public Boolean getEnabled() { - return enabled; - } - - public void setEnabled(String enabled) { - this.enabled = Boolean.parseBoolean(enabled); - } - - public Boolean getSave() { - return save; - } - - public void setSave(String save) { - this.save = Boolean.parseBoolean(save); - } - - public Boolean getRequireActivity() { - return requireActivity; - } - - public void setRequireActivity(String requireActivity) { - this.requireActivity = Boolean.parseBoolean(requireActivity); - } - - public String getBackupType() { - return backupType; - } - - public void setBackupType(String backupType) { - this.backupType = backupType; - } - - public long getMaxSize() { - return maxSize; - } - - public void setMaxSize(String maxSize) { - this.maxSize = Long.parseLong(maxSize); - } - - public float getMinTimer() { - return minTimer; - } - - public void setMinTimer(String minTimer) { - this.minTimer = Float.parseFloat(minTimer); - } - - - public float getMaxTimer() { - return maxTimer; - } - - public void setUptimeSchedule(String uptimeSchedule) { - this.uptimeSchedule = Boolean.parseBoolean(uptimeSchedule); - } - - public boolean getUptimeSchedule() { - return uptimeSchedule; - } - - public void setSchedule(String schedule) { - this.schedule = schedule; - } - - public String getSchedule() { - return schedule; - } - - public void setMaxTimer(String maxTimer) { - this.maxTimer = Float.parseFloat(maxTimer); - } - - public String getPath() { - return path; - } - - public void setPath(String path) { - this.path = path; - } - - public Boolean getSilent() { - return silent; - } - - public void setSilent(String silent) { - this.silent = Boolean.parseBoolean(silent); - } - - public Boolean getForceOnShutdown() { - return forceOnShutdown; - } - - public void setForceOnShutdown(String forceOnShutdown) { - this.forceOnShutdown = Boolean.parseBoolean(forceOnShutdown); - } - - public Boolean getForceOnStartup() { - return forceOnStartup; - } - - public void setForceOnStartup(String forceOnStartup) { - this.forceOnStartup = Boolean.parseBoolean(forceOnStartup); - } - - public void setStartupDelay(String delay) { - this.startupDelay = Long.parseLong(delay); - } - - public long getStartupDelay() { - return startupDelay; - } - - public int getCompressionLevel() { - return compressionLevel; - } - - public void setCompressionLevel(String compressionLevel) { - this.compressionLevel = Integer.parseInt(compressionLevel); - } - - public int getMaxDepth() { - return maxDepth; - } - - public void setMaxDepth(String maxDepth) { - this.maxDepth = Integer.parseInt(maxDepth); - } - - public boolean getCompressChains() { - return compressChains; - } - - public void setCompressChains(String compressChains) { - this.compressChains = Boolean.parseBoolean(compressChains); - } - - public boolean getSmartChains() { - return smartChains; - } - - public void setSmartChains(String smartChains) { - this.smartChains = Boolean.parseBoolean(smartChains); - } - - - public boolean getPurgeIncrementals() { - return purgeIncrementals; - } - - public void setPurgeIncrementals(String purgeIncrementals) { - this.purgeIncrementals = Boolean.parseBoolean(purgeIncrementals); - } - - public int getMaxSizePercent() { - return maxSizePercent; - } - - public void setMaxSizePercent(String maxSizePercent) { - this.maxSizePercent = Integer.parseInt(maxSizePercent); - } - - - - - //default config output - can be ignored - public static String config(Object enabled, Object save, - Object activity, Object type, Object location, - Object size, Object min, Object max, - Object uptime, Object schedule, Object shutdown, - Object startup, Object delay, Object silent, - Object compression, Object chainLength, Object compressChains, - Object smartChains, Object maxPercent, Object purgeIncrementals) { - return String.join("\n", - -"#Enable or disable automatic backups.", -"#Options : true, false #Default : true,", -"config.advancedbackups.enabled=" + enabled, -"", -"#Whether to save before making a backup.", -"#Options : true, false #Default : false", -"config.advancedbackups.save=" + save, -"", -"#Whether to require player activity between backups.", -"#Options : true, false #Default : false", -"config.advancedbackups.activity=" + activity, -"", -"#The type of backups to use.", -"#Options : zip, differential, incremental #Default : differential", -"config.advancedbackups.type=" + type, -"", -"#The absolute or relative path to the backup location.", -"#Options : any file path. Default : ./backups", -"config.advancedbackups.path=" + location, -"", -"#The maximum size to keep, in GB. Keep relatively high for zips, tighter space requirements should instead use differential or incremental backups.", -"#Range : 5 - 9999 #Default : 50", -"config.advancedbackups.size=" + size, -"", -"#Minimum time between backups, in hours. This can prevent a shutdown backup from triggering immediately after a scheduled backup or similar situations.", -"#Range : 0.5 - 500 #Default : 0.5", -"config.advancedbackups.frequency.min=" + min, -"", -"#Triggers a backup if none has already happened within this time. Can be combined with an uptime-based schedule.", -"#Range : 0.5 - 500 #Default : 24", -"config.advancedbackups.frequency.max=" + max, -"", -"#Whether the schedule below uses uptime (true) or real-world time (false).", -"#Default : true", -"config.advancedbackups.frequency.uptime=" + uptime, -"", -"#When using server uptime:", -" #A looping comma-separated backup schedule, based off of server uptime, hours:minutes. Examples:", -" #4:00 - Makes a backup every four hours.", -" #4:00,7:00 - Makes a backup after four hours, then three, then four, and so on.", -" #1:00 - Makes a backup every hour.", -" #4:00,8:00,12:00,16:00,17:00,18:00,19:00,20:00,21:00,24:00 - Makes a backup following a strict schedule.", -"", -"#When using real-world time:", -" #A strict schedule, using hours:minutes to follow real-world time. Examples:", -" #4:00 - Makes a backup at 4am each day.", -" #4:00,8:00,12:00,16:00,17:00,18:00,19:00,20:00,21:00,24:00 - Makes a backup at specific times of day.", -"", -"#Default : 12:00", -"config.advancedbackups.frequency.schedule=" + schedule, -"", -"#Whether to force a backup on server shutdown. Respects min frequency.", -"#Options : true, false #Default : false", -"config.advancedbackups.frequency.shutdown=" + shutdown, -"", -"#Whether to force a backup on server startup. Respects min frequency.", -"#Options : true, false #Default : false", -"config.advancedbackups.frequency.startup=" + startup, -"", -"#Delay to use after startup, in seconds. Is always at least 5 seconds.", -"#Range : 5-9999999999", -"config.advancedbackups.frequency.delay=" + delay, -"", -"#Whether to disable console and chat logging. Does not affect debug.log, does not affect error messages.", -"#Options : true, false #Default : false", -"config.advancedbackups.logging.silent=" + silent, -"", -"", -"", -"#--------------------------------------------------------------------------------------------------------------------", -"##The following options only affect zip files, whether that's for zip backups, export commands or some other option.", -"#--------------------------------------------------------------------------------------------------------------------", -"", -"#The compression level to use for zip files. Higher numbers space usage, but decrease performance.", -"#Range : 1-9 #Default : 4", -"config.advancedbackups.zips.compression=" + compression, -"", -"", -"", -"#--------------------------------------------------------------------------------------------------------------------", -"##The following options only affect differential and incremental backups.", -"#--------------------------------------------------------------------------------------------------------------------", -"", -"#The maximum 'chain' length to keep.", -"#Range : 5-500 #Default : 50", -"config.advancedbackups.chains.length=" + chainLength, -"", -"#Whether to compress 'chains'. This compresses the base backup and all sequential backups. Reduces space usage, but decreases performance.", -"#Options : true, false #Default : true", -"config.advancedbackups.chains.compress=" + compressChains, -"", -"#Whether to enable \"smart\" reset for chains - if every file is being backed up, mark the backup as complete and reset chain length regardless of intended backup type.", -"#Options : true, false #Default : true", -"config.advancedbackups.chains.smart=" + smartChains, -"", -"#What % of a full backup is allowed to be contained in a partial before forcing it into a full backup. Useful for reducing partial backup size.", -"config.advancedbackups.chains.maxpercent=" + maxPercent, -"", -"#Whether to delete incremental backup chains if max size is exceeded. If not, incremental backups do not respect the max size config and never delete.", -"#Options : true, false #Default : false", -"config.advancedbackups.purge.incrementals=" + purgeIncrementals - - - ); - } - - public static String defaults() { - return config( - "true", "false", "false", - "differential", "./backups", "50", - "0.5", "24", "true", - "12:00", "false", "false", - "5", "false", "4", - "50", "true", "true", - "75","false"); - - } -} From 542affcb89252a8ecf23994c20315b9710b204f4 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Wed, 30 Aug 2023 20:49:51 +0100 Subject: [PATCH 220/580] update readme --- README.md | 179 +----------------------------------------------------- 1 file changed, 3 insertions(+), 176 deletions(-) diff --git a/README.md b/README.md index 8fe67530..11effd38 100644 --- a/README.md +++ b/README.md @@ -1,177 +1,4 @@ -# Advanced Backups +# Forge - 1.19 - -A powerful backup mod for Minecraft, supporting Forge and Fabric. -Many Minecraft versions are supported - request more if the one you want isn't yet supported. - -[Supported Versions](#current-versions) - -[Features](#features) - -[Ingame Usage](#ingame) - -[Command Line Usage](#commandline) - -[Future Plans](#future-plans) - -## Current Versions: -- Forge 1.18 -- Fabric 1.18 -- Forge 1.16 -- Forge 1.12 -- Forge 1.7.10 - -## Features: -- Choose between zip, differential or incremental backups. -- Set a schedule to backup as and when you want. -- Optionally force a minimum time between backups to avoid doing so too frequently. -- Backup on server startup and / or shutdown, or neither. -- Set a cap to max backup sizes. -- Save anywhere on disk, including network locations. -- Customisable compression level. -- Commandline restoration tool built into the jar. - - -## Usage: - -### Ingame: -\- Upon first boot, an `AdvancedBackups.properties` file will be created in your server or client root directory. - -\- Adjust this to suit your needs, then restart the server or use `/advancedbackups reload` to reload the config. A small description of each config entry is below. - -| Config | Description | Default Value | Supported From | -| ----------- | ----------- | ------------- | -------------- | -| config.advancedbackups.enabled | Enable or disable backups entirely. | true | 0.3 | -| config.advancedbackups.activity | Enable or disable player activity requirements. | false | 1.0 | -| config.advancedbackups.save | Whether to save before making a backup. | false | 0.3 | -| config.advancedbackups.type | Whether to use zip, differential or incremental backups. | differential | 0.3 | -| config.advancedbackups.path | The relative or absolute location where backups are stored. | ./backups | 0.3 | -| config.advancedbackups.size | The maximum backup size to keep, in GB. Oldest backups are deleted if this is exceeded. | 50 | 0.3 | -| config.advancedbackups.frequency.min | The minimum time between backups. Command backups bypass this. | 0.5 | 0.3 | -| config.advancedbackups.frequency.max | If this time has passed since a backup was last made, one **will** be made. | 24 | 0.3 | -| config.advancedbackups.frequency.uptime| Whether the schedule is based on uptime. If not. it uses real-time instead. | true | 0.3 | -| config.advancedbackups.frequency.schedule | Uptime based : a looping uptime-based schedule. Real-time based : A strict schedule, following real-world time. | 12:00 | 0.3 | -| config.advancedbackups.frequency.shutdown | Whether to make a backup on server shutdown. | false | 0.3 | -| config.advancedbackups.frequency.startup | Whether to make a backup on server startup. | false | 0.3 | -| config.advancedbackups.frequency.delay | The delay in seconds before making a startup backup. Always at least 5 seconds. | 5 | 0.3 | -| config.advancedbackups.logging.silent | Whether to disable chat and console logging. Does not affect debug.log or error messages. | false | N/A | -| config.advancedbackups.zips.compression | The attempted compression level for all zip files. | 4 | 0.3 | -| config.advancedbackups.chains.length | The maximum chain length for incremental and differential backups. | 50 | 0.3 | -| config.advancedbackups.chains.compress | Whether to compress incremental and differential backups into zip files. | true | 0.3 | -| config.advancedbackups.chains.smart | For differential and incremental backups. Resets the chain length if every file is being backed up. | true | 0.3 | -| config.advancedbackups.purge.incremental | For incremental backups only. Enable to allow purging incremental backup chains if the defined storage usage is limit exceeded. | false | 1.0 | - -#### Commands: - -\- All entries in the table below must be prefixed with `/advancedbackups`. - -- Example : `/advancedbackups force-backup` - - -| Command | Description | Supported From | -| ----------- | ----------- | -------------- | -| check | Checks if a backup would be made at this point in time, and tells you the result. Does not make a backup.| 1.0 | -| start | Starts a backup if all checks pass. Tells you check results.| 1.0 | -| reload | Reloads the config.| 1.0 | -| force-backup | Forces a backup without running any checks.| 1.0 | -| reset-chain | Resets any current chain length.| 1.0 | - - -### Commandline: -TODO - export option for backups. - -\- Run the jar directly from the mods folder. `java -jar AdvancedBackups-modloader-mcversion-modversion` for example, replacing the filename with the correct one for your installation. - -\- It will read your config. Then, it will ask you which backup type to restore. - -\- Afterwards, it will ask you if you are on a client or server. If you run the forge/fabric server software, choose server, otherwise it's a client. - -\- Then it will ask for your world name. It will verify this, and will not proceed if it can't find the name. - -\- Then it will prompt you to choose a backup to restore. The most recent are listed last. With differential and incremental upgrades, the backups will be labelled as partial or fill. - -- This is only for your information, and will not affect the restoration process. - -\- The below image shows this for a differential backup. - - -![image](https://github.com/MommyHeather/AdvancedBackups/assets/66441550/ba73af5f-1bca-4ec7-9a3e-a21f6b7350ab) - -\- Next you choose whether you're restoring the entire backup, or a singular file. - -- This restores the **ENTIRE WORLD STATE** at the time of the backups. Partial backups will have the relevant previous backups also restored to make this happen. - - -Finally, you can accept the warning prompt it gives you. - -If you chose to restore the entire backup, the program will exit when it is complete. -If you chose to restore a singular file, you'll be presented with a rudimentary file browser. The below example is for differential backups: - -![image](https://github.com/MommyHeather/AdvancedBackups/assets/66441550/d5f771f5-32d4-435f-aa82-a1da52e3996c) - -Directories are marked, and `../` will traverse up a directory. - -If your selected backup type is differential or incremental, files will be marked with the date they're from. This is purely for your information, the file's state will match that of when the selected backup was made. - -Once you select a file, it will be restored. The program will then exit. - -![image](https://github.com/MommyHeather/AdvancedBackups/assets/66441550/7a2c5d4c-e8db-48c3-8353-46486b9f86b3) - - - -# Future Plans: -- Note : these are in no particular order. -- [Profiles](#profiles) -- [More Commands](#more-commands) -- [Client Feedback](#client-feedback) -- [Commandline Improvements](#commandline-improvements) - -## Profiles - -- Profiles plan to allow one server to have several backup configs active at once. -- Say, take an incremental backup every day, but make sure a zip backup is made at least once a week. -- Or maybe, you want to save a differential backup every hour on a remote drive, but keep a full-world zip backup ready locally every 24 hours. - -### Profiles can do this! - -Essentially, profiles will be an optional set of additional configs. - -These are completely separate - meaning they will not interfere with one another, at all. -- Certain values, such as min and max, may have problems if two profiles use the same location and backup type. I am not sure if I will fix this yet. - -The profile system will not be compatible with versions that predate its release. -- Backups themselves will be unaffected, and any version will be able to restore them. -- The backup location detection however may not work if your restoration cli predates the profile release. - -Upon first load with a version updated to use profiles, a default profile will be made. -- If you have a config present from an older version, the changes you made will be automatically applied to the default profile for you. -- *This means that a user who does not wish to use profiles will not be affected whatsoever. They can edit the default profile as they would with a standard config.* - - -## More commands - -Shortly after release, I wish to add more commands. - -- Config editing on the fly -- One-off backup types - - Currently, the `start` and `force-backup` commands only allow you to make a backup of the type specified in config. This will change. - - -## Client feedback - -Having some client feedback would allow connected clients that have the mod view backup progress. -- This should be toggleable in config. -- A config option to only show progress to ops should exist. - -This might be in the form of either a progress bar, or a simple percentage. - -Clients with the mod should have a way to opt out of this. - - -## Commandline improvements - -Export feature : -- When asked whether restoring a singular file or the whole world, a third option will be present : export. -- This will package the backup into a singular zip file (...so yeah, just copy over the backup in the case of zip backups). -- It will leave the actual world intact. - +This is the branch specifically for forge 1.19. +Any differences will be listed below. For full documentation, see the `core` branch. \ No newline at end of file From 0f682361ef5446b1161bf2504bd782ed1219990c Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Thu, 31 Aug 2023 02:02:00 +0100 Subject: [PATCH 221/580] Update to new core system --- build.gradle | 5 +- gradle.properties | 2 +- .../advancedbackups/AdvancedBackups.java | 69 +- .../AdvancedBackupsCommand.java | 2 +- .../PlatformMethodWrapper.java | 66 -- .../cli/AdvancedBackupsCLI.java | 954 ------------------ .../core/CoreCommandSystem.java | 77 -- .../core/backups/BackupCheckEnum.java | 38 - .../core/backups/BackupTimingThread.java | 74 -- .../core/backups/BackupWrapper.java | 273 ----- .../core/backups/ThreadedBackup.java | 240 ----- .../backups/gson/DifferentialManifest.java | 73 -- .../advancedbackups/core/config/AVConfig.java | 165 --- .../core/config/ConfigData.java | 378 ------- .../assets/advanced-backups/icon.png | Bin 453 -> 0 bytes 15 files changed, 69 insertions(+), 2347 deletions(-) delete mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/PlatformMethodWrapper.java delete mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java delete mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java delete mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupCheckEnum.java delete mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java delete mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java delete mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java delete mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/core/backups/gson/DifferentialManifest.java delete mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java delete mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java delete mode 100644 src/main/resources/assets/advanced-backups/icon.png diff --git a/build.gradle b/build.gradle index 9230c446..5507b3ba 100644 --- a/build.gradle +++ b/build.gradle @@ -36,8 +36,9 @@ dependencies { // modImplementation "net.fabricmc.fabric-api:fabric-api-deprecated:${project.fabric_version}" - implementation files('dependencies/jansi-2.4.0.jar') - extraLibs files('dependencies/jansi-2.4.0.jar') + implementation files ('../advancedbackups-corelib.jar') + extraLibs files ('../advancedbackups-corelib.jar') + } processResources { diff --git a/gradle.properties b/gradle.properties index d559170a..9e098e85 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,7 @@ yarn_mappings=1.18.2+build.4 loader_version=0.14.19 # Mod Properties -mod_version=1.0 +mod_version=2.0 maven_group=co.uk.mommyheather.advancedbackups archives_base_name=advanced-backups modloaderName =fabric diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 917c178f..8bba8190 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -5,6 +5,7 @@ import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; import net.minecraft.server.MinecraftServer; +import net.minecraft.server.world.ServerWorld; import net.minecraft.util.WorldSavePath; import java.util.function.Consumer; @@ -12,8 +13,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import co.uk.mommyheather.advancedbackups.core.ABCore; import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; -import co.uk.mommyheather.advancedbackups.core.config.AVConfig; +import co.uk.mommyheather.advancedbackups.core.config.ABConfig; public class AdvancedBackups implements ModInitializer { // This logger is used to write text to the console and the log file. @@ -32,10 +34,18 @@ public class AdvancedBackups implements ModInitializer { public void onInitialize() { ServerLifecycleEvents.SERVER_STARTING.register((server) -> { AdvancedBackups.server = server; - AVConfig.loadOrCreateConfig(); + ABConfig.loadOrCreateConfig(); LOGGER.info("Config loaded!!"); - PlatformMethodWrapper.worldName = server.getSaveProperties().getLevelName(); - PlatformMethodWrapper.worldDir = server.getSavePath(WorldSavePath.ROOT); + ABCore.worldName = server.getSaveProperties().getLevelName(); + ABCore.worldDir = server.getSavePath(WorldSavePath.ROOT); + + ABCore.disableSaving = AdvancedBackups::disableSaving; + ABCore.enableSaving = AdvancedBackups::enableSaving; + ABCore.saveOnce = AdvancedBackups::saveOnce; + + ABCore.infoLogger = infoLogger; + ABCore.warningLogger = warningLogger; + ABCore.errorLogger = errorLogger; }); ServerLifecycleEvents.SERVER_STARTED.register((server) -> { @@ -46,7 +56,7 @@ public void onInitialize() { }); ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> { - PlatformMethodWrapper.activity = true; + ABCore.setActivity(); }); CommandRegistrationCallback.EVENT.register((dispatcher, isDedicated) -> { @@ -54,4 +64,53 @@ public void onInitialize() { }); } + + public static final String savesDisabledMessage = """ + + + *************************************** + SAVING DISABLED - PREPARING FOR BACKUP! + *************************************** + """; + public static final String savesEnabledMessage = """ + + + ********************************* + SAVING ENABLED - BACKUP COMPLETE! + ********************************* + """; + public static final String saveCompleteMessage = """ + + + ************************************* + SAVE COMPLETE - PREPARING FOR BACKUP! + ************************************* + """; + + + public static void disableSaving() { + MinecraftServer server = AdvancedBackups.server; + for (ServerWorld level : server.getWorlds()) { + if (level != null && !level.savingDisabled) { + level.savingDisabled = true; + } + } + warningLogger.accept(savesDisabledMessage); + } + + public static void enableSaving() { + MinecraftServer server = AdvancedBackups.server; + for (ServerWorld level : server.getWorlds()) { + if (level != null && !level.savingDisabled) { + level.savingDisabled = false; + } + } + warningLogger.accept(savesEnabledMessage); + } + + public static void saveOnce() { + MinecraftServer server = AdvancedBackups.server; + server.saveAll(true, true, true); + warningLogger.accept(saveCompleteMessage); + } } \ No newline at end of file diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index 52e552bf..1b171a51 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -40,7 +40,7 @@ public static void register(CommandDispatcher stack) { })) .then(CommandManager.literal("reset-chain").executes((runner) -> { - CoreCommandSystem.reloadConfig((response) -> { + CoreCommandSystem.resetChainLength((response) -> { runner.getSource().sendFeedback(Text.of(response), true); }); return 1; diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/PlatformMethodWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/PlatformMethodWrapper.java deleted file mode 100644 index 4779a7bc..00000000 --- a/src/main/java/co/uk/mommyheather/advancedbackups/PlatformMethodWrapper.java +++ /dev/null @@ -1,66 +0,0 @@ -package co.uk.mommyheather.advancedbackups; - -import java.nio.file.Path; -import java.util.function.Consumer; - -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.world.ServerWorld; - -public class PlatformMethodWrapper { - - public static String worldName = ""; - public static Path worldDir = null; - public static Boolean activity = false; - public static final Consumer infoLogger = AdvancedBackups.infoLogger; - public static final Consumer warningLogger = AdvancedBackups.warningLogger; - public static final Consumer errorLogger = AdvancedBackups.errorLogger; - - public static final String savesDisabledMessage = """ - - -*************************************** -SAVING DISABLED - PREPARING FOR BACKUP! -*************************************** -"""; - public static final String savesEnabledMessage = """ - - -********************************* -SAVING ENABLED - BACKUP COMPLETE! -********************************* -"""; - public static final String saveCompleteMessage = """ - - -************************************* -SAVE COMPLETE - PREPARING FOR BACKUP! -************************************* -"""; - - - public static void disableSaving() { - MinecraftServer server = AdvancedBackups.server; - for (ServerWorld level : server.getWorlds()) { - if (level != null && !level.savingDisabled) { - level.savingDisabled = true; - } - } - warningLogger.accept(savesDisabledMessage); - } - - public static void enableSaving() { - MinecraftServer server = AdvancedBackups.server; - for (ServerWorld level : server.getWorlds()) { - if (level != null && !level.savingDisabled) { - level.savingDisabled = false; - } - } - warningLogger.accept(savesEnabledMessage); - } - - public static void saveOnce() { - MinecraftServer server = AdvancedBackups.server; - server.saveAll(true, true, true); - warningLogger.accept(saveCompleteMessage); - } -} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java deleted file mode 100644 index 5787b961..00000000 --- a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java +++ /dev/null @@ -1,954 +0,0 @@ -package co.uk.mommyheather.advancedbackups.cli; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.FileReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.nio.file.FileSystem; -import java.nio.file.FileSystems; -import java.nio.file.FileVisitResult; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.SimpleFileVisitor; -import java.nio.file.StandardCopyOption; -import java.nio.file.attribute.BasicFileAttributes; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.InputMismatchException; -import java.util.Properties; -import java.util.Scanner; -import java.util.regex.Pattern; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; -import java.util.zip.ZipInputStream; -import java.util.zip.ZipOutputStream; - -import org.fusesource.jansi.AnsiConsole; - -import co.uk.mommyheather.advancedbackups.core.backups.ThreadedBackup; - -public class AdvancedBackupsCLI { - - private static String backupLocation; - private static File serverDir = new File(new File("").toPath().toAbsolutePath().getParent().toString()); - private static String type; - private static Scanner input = new Scanner(System.in); - private static ArrayList fileNames = new ArrayList<>(); - private static File worldFile; - private static String worldPath; - public static void main(String args[]){ - - - System.out.print("\033[H\033[2J"); - System.out.flush(); - - if (System.console() != null) { - AnsiConsole.systemInstall(); //this gets ansi escape codes working on windows. this was a FUCKING PAIN IN MY ASS - } - - - info("Advanced Backups - Version " + AdvancedBackupsCLI.class.getPackage().getImplementationVersion()); - info("Searching for properties...", false); - - Properties props = new Properties(); - File file = new File(serverDir, "AdvancedBackups.properties"); - FileReader reader; - try { - reader = new FileReader(file); - props.load(reader); - - backupLocation = props.getProperty("config.advancedbackups.path"); - type = props.getProperty("config.advancedbackups.type"); - } catch (Exception e) { - error("ERROR LOADING PROPERTIES!"); - error(getStackTrace(e)); - error(""); - error(""); - error("Ensure you're running this from within the mods directory, and the config file is in the parent directory!"); - // Fatal, cannot proceed - return; - } - - if (backupLocation == null || type == null) { - error("ERROR LOADING PROPERTIES!"); - error("Backup location : " + backupLocation); - error("Type : " + type); - // Fatal, cannot proceed - return; - } - - info("Config loaded!"); - - type = getBackupType(); - - worldFile = getWorldFile(); - - if (!worldFile.exists()) { - error("Unable to find world folder!"); - error(worldFile.getAbsolutePath()); - error("Check if the location exists and the name is correct and try again."); - return; - - } - - - File backupDir; - - if (backupLocation.startsWith(Pattern.quote(File.separator))) { - backupDir = new File(backupLocation, File.separator + type + File.separator); - } - else { - backupDir = new File(serverDir, backupLocation.replaceAll(Pattern.quote("." + File.separator), "") + File.separator + type + File.separator); - } - - if (!backupDir.exists()) { - error("Could not find backup directory!"); - error(backupDir.getAbsolutePath()); - error("Have you made any backups before?"); - //Fatal, cannot continue - return; - } - - int backupDateIndex; - try { - backupDateIndex = getBackupDate(backupDir); - } catch (IOException e) { - error("ERROR VIEWING BACKUPS!"); - e.printStackTrace(); - return; - } - - - String restore = restoreWorldOrFile(); - - if (!confirmWarningMessage()) { - error("ABORTED - WILL NOT PROCEED."); - return; - } - - info("Preparing..."); - - - - switch(restore) { - case "world" : { - //No going back now! - //TODO : make a backup of current world state. - deleteEntireWorld(worldFile); - switch(type) { - case "zips" : { - restoreFullZip(backupDateIndex, worldFile); - return; - } - case "differential" : { - restoreFullDifferential(backupDateIndex, worldFile); - return; - } - case "incremental" : { - restoreFullIncremental(backupDateIndex, worldFile); - return; - } - } - } - case "file" : { - switch(type) { - case "zips" : { - restorePartialZip(backupDateIndex, worldFile); - return; - } - case "differential" : { - restorePartialDifferential(backupDateIndex, worldFile); - return; - } - case "incremental" : { - restorePartialIncremental(backupDateIndex, worldFile); - return; - } - } - } - } - - - } - - - - - - - - - - - - - - - - - - - //HELPER METHODS! - private static void info(String out, boolean line) { - if (line) System.out.println(out); - else System.out.print(out); - - } - - private static void warn(String out, boolean line) { - if (line) System.out.println("\u001B[33m" + out + "\u001B[0m"); - else System.out.print("\u001B[33m" + out + "\u001B[0m"); - - } - - private static void error(String out, boolean line) { - if (line) System.out.println("\u001B[31m" + out + "\u001B[0m"); - else System.out.print("\u001B[31m" + out + "\u001B[0m"); - - } - - private static void info(String out) { - info(out, true); - } - - private static void warn(String out) { - warn(out, true); - } - - private static void error(String out) { - error(out, true); - } - - - private static String getStackTrace(final Throwable throwable) { - final StringWriter sw = new StringWriter(); - final PrintWriter pw = new PrintWriter(sw, true); - throwable.printStackTrace(pw); - return sw.getBuffer().toString(); - } - - private static String getBackupType() { - // Select a type of backup to restore - info("Select a backup type to restore. Your server is currently set to use " + type + " backups."); - info("1: zip\n2: differential\n3: incremental"); - info("Enter a number or leave blank for " + type + "."); - int inputType; - try { - String line = input.nextLine(); - if (line == "") { - return type; - } - inputType = Integer.parseInt(line); - } catch (InputMismatchException | NumberFormatException e) { - warn("That was not a number. Please enter a number."); - return getBackupType(); - } - switch (inputType) { - case 1 : return "zips"; - case 2 : return "differential"; - case 3 : return "incremental"; - default : { - warn("Please pick an option between 1 and 3 inclusive."); - return getBackupType(); - } - } - } - - - private static File getWorldFile() { - info("Are you on a client or server?"); - info("1: Client\n2: Server"); - info("Enter a number."); - - int inputType; - File ret = new File(serverDir.getAbsolutePath()); - - try { - String line = input.nextLine(); - if (line == "") { - warn("Please enter a number."); - return getWorldFile(); - } - inputType = Integer.parseInt(line); - } catch (InputMismatchException | NumberFormatException e) { - warn("That was not a number. Please enter a number."); - return getWorldFile(); - } - - if (inputType < 1 || inputType > 2) { - warn("Please enter 1 or 2."); - return getWorldFile(); - } - - if (inputType == 1) { - ret = new File(ret, "/saves/"); - } - - ret = new File(ret, getWorldName(ret)); - return ret; - - } - - private static String getWorldName(File dir) { - ArrayList worlds = new ArrayList<>(); - int worldIndex; - for (File file : dir.listFiles()) { - boolean flag = false; - if (!file.isDirectory()) continue; - for (File file2 : file.listFiles()) { - if (file2.getName().contains("level.dat")) { - flag = true; - } - } - if (flag) { - worlds.add(file.getName()); - } - } - info("Please select your world. Default for servers is \"world\"."); - int index = 1; - for (String world : worlds) { - info (index + ". " + world); - index++; - } - try { - String line = input.nextLine(); - if (line == "") { - warn("Please enter a number."); - return getWorldName(dir); - } - worldIndex = Integer.parseInt(line); - } catch (InputMismatchException | NumberFormatException e) { - warn("That was not a number. Please enter a number."); - return getWorldName(dir); - } - if (worldIndex < 1 || worldIndex > worlds.size()) { - warn("Please enter a number between " + worlds.size() + "."); - return getWorldName(dir); - } - - worldPath = worlds.get(worldIndex -1).replaceAll(" ", "_"); - return worlds.get(worldIndex - 1); - - } - - - private static int getBackupDate(File backupDir) throws IOException { - fileNames.clear(); - int inputType; - - info("Select a backup to restore."); - - for (File file : backupDir.listFiles()) { - if (!file.getName().contains(worldPath)) continue; - fileNames.add(file.getAbsolutePath()); - String out = file.getName(); - out = out.replaceAll(".zip", ""); - out = out.replaceAll(worldPath + "_", ": "); - out = out.replaceAll("-partial", "\u001B[33m partial\u001B[0m"); - out = out.replaceAll("-full", "\u001B[32m full\u001B[0m"); - info(fileNames.size() + out); - } - - try { - String line = input.nextLine(); - if (line == "") { - warn("Please enter a number."); - return getBackupDate(backupDir); - } - inputType = Integer.parseInt(line); - } catch (InputMismatchException | NumberFormatException e) { - warn("That was not a number. Please enter a number."); - return getBackupDate(backupDir); - } - - if (inputType < 1 || inputType > fileNames.size()) { - warn("Please enter a number between " + fileNames.size() + "."); - return getBackupDate(backupDir); - } - - return inputType - 1; - } - - private static String restoreWorldOrFile() { - info("Do you want to restore the entire world state at this point, or a singular file?"); - info("1: Entire world\n2: Single file"); - info("Enter a number."); - int inputType; - try { - String line = input.nextLine(); - if (line == "") { - return type; - } - inputType = Integer.parseInt(line); - } catch (InputMismatchException | NumberFormatException e) { - warn("That was not a number. Please enter a number."); - return restoreWorldOrFile(); - } - switch (inputType) { - case 1 : return "world"; - case 2 : return "file"; - default : { - warn("Please pick 1 or 2."); - return restoreWorldOrFile(); - } - } - - } - - - - private static boolean confirmWarningMessage() { - warn(""); - warn(""); - warn("WARNING! DOING THIS WHILST THE SERVER IS RUNNING CAN CAUSE SEVERE CORRUPTION, PARTIAL RESTORATION, AND OTHER ISSUES."); - warn("TYPE \"continue\" IF YOU WISH TO CONTINUE...", false); - - - String line = input.nextLine(); - if (line.equals("")) { - return confirmWarningMessage(); - } - return line.equals("continue"); - } - - - private static void restoreFullZip(int index, File worldFile) { - byte[] buffer = new byte[1024]; - //The most basic of the bunch. - ZipEntry entry; - try { - FileInputStream fileInputStream = new FileInputStream(fileNames.get(index)); - ZipInputStream zip = new ZipInputStream(fileInputStream); - while ((entry = zip.getNextEntry()) != null) { - File outputFile; - - //FTB Backups and some other mods need special handling. - if (entry.getName().startsWith(worldFile.getName())) { - outputFile = new File(worldFile.getParentFile(), entry.getName()); - } - else { - outputFile = new File(worldFile, entry.getName()); - } - - if (!outputFile.getParentFile().exists()) { - outputFile.getParentFile().mkdirs(); - } - - FileOutputStream outputStream = new FileOutputStream(outputFile); - int length = 0; - while ((length = zip.read(buffer)) > 0) { - outputStream.write(buffer, 0, length); - } - outputStream.close(); - } - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - - private static void restoreFullDifferential(int index, File worldFile) { - //Do we need to check for past backups? if selected is a full backup, we do not. - File backup = new File(fileNames.get(index)); - if (backup.getName().contains("-full")) { - if (backup.isFile()) { - restoreFullZip(index, worldFile); - return; - } - restoreFolder(index, worldFile); - return; - } - //find last FULL backup - for (int i = index;i>0;i--) { - String name = fileNames.get(i); - if (name.contains("-full")) { - info("Restoring last full backup..."); - File file = new File(name); - if (file.isFile()) { - restoreFullZip(i, worldFile); - } - else { - restoreFolder(i, worldFile); - } - break; - } - } - info("\n\nRestoring selected backup..."); - if (backup.isFile()) { - restoreFullZip(index, worldFile); - } - else { - restoreFolder(index, worldFile); - } - } - - private static void restoreFullIncremental(int index, File worldFile) { - //Do we need to check for past backups? if selected is a full backup, we do not. - File backup = new File(fileNames.get(index)); - if (backup.getName().contains("-full")) { - if (backup.isFile()) { - restoreFullZip(index, worldFile); - return; - } - restoreFolder(index, worldFile); - return; - } - //find last FULL backup - int i = index; - while(i >= 0) { - String name = fileNames.get(i); - if (name.contains("-full")) { - info("Restoring last full backup..."); - File file = new File(name); - if (file.isFile()) { - restoreFullZip(i, worldFile); - } - else { - restoreFolder(i, worldFile); - } - break; - } - i--; - } - //restore backups up until the selected one - while(i < index) { - String name = fileNames.get(i); - info("Restoring chained backup..."); - File file = new File(name); - if (file.isFile()) { - restoreFullZip(i, worldFile); - } - else { - restoreFolder(i, worldFile); - } - i++; - } - - - info("\n\nRestoring selected backup..."); - if (backup.isFile()) { - restoreFullZip(index, worldFile); - } - else { - restoreFolder(index, worldFile); - } - } - - private static void restorePartialZip(int index, File worldFile) { - Path file; - HashMap entries = new HashMap<>(); - - try { - FileSystem zipFs = FileSystems.newFileSystem(new File(fileNames.get(index)).toPath(), AdvancedBackupsCLI.class.getClassLoader()); - Path root = zipFs.getPath(""); - Files.walkFileTree(root, new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) throws IOException { - entries.put(file.toString(), file); - return FileVisitResult.CONTINUE; - } - }); - - file = getFileToRestore(entries, ""); - info("Restoring " + file.toString() + "..."); - Path outputFile = new File(worldFile, file.toString()).toPath(); - Files.copy(file, outputFile, StandardCopyOption.REPLACE_EXISTING); - info("Done."); - - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - return; - } - - } - - private static void restorePartialDifferential(int index, File worldFile) { - //Do we need to check for past backups? if selected is a full backup, we do not. - HashMap filePaths = new HashMap<>(); - HashMap dates = new HashMap<>(); - HashMap entryOwners = new HashMap<>(); - try { - File backup = new File(fileNames.get(index)); - if (!backup.getName().contains("-full")) { - //find last FULL backup - for (int i = index;i>=0;i--) { - String name = fileNames.get(i); - if (name.contains("-full")) { - addBackupNamesToLists(new File(name), entryOwners, filePaths, dates, "\u001b[31m"); - break; - } - } - } - - File file = new File(fileNames.get(index)); - addBackupNamesToLists(file, entryOwners, filePaths, dates, "\u001B[32m"); - - HashMap properMapping = new HashMap<>(); - for (String date : dates.keySet()) { - properMapping.put( - date + " " + dates.get(date), - filePaths.get(date) - ); - } - - Object select = getFileToRestore(properMapping, ""); - if (select instanceof Path) { - Path input = (Path) select; - - - if (select.toString().replace("\\", "/").contains("-full/")) { - select = new File( - select.toString().replace("\\", "/") - .split("-full/")[1] - ).toPath(); - } - if (select.toString().replace("\\", "/").contains("-partial/")) { - select = new File( - select.toString().replace("\\", "/") - .split("-partial/")[1] - ).toPath(); - } - - File outputFile = new File(worldFile, select.toString()); - if (!outputFile.getParentFile().exists()) { - outputFile.getParentFile().mkdirs(); - } - info("\n\nRestoring file : " + select); - Files.copy(input, outputFile.toPath(), StandardCopyOption.REPLACE_EXISTING); - } - else if (select instanceof ZipEntry) { - ZipEntry entry = (ZipEntry) select; - - File outputFile = new File(worldFile, entry.toString()); - FileOutputStream outputStream = new FileOutputStream(outputFile); - - info("Restoring " + entry.toString() + "..."); - - byte[] buffer = new byte[1028]; - InputStream inputSteam = entryOwners.get(entry.toString()).getInputStream(entry); - int length; - while ((length = inputSteam.read(buffer, 0, buffer.length)) > 0) { - outputStream.write(buffer, 0, length); - } - outputStream.flush(); - outputStream.close(); - } - - - } - catch (IOException e){ - //TODO : Scream at user - e.printStackTrace(); - } - } - - private static void restorePartialIncremental(int index, File worldFile) { - //Do we need to check for past backups? if selected is a full backup, we do not. - HashMap filePaths = new HashMap<>(); - HashMap dates = new HashMap<>(); - HashMap entryOwners = new HashMap<>(); - try { - File backup = new File(fileNames.get(index)); - if (!backup.getName().contains("-full")) { - int i; - //find last FULL backup - for (i = index;i>=0;i--) { - String name = fileNames.get(i); - if (name.contains("-full")) { - addBackupNamesToLists(new File(name), entryOwners, filePaths, dates, "\u001b[31m"); - break; - } - } - while (i < index) { - String name = fileNames.get(i); - addBackupNamesToLists(new File(name), entryOwners, filePaths, dates, "\u001b[31m"); - i++; - } - - } - - File file = new File(fileNames.get(index)); - addBackupNamesToLists(file, entryOwners, filePaths, dates, "\u001B[32m"); - - HashMap properMapping = new HashMap<>(); - for (String date : dates.keySet()) { - properMapping.put( - date + " " + dates.get(date), - filePaths.get(date) - ); - } - - Object select = getFileToRestore(properMapping, ""); - if (select instanceof Path) { - Path input = (Path) select; - - - if (select.toString().replace("\\", "/").contains("-full/")) { - select = new File( - select.toString().replace("\\", "/") - .split("-full/")[1] - ).toPath(); - } - if (select.toString().replace("\\", "/").contains("-partial/")) { - select = new File( - select.toString().replace("\\", "/") - .split("-partial/")[1] - ).toPath(); - } - - File outputFile = new File(worldFile, select.toString()); - if (!outputFile.getParentFile().exists()) { - outputFile.getParentFile().mkdirs(); - } - info("\n\nRestoring file : " + select); - Files.copy(input, outputFile.toPath(), StandardCopyOption.REPLACE_EXISTING); - } - else if (select instanceof ZipEntry) { - ZipEntry entry = (ZipEntry) select; - - File outputFile = new File(worldFile, entry.toString()); - FileOutputStream outputStream = new FileOutputStream(outputFile); - - info("Restoring " + entry.toString() + "..."); - - byte[] buffer = new byte[1028]; - InputStream inputSteam = entryOwners.get(entry.toString()).getInputStream(entry); - int length; - while ((length = inputSteam.read(buffer, 0, buffer.length)) > 0) { - outputStream.write(buffer, 0, length); - } - outputStream.flush(); - outputStream.close(); - } - - - } - catch (IOException e){ - //TODO : Scream at user - e.printStackTrace(); - } - } - - - private static void restoreFolder(int index, File worldFile) { - File backup = new File(fileNames.get(index)); - - try { - Files.walkFileTree(backup.toPath(), new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) throws IOException { - File source = backup.toPath().relativize(file).toFile(); - File outputFile = new File(worldFile, source.getPath()); - - if (!outputFile.getParentFile().exists()) { - outputFile.getParentFile().mkdirs(); - } - Files.copy(file, outputFile.toPath()); - return FileVisitResult.CONTINUE; - } - }); - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - - - private static void deleteEntireWorld(File worldDir) { - backupExistingWorld(worldDir); - try { - Files.walkFileTree(worldDir.toPath(), new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { - file.toFile().delete(); - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult postVisitDirectory(Path file, java.io.IOException arg1) { - if (file.toFile().listFiles().length == 0) { - file.toFile().delete(); - } - return FileVisitResult.CONTINUE; - } - }); - } catch (IOException e) { - warn("Failed to delete file :"); - e.printStackTrace(); - } - } - - private static void backupExistingWorld(File worldDir) { - try { - File out = new File(worldDir, "../cli" + ThreadedBackup.serialiseBackupName("backup") + ".zip"); - FileOutputStream outputStream = new FileOutputStream(out); - ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream); - zipOutputStream.setLevel(4); - Files.walkFileTree(worldDir.toPath(), new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { - Path targetFile; - try { - targetFile = worldDir.toPath().relativize(file); - if (targetFile.toFile().getName().compareTo("session.lock") == 0) { - return FileVisitResult.CONTINUE; - } - zipOutputStream.putNextEntry(new ZipEntry(targetFile.toString())); - byte[] bytes = Files.readAllBytes(file); - zipOutputStream.write(bytes, 0, bytes.length); - zipOutputStream.closeEntry(); - - } catch (IOException e) { - // TODO : Scream at user - e.printStackTrace(); - } - - return FileVisitResult.CONTINUE; - } - }); - zipOutputStream.flush(); - zipOutputStream.close(); - } catch (Exception e) { - - } - } - - - private static T getFileToRestore(HashMap files, String directory) { - ArrayList toDisplay = new ArrayList<>(); - HashMap keyMap = new HashMap<>(); - int index = 1; - for (String name : files.keySet()) { - String name2 = name.replace("\\", "/"); // this replacement can fix some problems with wsl, and helps keep code neat. - if (name2.contains(directory)) { - name2 = name2.replace(directory, ""); - if (name2.startsWith(worldFile.getName())) { - name2 = name2.replace(worldFile.getName() + "/", ""); - } - if (name2.contains("/")) { - name2 = "\u001B[33mdirectory\u001B[0m " + name2.split("/")[0]; - } - if (!toDisplay.contains(name2)) { - toDisplay.add(name2); - keyMap.put(name2, name); - } - } - } - toDisplay = sortStringsAlphabeticallyWithDirectoryPriority(toDisplay); - info("Choose a file to restore.\n"); - for (String name : toDisplay) { - if (index < 10) { - info(index + ": " + name); - } - else { - info(index + ": " + name); - } - index++; - } - if (!directory.equals("")) { - info(index + ": ../"); - } - - - int userInput; - try { - String line = input.nextLine(); - if (line == "") { - warn("Please enter a number!"); - return getFileToRestore(files, directory); - } - userInput = Integer.parseInt(line); - } catch (InputMismatchException | NumberFormatException e) { - warn("That was not a number. Please enter a number."); - return getFileToRestore(files, directory); - } - - if (userInput <= 0 || userInput > (directory.equals("") ? toDisplay.size() : toDisplay.size() + 1)) { - warn("Please enter a number in the specified range!"); - return getFileToRestore(files, directory); - } - else if (userInput > toDisplay.size()) { - return null; - } - else if (!toDisplay.get(userInput - 1).contains("\u001B[33mdirectory\u001B[0m ")) { - return files.get(keyMap.get(toDisplay.get(userInput -1))); - } - - T result = getFileToRestore(files, directory + toDisplay.get(userInput -1).replace("\u001B[33mdirectory\u001B[0m ", "") + "/"); - if (result != null) { - return result; - } - else { - return getFileToRestore(files, directory); - } - } - - - private static ArrayList sortStringsAlphabeticallyWithDirectoryPriority(ArrayList in) { - ArrayList out = new ArrayList<>(); - Collections.sort(in); - for (String string : in) { - if (string.contains("\u001B[33mdirectory\u001B[0m")) { - out.add(string); - } - } - for (String string : in) { - if (!string.contains("\u001B[33mdirectory\u001B[0m")) { - out.add(string); - } - } - return out; - } - - - private static void addBackupNamesToLists(File file, HashMap entryOwners, HashMap filePaths, - HashMap dates, String colour) throws IOException { - - if (file.isFile()) { - - ZipFile zipFile = new ZipFile(file); - Enumeration entryEnum = zipFile.entries(); - - while (entryEnum.hasMoreElements()) { - ZipEntry entry = entryEnum.nextElement(); - - String backupName = file.toString().replace("\\", "/"); - filePaths.put(entry.toString().replace("\\", "/"), entry); - dates.put(entry.toString().replace("\\", "/"), "\u001b[31m" - + backupName - .substring(backupName.toString().lastIndexOf("/") + 1) - .replace(worldPath + "_", "") - .replace("-full.zip", "") - .replace("-partial.zip", "") - + "\u001B[0m"); - entryOwners.put(entry.toString(), zipFile); - } - } - - else { - Files.walkFileTree(file.toPath(), new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path path, BasicFileAttributes attributes) throws IOException { - String backupName = file.toString().replace("\\", "/"); - filePaths.put(file.toPath().relativize(path).toString().replace("\\", "/"), path); - dates.put(file.toPath().relativize(path).toString().replace("\\", "/"), "\u001b[31m" - + backupName - .substring(backupName.toString().lastIndexOf("/") + 1) - .replace(worldPath + "_", "") - .replace("-full", "") - .replace("-partial", "") - + "\u001B[0m"); - return FileVisitResult.CONTINUE; - } - }); - } - } - -} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java deleted file mode 100644 index 76e59aef..00000000 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java +++ /dev/null @@ -1,77 +0,0 @@ -package co.uk.mommyheather.advancedbackups.core; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileWriter; -import java.nio.file.Files; -import java.util.function.Consumer; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; - -import co.uk.mommyheather.advancedbackups.core.backups.BackupCheckEnum; -import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; -import co.uk.mommyheather.advancedbackups.core.backups.gson.DifferentialManifest; -import co.uk.mommyheather.advancedbackups.core.config.AVConfig; - -public class CoreCommandSystem { - private static GsonBuilder builder = new GsonBuilder(); - private static Gson gson; - static { - builder.setPrettyPrinting(); - gson = builder.create(); - } - - - //These methods are all called by relevant command classes in version specific code - public static void checkBackups(Consumer chat) { - BackupCheckEnum check = BackupWrapper.checkBackups(); - chat.accept(check.getCheckMessage()); - } - - public static void startBackup(Consumer chat) { - BackupCheckEnum check = BackupWrapper.checkBackups(); - chat.accept(check.getCheckMessage()); - if (check.success()) { - chat.accept("Starting backup..."); - BackupWrapper.makeSingleBackup(0); - } - } - - public static void forceBackup(Consumer chat) { - chat.accept("Forcing a backup..."); - BackupWrapper.makeSingleBackup(0); - } - - public static void reloadConfig(Consumer chat) { - chat.accept("Reloading config..."); - AVConfig.loadConfig(); - chat.accept("Done!"); - } - - public static void resetChainLength(Consumer chat) { - chat.accept("Resetting chain length... The next backup will be a complete backup."); - boolean differential = AVConfig.config.getBackupType().equals("differential") ? true : false; - File manifestFile = differential ? new File(AVConfig.config.getPath() + "/differential/manifest.json") : new File(AVConfig.config.getPath() + "/incremental/manifest.json"); - DifferentialManifest manifest; - try { - if (manifestFile.exists()) { - manifest = gson.fromJson(new String(Files.readAllBytes(manifestFile.toPath())), DifferentialManifest.class); - manifest.setChain(manifest.getChain() + AVConfig.config.getMaxDepth()); - FileWriter writer = new FileWriter(manifestFile); - writer.write(gson.toJson(manifest)); - writer.flush(); - writer.close(); - chat.accept("Done!"); - return; - } - else { - chat.accept("No manifest file exists!"); - return; - } - } catch (Exception e) { - chat.accept("Error resetting chain length. - check logs for more info."); - e.printStackTrace(); - } - } -} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupCheckEnum.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupCheckEnum.java deleted file mode 100644 index 06e00e14..00000000 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupCheckEnum.java +++ /dev/null @@ -1,38 +0,0 @@ -package co.uk.mommyheather.advancedbackups.core.backups; - -public enum BackupCheckEnum { - SUCCESS, - DISABLED, - NOACTIVITY, - TOORECENT; - - public boolean success() { - switch (this) { - case SUCCESS: { - return true; - } - default : return false; - } - } - - - public String getCheckMessage() { - switch(this) { - case SUCCESS : { - return "Checks successful!"; - } - case DISABLED : { - return "Backups are disabled!"; - } - case NOACTIVITY : { - return "Player activity is required, but none have been active!"; - } - case TOORECENT : { - return "The time since the last backup is less than the minimum time specified in config!"; - } - default : { - return "You should not see this message, report a bug!"; - } - } - } -} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java deleted file mode 100644 index b346e89c..00000000 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java +++ /dev/null @@ -1,74 +0,0 @@ -package co.uk.mommyheather.advancedbackups.core.backups; - -import java.time.LocalDateTime; -import java.util.ArrayList; - -import co.uk.mommyheather.advancedbackups.core.config.AVConfig; - -public class BackupTimingThread extends Thread { - private int loops = 0; - private int index = 0; - private long prev = 0; - - public BackupTimingThread() { - setName("AB Backup Timing Daemon"); - setDaemon(true); - } - - @Override - public void run() { - while (true) { - try { - long time = calculateNextBackupTime(); - sleep(time); - BackupWrapper.checkAndMakeBackups(); - } catch (InterruptedException e) { - // TODO Scream at user - e.printStackTrace(); - break; - } - } - } - - - private long calculateNextBackupTime() { - long forcedMillis = BackupWrapper.mostRecentBackupTime() + (long) (AVConfig.config.getMaxTimer() * 3600000L); - if (forcedMillis == AVConfig.config.getMaxTimer() * 3600000L || forcedMillis <= System.currentTimeMillis()) forcedMillis = 300000; //sets it to 5m if no backup exists or the timer is already execeeded to get the chain going - else forcedMillis -= System.currentTimeMillis(); - long ret = Long.MAX_VALUE; - if (AVConfig.config.getUptimeSchedule() && !BackupWrapper.configuredPlaytime.isEmpty()) { - ArrayList timings = new ArrayList(BackupWrapper.configuredPlaytime); - if (index >= timings.size()) { - index = 0; - loops++; - } - ret = (timings.get(index) + (timings.get(timings.size() - 1) * loops)); - ret -= prev; - prev += ret; - index++; - } - - else if (!BackupWrapper.configuredPlaytime.isEmpty()) { - long nextTime = 0; - long currentTime = System.currentTimeMillis(); - ArrayList timings = new ArrayList(BackupWrapper.configuredPlaytime); - for (long time : timings) { - if (time >= currentTime) { - nextTime = time; - break; - } - } - ret = nextTime >= currentTime ? nextTime - currentTime : 86640000 - currentTime; - } - - return Math.min(forcedMillis, ret); - - - - - - - } - - -} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java deleted file mode 100644 index f5960e0d..00000000 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java +++ /dev/null @@ -1,273 +0,0 @@ -package co.uk.mommyheather.advancedbackups.core.backups; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.FileWriter; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.StringReader; -import java.util.ArrayList; -import java.util.Date; - - -import co.uk.mommyheather.advancedbackups.PlatformMethodWrapper; -import co.uk.mommyheather.advancedbackups.core.config.AVConfig; - -public class BackupWrapper { - - public static ArrayList configuredPlaytime = new ArrayList<>(); - - - public static void checkStartupBackups () { - if (AVConfig.config.getForceOnStartup()) { - checkAndMakeBackups(Math.max(5000, AVConfig.config.getStartupDelay() * 1000)); - } - - new BackupTimingThread().start(); - } - - public static void checkShutdownBackups() { - if (AVConfig.config.getForceOnShutdown()) { - checkAndMakeBackups(); - } - } - - public static void checkAndMakeBackups(long delay) { - BackupCheckEnum e = checkBackups(); - if (e.success()) { - makeSingleBackup(delay); - } - } - - public static void checkAndMakeBackups() { - checkAndMakeBackups(0); - } - - - public static BackupCheckEnum checkBackups() { - prepareBackupDestination(); - if (!AVConfig.config.getEnabled()) return BackupCheckEnum.DISABLED; - if (AVConfig.config.getRequireActivity() && !PlatformMethodWrapper.activity) return BackupCheckEnum.NOACTIVITY; - if (checkMostRecentBackup()) return BackupCheckEnum.TOORECENT; - - return BackupCheckEnum.SUCCESS; - - } - - private static void prepareBackupDestination() { - File file = new File(AVConfig.config.getPath()); - - if (!file.exists()) { - file.mkdirs(); - } - prepareReadMe(file); - - File zipFile = new File(file, "/zips/"); - if (!zipFile.exists()) { - zipFile.mkdirs(); - } - File differential = new File(file, "/differential/"); - if (!differential.exists()) { - differential.mkdirs(); - } - File incremental = new File(file, "/incremental/"); - if (!incremental.exists()) { - incremental.mkdirs(); - } - } - - private static void prepareReadMe(File path) { - File readme = new File(path, "README-BEFORE-RESTORING.txt"); - if (!readme.exists()) { - try { - InputStream is = BackupWrapper.class.getClassLoader().getResourceAsStream("advancedbackups-readme.txt"); - readme.createNewFile(); - FileOutputStream outputStream = new FileOutputStream(readme); - byte[] buf = new byte[1028]; - int n; - while ((n = is.read(buf)) > 0) { - outputStream.write(buf, 0, n); - } - outputStream.flush(); - outputStream.close(); - - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - - } - } - - - public static boolean checkMostRecentBackup() { - // Return true if the time difference between the most recent backup and the backup-to-be - // is less than specified in the config. - - Date date = new Date(); - long configVal = (long) (3600000F * AVConfig.config.getMinTimer()); - return (date.getTime() - mostRecentBackupTime()) < configVal; - } - - - public static long mostRecentBackupTime() { - - File directory = new File(AVConfig.config.getPath()); - - switch(AVConfig.config.getBackupType()) { - case "zip" : { - directory = new File(directory, "/zips/"); - break; - } - case "differential" : { - directory = new File(directory, "/differential/"); - break; - } - case "incremental" : { - directory = new File(directory, "/incremental/"); - break; - } - - } - - File[] files = directory.listFiles(); - long lastModifiedTime = Long.MIN_VALUE; - if (files == null || files.length == 0) return 0L; - for (File file : files) { - if (file.lastModified() > lastModifiedTime && !file.getName().contains("manifest")) { - lastModifiedTime = file.lastModified(); - } - } - return lastModifiedTime; - } - - - public static void makeSingleBackup(long delay) { - - PlatformMethodWrapper.disableSaving(); - if (AVConfig.config.getSave()) { - PlatformMethodWrapper.saveOnce(); - } - - // Make new thread, run backup utility. - ThreadedBackup threadedBackup = new ThreadedBackup(delay); - threadedBackup.start(); - // Don't re-enable saving - leave that down to the backup thread. - - } - - public static void finishBackup() { - File directory = new File(AVConfig.config.getPath()); - ThreadedBackup.running = false; - PlatformMethodWrapper.enableSaving(); - - switch(AVConfig.config.getBackupType()) { - case "zip" : { - directory = new File(directory, "/zips/"); - long date = Long.MIN_VALUE; - while (true) { - if (calculateDirectorySize(directory) < AVConfig.config.getMaxSize() * 1000000000L) return; - File file = getFirstBackupAfterDate(directory, date); - date = file.lastModified(); - file.delete(); - } - } - case "differential" : { - directory = new File(directory, "/differential/"); - long date = Long.MIN_VALUE; - while (true) { - if (calculateDirectorySize(directory) < AVConfig.config.getMaxSize() * 1000000000L) return; - File file = getFirstBackupAfterDate(directory, date); - date = file.lastModified(); - if (file.getName().contains("full")) { - File nextFile = getFirstBackupAfterDate(directory, date); - if (nextFile.getName().contains("partial")) { - nextFile.delete(); - } - else { - file.delete(); - } - } - else { - file.delete(); - } - - } - } - case "incremental" : { - directory = new File(directory, "/incremental/"); - if (!AVConfig.config.getPurgeIncrementals()) return; - long date = Long.MIN_VALUE; - while (true) { - if (calculateDirectorySize(directory) < AVConfig.config.getMaxSize() * 1000000000L) return; - if (calculateChainCount(directory) < 2) return; - PlatformMethodWrapper.errorLogger.accept("Purging incremental backup chain - too much space taken up!"); - File file = getFirstBackupAfterDate(directory, date); - date = file.lastModified(); - if (file.getName().contains("full")) { - file.delete(); - while (true) { - file = getFirstBackupAfterDate(directory, date); - date = file.lastModified(); - if (file.getName().contains("full")) { - file.delete(); - } - else { - break; - } - } - } - else { - file.delete(); - } - - } - } - - } - } - - - public static long calculateDirectorySize(File directory) { - long size = 0; - File[] files = directory.listFiles(); - if (files == null || files.length == 0) return size; - for (File file : files) { - if (file.isFile()) { - size += file.length(); - } - else { - size += calculateDirectorySize(file); - } - } - return size; - } - - public static File getFirstBackupAfterDate(File directory, long date) { - File[] files = directory.listFiles(); - File oldestFile = null; - long currentDate = Long.MAX_VALUE; - if (files == null || files.length == 0) return null; - for (File file : files) { - if (file.lastModified() < currentDate && file.lastModified() > date) { - currentDate = file.lastModified(); - oldestFile = file; - } - } - - return oldestFile; - } - - public static int calculateChainCount(File directory) { - int count = 0; - File[] files = directory.listFiles(); - if (files == null || files.length == 0) return 0; - for (File file : files) { - if (file.getName().contains("full")) { - count++; - } - } - return count; - } -} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java deleted file mode 100644 index b331c31b..00000000 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java +++ /dev/null @@ -1,240 +0,0 @@ -package co.uk.mommyheather.advancedbackups.core.backups; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.FileWriter; -import java.io.IOException; -import java.nio.file.FileVisitResult; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.SimpleFileVisitor; -import java.nio.file.attribute.BasicFileAttributes; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Date; -import java.util.zip.ZipEntry; -import java.util.zip.ZipOutputStream; - - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; - -import co.uk.mommyheather.advancedbackups.PlatformMethodWrapper; -import co.uk.mommyheather.advancedbackups.core.backups.gson.DifferentialManifest; -import co.uk.mommyheather.advancedbackups.core.config.AVConfig; - -public class ThreadedBackup extends Thread { - private static GsonBuilder builder = new GsonBuilder(); - private static Gson gson; - private long delay; - private static int count; - private static float partialSize; - private static float completeSize; - public static boolean running = false; - private static String backupName; - - static { - builder.setPrettyPrinting(); - gson = builder.create(); - } - - public ThreadedBackup(long delay) { - setName("AB Active Backup Thread"); - this.delay = delay; - count = 0; - partialSize = 0F; - completeSize = 0F; - } - - @Override - public void run() { - try { - sleep(delay); - } catch (InterruptedException e) { - return; - } - if (running) { - return; - } - running = true; - - File file = new File(AVConfig.config.getPath()); - backupName = serialiseBackupName(PlatformMethodWrapper.worldDir.getParent().toFile().getName().replaceAll(" ", "_")); - - switch(AVConfig.config.getBackupType()) { - case "zip" : { - makeZipBackup(file); - break; - } - case "differential" : { - makeDifferentialOrIncrementalBackup(file, true); - break; - } - case "incremental" : { - makeDifferentialOrIncrementalBackup(file, false); - break; - } - } - - BackupWrapper.finishBackup(); - } - - - private static void makeZipBackup(File file) { - try { - - File zip = new File(file.toString() + "/zips/", backupName + ".zip"); - PlatformMethodWrapper.infoLogger.accept("Preparing zip backup name: " + zip.getName()); - FileOutputStream outputStream = new FileOutputStream(zip); - ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream); - zipOutputStream.setLevel(AVConfig.config.getCompressionLevel()); - - Files.walkFileTree(PlatformMethodWrapper.worldDir, new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { - Path targetFile; - try { - targetFile = PlatformMethodWrapper.worldDir.relativize(file); - if (targetFile.toFile().getName().compareTo("session.lock") == 0) { - return FileVisitResult.CONTINUE; - } - zipOutputStream.putNextEntry(new ZipEntry(targetFile.toString())); - byte[] bytes = Files.readAllBytes(file); - zipOutputStream.write(bytes, 0, bytes.length); - zipOutputStream.closeEntry(); - - } catch (IOException e) { - // TODO : Scream at user - e.printStackTrace(); - PlatformMethodWrapper.errorLogger.accept(file.toString()); - } - - return FileVisitResult.CONTINUE; - } - }); - zipOutputStream.flush(); - zipOutputStream.close(); - - } catch (IOException e){ - // TODO : Scream at user - e.printStackTrace(); - } - - } - - - private static void makeDifferentialOrIncrementalBackup(File location, boolean differential) { - try { - PlatformMethodWrapper.infoLogger.accept("Preparing " + (differential ? "differential" : "incremental") + " backup name: " + backupName); - long time = 0; - File manifestFile = differential ? new File(location.toString() + "/differential/manifest.json") : new File(location.toString() + "/incremental/manifest.json"); - DifferentialManifest manifest; - if (manifestFile.exists()) { - manifest = gson.fromJson(new String(Files.readAllBytes(manifestFile.toPath())), DifferentialManifest.class); - } - else { - manifest = DifferentialManifest.defaultValues(); - } - - long comp = differential ? manifest.getLastFull() : manifest.getLastPartial(); - ArrayList toBackup = new ArrayList<>(); - ArrayList completeBackup = new ArrayList<>(); - - - boolean completeTemp = manifest.getComplete().size() == 0 || manifest.getChain() >= AVConfig.config.getMaxDepth() ? true : false; - - Files.walkFileTree(PlatformMethodWrapper.worldDir, new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { - Path targetFile; - targetFile = PlatformMethodWrapper.worldDir.relativize(file); - if (targetFile.toFile().getName().compareTo("session.lock") == 0) { - return FileVisitResult.CONTINUE; - } - count++; - completeSize += attributes.size(); - completeBackup.add(targetFile); - if (completeTemp || attributes.lastModifiedTime().toMillis() >= comp) { - toBackup.add(targetFile); - partialSize += attributes.size(); - } - return FileVisitResult.CONTINUE; - } - }); - boolean complete = completeTemp; - if (toBackup.size() >= count) { - complete = true; - } - if ((partialSize / completeSize) * 100F > AVConfig.config.getMaxSizePercent()) { - complete = true; - toBackup.clear(); - toBackup.addAll(completeBackup); - } - - backupName += complete? "-full":"-partial"; - - - - if (AVConfig.config.getCompressChains()) { - File zip = differential ? new File(location.toString() + "/differential/", backupName +".zip") : new File(location.toString() + "/incremental/", backupName +".zip"); - FileOutputStream outputStream = new FileOutputStream(zip); - ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream); - zipOutputStream.setLevel(AVConfig.config.getCompressionLevel()); - - for (Path path : toBackup) { - zipOutputStream.putNextEntry(new ZipEntry(path.toString())); - byte[] bytes = Files.readAllBytes(new File(PlatformMethodWrapper.worldDir.toString(), path.toString()).toPath()); - zipOutputStream.write(bytes, 0, bytes.length); - zipOutputStream.closeEntry(); - } - zipOutputStream.flush(); - zipOutputStream.close(); - - time = zip.lastModified(); - } - else { - File dest = differential ? new File(location.toString() + "/differential/", backupName + "/") :new File(location.toString() + "/incremental/", backupName + "/"); - dest.mkdirs(); - for (Path path : toBackup) { - File out = new File(dest, path.toString()); - if (!out.getParentFile().exists()) { - out.getParentFile().mkdirs(); - } - Files.copy(new File(PlatformMethodWrapper.worldDir.toString(), path.toString()).toPath(), out.toPath()); - } - time = dest.lastModified(); - } - - //Finally, update + write the manifest - if (complete || toBackup.size() >= count) { - manifest.setChain(0); - manifest.getComplete().add(time); - manifest.setLastFull(time); - } - else { - manifest.setChain(manifest.getChain() + 1); - manifest.getPartial().add(new Date().getTime()); - manifest.setLastPartial(new Date().getTime()); - } - - FileWriter writer = new FileWriter(manifestFile); - writer.write(gson.toJson(manifest)); - writer.flush(); - writer.close(); - - } catch (IOException e) { - // TODO Scream at user - e.printStackTrace(); - } - - - } - - - public static String serialiseBackupName(String in) { - Date date = new Date(); - String pattern = "yyyy-MM-dd_hh-mm-ss"; - - return in + "_" + new SimpleDateFormat(pattern).format(date); - } -} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/gson/DifferentialManifest.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/gson/DifferentialManifest.java deleted file mode 100644 index ca1385cc..00000000 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/gson/DifferentialManifest.java +++ /dev/null @@ -1,73 +0,0 @@ -package co.uk.mommyheather.advancedbackups.core.backups.gson; - -import java.util.ArrayList; -import java.util.List; - -public class DifferentialManifest { - private List complete; - private List partial; - private int chain; - private long lastFull; - private long lastPartial; - - - public List getComplete() { - return complete; - } - - - public void setComplete(List complete) { - this.complete = complete; - } - - - public List getPartial() { - return partial; - } - - - public void setPartial(List partial) { - this.partial = partial; - } - - - public int getChain() { - return chain; - } - - - public void setChain(int chain) { - this.chain = chain; - } - - - public long getLastFull() { - return lastFull; - } - - - public void setLastFull(long lastFull) { - this.lastFull = lastFull; - } - - - public long getLastPartial() { - return Math.max(lastFull, lastPartial); - } - - - public void setLastPartial(long lastPartial) { - this.lastPartial = lastPartial; - } - - - public static DifferentialManifest defaultValues() { - DifferentialManifest manifest = new DifferentialManifest(); - manifest.complete = new ArrayList<>(); - manifest.partial = new ArrayList<>(); - manifest.chain = 0; - manifest.lastFull = 0; - manifest.lastPartial = 0; - return manifest; - } -} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java deleted file mode 100644 index b56eed0c..00000000 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java +++ /dev/null @@ -1,165 +0,0 @@ -package co.uk.mommyheather.advancedbackups.core.config; - -import java.io.File; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Properties; - -import co.uk.mommyheather.advancedbackups.PlatformMethodWrapper; -import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; - -public class AVConfig { - - private static final String[] supportedProps = { - "config.advancedbackups.enabled", - "config.advancedbackups.save", - "config.advancedbackups.activity", - "config.advancedbackups.type", - "config.advancedbackups.path", - "config.advancedbackups.size", - "config.advancedbackups.frequency.min", - "config.advancedbackups.frequency.max", - "config.advancedbackups.frequency.uptime", - "config.advancedbackups.frequency.schedule", - "config.advancedbackups.frequency.shutdown", - "config.advancedbackups.frequency.startup", - "config.advancedbackups.frequency.delay", - "config.advancedbackups.logging.silent", - - "config.advancedbackups.zips.compression", - - "config.advancedbackups.chains.length", - "config.advancedbackups.chains.compress", - "config.advancedbackups.chains.smart", - "config.advancedbackups.chains.maxpercent", - - "config.advancedbackups.purge.incrementals" - - }; - - public static ConfigData config; - - public static void loadOrCreateConfig() { - // Called when the config needs to be loaded, but one may not exist. - // Creates a new config it one doesn't exist, then loads it. - File file = new File("./AdvancedBackups.properties"); - if (!file.exists()) { - initConfig(); - } - loadConfig(); - } - - public static void initConfig() { - // Called when no config file is present. - // Create a complete properties file in the cwd - File file = new File("./AdvancedBackups.properties"); - try { - if (!file.exists()) { - file.createNewFile(); - file.setWritable(true); - } - FileWriter writer = new FileWriter(file); - writer.write(ConfigData.defaults()); - writer.close(); - } catch (IOException e) { - // TODO : Scream to user - e.printStackTrace(); - } - - - } - - public static void loadConfig() { - // Called when the config needs to be loaded. - // Populates all values of ConfigData.class - - Properties props = new Properties(); - File file = new File("./AdvancedBackups.properties"); - FileReader reader; - try { - reader = new FileReader(file); - props.load(reader); - } catch (IOException e) { - // TODO : Scream to user - e.printStackTrace(); - } - - config = new ConfigData(); - - config.setEnabled(props.getProperty("config.advancedbackups.enabled", "true")); - config.setSave(props.getProperty("config.advancedbackups.save", "false")); - config.setRequireActivity(props.getProperty("config.advancedbackups.activity", "false")); - config.setBackupType(props.getProperty("config.advancedbackups.type", "differential")); - config.setPath(props.getProperty("config.advancedbackups.path", "./backups")); - config.setMaxSize(props.getProperty("config.advancedbackups.size", "50")); - config.setMinTimer(props.getProperty("config.advancedbackups.frequency.min", "0.5")); - config.setMaxTimer(props.getProperty("config.advancedbackups.frequency.max", "24")); - config.setUptimeSchedule(props.getProperty("config.advancedbackups.frequency.uptime", "true")); - config.setSchedule(props.getProperty("config.advancedbackups.frequency.schedule", "12:00")); - config.setForceOnShutdown(props.getProperty("config.advancedbackups.frequency.shutdown", "false")); - config.setForceOnStartup(props.getProperty("config.advancedbackups.frequency.startup", "false")); - config.setStartupDelay(props.getProperty("config.advancedbackups.frequency.delay", "5")); - config.setSilent(props.getProperty("config.advancedbackups.logging.silent", "false")); - - config.setCompressionLevel(props.getProperty("config.advancedbackups.zips.compression", "5")); - - config.setMaxDepth(props.getProperty("config.advancedbackups.chains.length", "50")); - config.setCompressChains(props.getProperty("config.advancedbackups.chains.compress", "true")); - config.setSmartChains(props.getProperty("config.advancedbackups.chains.smart", "true")); - config.setMaxSizePercent(props.getProperty("config.advancedbackups.chains.maxpercent", "75")); - - config.setPurgeIncrementals(props.getProperty("config.advancedbackups.purge.incrementals", "false")); - - - - String timingsString = config.getSchedule(); - if (timingsString.length() != 0) { - BackupWrapper.configuredPlaytime = new ArrayList<>(); - for (String time : timingsString.split(",")) { - String[] hm = time.split(":"); - long hours = Long.parseLong(hm[0]) * 3600000L; - long mins = Long.parseLong(hm[1]) * 60000; - BackupWrapper.configuredPlaytime.add(hours + mins); - } - } - - boolean flag = false; - - for (String prop : supportedProps) { - if (!props.containsKey(prop)) { - flag = true; - break; - } - } - - if (flag) { - PlatformMethodWrapper.warningLogger.accept("Broken, incomplete or misising config found! Generating new file whilst preserving any existing config values..."); - - File newPropsFile = new File("./AdvancedBackups.properties"); - try { - if (!newPropsFile.exists()) { - newPropsFile.createNewFile(); - } - FileWriter writer = new FileWriter(newPropsFile); - writer.write(ConfigData.config(config.getEnabled(), config.getSave(), - config.getRequireActivity(), config.getBackupType(), config.getPath(), - config.getMaxSize(), config.getMinTimer(), config.getMaxTimer(), - config.getUptimeSchedule(), config.getSchedule(), config.getForceOnShutdown(), - config.getForceOnStartup(), config.getStartupDelay(), config.getSilent(), - config.getCompressionLevel(), config.getMaxDepth(), config.getCompressChains(), - config.getSmartChains(), config.getMaxSizePercent(), config.getPurgeIncrementals() - )); - writer.close(); - } catch (IOException e) { - // TODO : Scream to user - e.printStackTrace(); - - } - loadConfig(); - } - - } - -} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java deleted file mode 100644 index ecf162c9..00000000 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java +++ /dev/null @@ -1,378 +0,0 @@ -package co.uk.mommyheather.advancedbackups.core.config; - -public class ConfigData { - - private Boolean enabled; - //Allows outright disabling of backups. - //OPTIONS = "TRUE", "FALSE" - - private Boolean save; - //Whether to save before a backup. - //OPTIONS = "TRUE", "FALSE" - - private Boolean requireActivity; - //Whether to require player activity between backups. - //OPTIONS = "TRUE", "FALSE" - - private String backupType; - //The type of backup to make. Each has a separate file structure, but only the currently selected backup type is scanned for. - //OPTIONS = "ZIP", "DIFFERENTIAL", "INCREMENTAL" - - private long maxSize; - //Maximum size of backups. With zips, deletes the absolute oldest file if size is exceeded after making a backup, and repeats until below max size. - //RANGE = 5GB - 9999GB - - private float minTimer; - //Ensure this amount of time is waited between backups, in hours. - //RANGE = 0.5 - 500 - - private float maxTimer; - //Triggers a backup if none has already happened within this time. Can be combined with an uptime-based schedule. - //RANGE = 0.5 - 500 - - private boolean uptimeSchedule; - //Whether the schedule is based off of server uptime (true) or world-time (false). - - private String schedule; - //A comma seperated schedule. About it. - - private String path; - //The path for backups. Defaults to ./backups. Can be absolute or relative. - //ANY STRING IS TESTED, WILL CREATE DIRECTORIES IF MISSING - - private Boolean silent; - //Whether to supress all information. Does not affect debug.log. - // TRUE OR FALSE - - private Boolean forceOnShutdown; - //Whether to build a backup when the server shuts down. - // TRUE OR FALSE - - private Boolean forceOnStartup; - //Whether to build a backup when the server starts up. - // TRUE OR FALSE - - //Startup backup delay, in seconds. - private long startupDelay; - - - //BELOW ONLY APPLIES TO ZIP FILES! (affects export command) - private int compressionLevel; - //The compression level to be passed to zip streams. - // RANGE = 1 - 9 - - - //BELOW ONLY APPLIES TO INCREMENTAL AND DIFFERENTIAL BACKUPS! - private int maxDepth; - //The maximum "depth" of partial backups to create before creating a full backup. Higher numbers are reccomended if using incremental. Lower numbers increase storage usage but reduce restoration times. - // RANGE = 5 - 500 - - private boolean compressChains; - //Whether to compress chains. Useful for size reduction and manual restoration. - // TRUE OR FALSE - - private boolean smartChains; - // Smart chain resetting. - // TRUE OR FALSE - - private int maxSizePercent; - // Resets chain length if what gets backed up is over the defined % size. - // 1-100 range. - - private boolean purgeIncrementals; - // Whether to purge incremental backups if over the limit. - // TRUE OR FALSE - - public Boolean getEnabled() { - return enabled; - } - - public void setEnabled(String enabled) { - this.enabled = Boolean.parseBoolean(enabled); - } - - public Boolean getSave() { - return save; - } - - public void setSave(String save) { - this.save = Boolean.parseBoolean(save); - } - - public Boolean getRequireActivity() { - return requireActivity; - } - - public void setRequireActivity(String requireActivity) { - this.requireActivity = Boolean.parseBoolean(requireActivity); - } - - public String getBackupType() { - return backupType; - } - - public void setBackupType(String backupType) { - this.backupType = backupType; - } - - public long getMaxSize() { - return maxSize; - } - - public void setMaxSize(String maxSize) { - this.maxSize = Long.parseLong(maxSize); - } - - public float getMinTimer() { - return minTimer; - } - - public void setMinTimer(String minTimer) { - this.minTimer = Float.parseFloat(minTimer); - } - - - public float getMaxTimer() { - return maxTimer; - } - - public void setUptimeSchedule(String uptimeSchedule) { - this.uptimeSchedule = Boolean.parseBoolean(uptimeSchedule); - } - - public boolean getUptimeSchedule() { - return uptimeSchedule; - } - - public void setSchedule(String schedule) { - this.schedule = schedule; - } - - public String getSchedule() { - return schedule; - } - - public void setMaxTimer(String maxTimer) { - this.maxTimer = Float.parseFloat(maxTimer); - } - - public String getPath() { - return path; - } - - public void setPath(String path) { - this.path = path; - } - - public Boolean getSilent() { - return silent; - } - - public void setSilent(String silent) { - this.silent = Boolean.parseBoolean(silent); - } - - public Boolean getForceOnShutdown() { - return forceOnShutdown; - } - - public void setForceOnShutdown(String forceOnShutdown) { - this.forceOnShutdown = Boolean.parseBoolean(forceOnShutdown); - } - - public Boolean getForceOnStartup() { - return forceOnStartup; - } - - public void setForceOnStartup(String forceOnStartup) { - this.forceOnStartup = Boolean.parseBoolean(forceOnStartup); - } - - public void setStartupDelay(String delay) { - this.startupDelay = Long.parseLong(delay); - } - - public long getStartupDelay() { - return startupDelay; - } - - public int getCompressionLevel() { - return compressionLevel; - } - - public void setCompressionLevel(String compressionLevel) { - this.compressionLevel = Integer.parseInt(compressionLevel); - } - - public int getMaxDepth() { - return maxDepth; - } - - public void setMaxDepth(String maxDepth) { - this.maxDepth = Integer.parseInt(maxDepth); - } - - public boolean getCompressChains() { - return compressChains; - } - - public void setCompressChains(String compressChains) { - this.compressChains = Boolean.parseBoolean(compressChains); - } - - public boolean getSmartChains() { - return smartChains; - } - - public void setSmartChains(String smartChains) { - this.smartChains = Boolean.parseBoolean(smartChains); - } - - - public boolean getPurgeIncrementals() { - return purgeIncrementals; - } - - public void setPurgeIncrementals(String purgeIncrementals) { - this.purgeIncrementals = Boolean.parseBoolean(purgeIncrementals); - } - - public int getMaxSizePercent() { - return maxSizePercent; - } - - public void setMaxSizePercent(String maxSizePercent) { - this.maxSizePercent = Integer.parseInt(maxSizePercent); - } - - - - - //default config output - can be ignored - public static String config(Object enabled, Object save, - Object activity, Object type, Object location, - Object size, Object min, Object max, - Object uptime, Object schedule, Object shutdown, - Object startup, Object delay, Object silent, - Object compression, Object chainLength, Object compressChains, - Object smartChains, Object maxPercent, Object purgeIncrementals) { - return String.join("\n", - -"#Enable or disable automatic backups.", -"#Options : true, false #Default : true,", -"config.advancedbackups.enabled=" + enabled, -"", -"#Whether to save before making a backup.", -"#Options : true, false #Default : false", -"config.advancedbackups.save=" + save, -"", -"#Whether to require player activity between backups.", -"#Options : true, false #Default : false", -"config.advancedbackups.activity=" + activity, -"", -"#The type of backups to use.", -"#Options : zip, differential, incremental #Default : differential", -"config.advancedbackups.type=" + type, -"", -"#The absolute or relative path to the backup location.", -"#Options : any file path. Default : ./backups", -"config.advancedbackups.path=" + location, -"", -"#The maximum size to keep, in GB. Keep relatively high for zips, tighter space requirements should instead use differential or incremental backups.", -"#Range : 5 - 9999 #Default : 50", -"config.advancedbackups.size=" + size, -"", -"#Minimum time between backups, in hours. This can prevent a shutdown backup from triggering immediately after a scheduled backup or similar situations.", -"#Range : 0.5 - 500 #Default : 0.5", -"config.advancedbackups.frequency.min=" + min, -"", -"#Triggers a backup if none has already happened within this time. Can be combined with an uptime-based schedule.", -"#Range : 0.5 - 500 #Default : 24", -"config.advancedbackups.frequency.max=" + max, -"", -"#Whether the schedule below uses uptime (true) or real-world time (false).", -"#Default : true", -"config.advancedbackups.frequency.uptime=" + uptime, -"", -"#When using server uptime:", -" #A looping comma-separated backup schedule, based off of server uptime, hours:minutes. Examples:", -" #4:00 - Makes a backup every four hours.", -" #4:00,7:00 - Makes a backup after four hours, then three, then four, and so on.", -" #1:00 - Makes a backup every hour.", -" #4:00,8:00,12:00,16:00,17:00,18:00,19:00,20:00,21:00,24:00 - Makes a backup following a strict schedule.", -"", -"#When using real-world time:", -" #A strict schedule, using hours:minutes to follow real-world time. Examples:", -" #4:00 - Makes a backup at 4am each day.", -" #4:00,8:00,12:00,16:00,17:00,18:00,19:00,20:00,21:00,24:00 - Makes a backup at specific times of day.", -"", -"#Default : 12:00", -"config.advancedbackups.frequency.schedule=" + schedule, -"", -"#Whether to force a backup on server shutdown. Respects min frequency.", -"#Options : true, false #Default : false", -"config.advancedbackups.frequency.shutdown=" + shutdown, -"", -"#Whether to force a backup on server startup. Respects min frequency.", -"#Options : true, false #Default : false", -"config.advancedbackups.frequency.startup=" + startup, -"", -"#Delay to use after startup, in seconds. Is always at least 5 seconds.", -"#Range : 5-9999999999", -"config.advancedbackups.frequency.delay=" + delay, -"", -"#Whether to disable console and chat logging. Does not affect debug.log, does not affect error messages.", -"#Options : true, false #Default : false", -"config.advancedbackups.logging.silent=" + silent, -"", -"", -"", -"#--------------------------------------------------------------------------------------------------------------------", -"##The following options only affect zip files, whether that's for zip backups, export commands or some other option.", -"#--------------------------------------------------------------------------------------------------------------------", -"", -"#The compression level to use for zip files. Higher numbers space usage, but decrease performance.", -"#Range : 1-9 #Default : 4", -"config.advancedbackups.zips.compression=" + compression, -"", -"", -"", -"#--------------------------------------------------------------------------------------------------------------------", -"##The following options only affect differential and incremental backups.", -"#--------------------------------------------------------------------------------------------------------------------", -"", -"#The maximum 'chain' length to keep.", -"#Range : 5-500 #Default : 50", -"config.advancedbackups.chains.length=" + chainLength, -"", -"#Whether to compress 'chains'. This compresses the base backup and all sequential backups. Reduces space usage, but decreases performance.", -"#Options : true, false #Default : true", -"config.advancedbackups.chains.compress=" + compressChains, -"", -"#Whether to enable \"smart\" reset for chains - if every file is being backed up, mark the backup as complete and reset chain length regardless of intended backup type.", -"#Options : true, false #Default : true", -"config.advancedbackups.chains.smart=" + smartChains, -"", -"#What % of a full backup is allowed to be contained in a partial before forcing it into a full backup. Useful for reducing partial backup size.", -"config.advancedbackups.chains.maxpercent=" + maxPercent, -"", -"#Whether to delete incremental backup chains if max size is exceeded. If not, incremental backups do not respect the max size config and never delete.", -"#Options : true, false #Default : false", -"config.advancedbackups.purge.incrementals=" + purgeIncrementals - - - ); - } - - public static String defaults() { - return config( - "true", "false", "false", - "differential", "./backups", "50", - "0.5", "24", "true", - "12:00", "false", "false", - "5", "false", "4", - "50", "true", "true", - "75","false"); - - } -} diff --git a/src/main/resources/assets/advanced-backups/icon.png b/src/main/resources/assets/advanced-backups/icon.png deleted file mode 100644 index 047b91f2347de5cf95f23284476fddbe21ba23fe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 453 zcmV;$0XqJPP)QAFYGys`80vegN0XDFh0OXKz&i8?Le#x7{1X)R+00000NkvXXu0mjf73i~T From ddd3d1bac76c1e58a7dd6eec0833c0aa87d59557 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Fri, 1 Sep 2023 17:55:16 +0100 Subject: [PATCH 222/580] Support the core separation stuff --- build.gradle | 5 +- .../advancedbackups/AdvancedBackups.java | 74 +- .../PlatformMethodWrapper.java | 67 -- .../cli/AdvancedBackupsCLI.java | 954 ------------------ .../core/CoreCommandSystem.java | 77 -- .../core/backups/BackupCheckEnum.java | 38 - .../core/backups/BackupTimingThread.java | 74 -- .../core/backups/BackupWrapper.java | 273 ----- .../core/backups/ThreadedBackup.java | 240 ----- .../backups/gson/DifferentialManifest.java | 73 -- .../advancedbackups/core/config/AVConfig.java | 165 --- .../core/config/ConfigData.java | 378 ------- 12 files changed, 72 insertions(+), 2346 deletions(-) delete mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/PlatformMethodWrapper.java delete mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java delete mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java delete mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupCheckEnum.java delete mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java delete mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java delete mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java delete mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/core/backups/gson/DifferentialManifest.java delete mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java delete mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java diff --git a/build.gradle b/build.gradle index e2761673..5a7e8b72 100644 --- a/build.gradle +++ b/build.gradle @@ -158,8 +158,9 @@ dependencies { // The userdev artifact is a special name and will get all sorts of transformations applied to it. minecraft 'net.minecraftforge:forge:1.18.2-40.2.1' //extraLibs 'com.sun.jna.platform:5.13.0' - implementation files('dependencies/jansi-2.4.0.jar') - extraLibs files('dependencies/jansi-2.4.0.jar') + + minecraftLibrary files ('../advancedbackups-corelib.jar') + extraLibs files ('../advancedbackups-corelib.jar') // Real mod deobf dependency examples - these get remapped to your current mappings // compileOnly fg.deobf("mezz.jei:jei-${mc_version}:${jei_version}:api") // Adds JEI API as a compile dependency diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 9d35e69e..30de3b24 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -2,12 +2,16 @@ import com.mojang.logging.LogUtils; +import co.uk.mommyheather.advancedbackups.core.ABCore; import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; -import co.uk.mommyheather.advancedbackups.core.config.AVConfig; +import co.uk.mommyheather.advancedbackups.core.config.ABConfig; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.storage.LevelResource; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.server.ServerLifecycleHooks; import net.minecraftforge.event.RegisterCommandsEvent; import net.minecraftforge.event.entity.player.PlayerEvent; import net.minecraftforge.event.server.ServerStartedEvent; @@ -39,10 +43,20 @@ public AdvancedBackups() public void onServerStarting(ServerStartingEvent event) { // Do something when the server starts - AVConfig.loadOrCreateConfig(); + ABConfig.loadOrCreateConfig(); LOGGER.info("Config loaded!!"); - PlatformMethodWrapper.worldName = event.getServer().getWorldData().getLevelName(); - PlatformMethodWrapper.worldDir = event.getServer().getWorldPath(LevelResource.ROOT); + ABCore.worldName = event.getServer().getWorldData().getLevelName(); + ABCore.worldDir = event.getServer().getWorldPath(LevelResource.ROOT); + + + ABCore.disableSaving = AdvancedBackups::disableSaving; + ABCore.enableSaving = AdvancedBackups::enableSaving; + ABCore.saveOnce = AdvancedBackups::saveOnce; + + ABCore.infoLogger = infoLogger; + ABCore.warningLogger = warningLogger; + ABCore.errorLogger = errorLogger; + } @@ -59,7 +73,7 @@ public void onServerStopping(ServerStoppingEvent event) { @SubscribeEvent public void onPlayerJoined(PlayerEvent.PlayerLoggedInEvent event) { - PlatformMethodWrapper.activity = true; + ABCore.activity = true; } @SubscribeEvent @@ -67,4 +81,54 @@ public void registerCommands(RegisterCommandsEvent event){ AdvancedBackupsCommand.register(event.getDispatcher()); } + + public static final String savesDisabledMessage = """ + + +*************************************** +SAVING DISABLED - PREPARING FOR BACKUP! +*************************************** +"""; + public static final String savesEnabledMessage = """ + + +********************************* +SAVING ENABLED - BACKUP COMPLETE! +********************************* +"""; + public static final String saveCompleteMessage = """ + + +************************************* +SAVE COMPLETE - PREPARING FOR BACKUP! +************************************* +"""; + + + public static void disableSaving() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + for (ServerLevel level : server.getAllLevels()) { + if (level != null && !level.noSave) { + level.noSave = true; + } + } + warningLogger.accept(savesDisabledMessage); + } + + public static void enableSaving() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + for (ServerLevel level : server.getAllLevels()) { + if (level != null && !level.noSave) { + level.noSave = false; + } + } + warningLogger.accept(savesEnabledMessage); + } + + public static void saveOnce() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + server.saveEverything(true, true, true); + warningLogger.accept(saveCompleteMessage); + } + } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/PlatformMethodWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/PlatformMethodWrapper.java deleted file mode 100644 index b47a0d95..00000000 --- a/src/main/java/co/uk/mommyheather/advancedbackups/PlatformMethodWrapper.java +++ /dev/null @@ -1,67 +0,0 @@ -package co.uk.mommyheather.advancedbackups; - -import java.nio.file.Path; -import java.util.function.Consumer; - -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ServerLevel; -import net.minecraftforge.server.ServerLifecycleHooks; - -public class PlatformMethodWrapper { - - public static String worldName = ""; - public static Path worldDir = null; - public static Boolean activity = false; - public static final Consumer infoLogger = AdvancedBackups.infoLogger; - public static final Consumer warningLogger = AdvancedBackups.warningLogger; - public static final Consumer errorLogger = AdvancedBackups.errorLogger; - - public static final String savesDisabledMessage = """ - - -*************************************** -SAVING DISABLED - PREPARING FOR BACKUP! -*************************************** -"""; - public static final String savesEnabledMessage = """ - - -********************************* -SAVING ENABLED - BACKUP COMPLETE! -********************************* -"""; - public static final String saveCompleteMessage = """ - - -************************************* -SAVE COMPLETE - PREPARING FOR BACKUP! -************************************* -"""; - - - public static void disableSaving() { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - for (ServerLevel level : server.getAllLevels()) { - if (level != null && !level.noSave) { - level.noSave = true; - } - } - warningLogger.accept(savesDisabledMessage); - } - - public static void enableSaving() { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - for (ServerLevel level : server.getAllLevels()) { - if (level != null && !level.noSave) { - level.noSave = false; - } - } - warningLogger.accept(savesEnabledMessage); - } - - public static void saveOnce() { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - server.saveEverything(true, true, true); - warningLogger.accept(saveCompleteMessage); - } -} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java deleted file mode 100644 index 5787b961..00000000 --- a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java +++ /dev/null @@ -1,954 +0,0 @@ -package co.uk.mommyheather.advancedbackups.cli; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.FileReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.nio.file.FileSystem; -import java.nio.file.FileSystems; -import java.nio.file.FileVisitResult; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.SimpleFileVisitor; -import java.nio.file.StandardCopyOption; -import java.nio.file.attribute.BasicFileAttributes; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.InputMismatchException; -import java.util.Properties; -import java.util.Scanner; -import java.util.regex.Pattern; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; -import java.util.zip.ZipInputStream; -import java.util.zip.ZipOutputStream; - -import org.fusesource.jansi.AnsiConsole; - -import co.uk.mommyheather.advancedbackups.core.backups.ThreadedBackup; - -public class AdvancedBackupsCLI { - - private static String backupLocation; - private static File serverDir = new File(new File("").toPath().toAbsolutePath().getParent().toString()); - private static String type; - private static Scanner input = new Scanner(System.in); - private static ArrayList fileNames = new ArrayList<>(); - private static File worldFile; - private static String worldPath; - public static void main(String args[]){ - - - System.out.print("\033[H\033[2J"); - System.out.flush(); - - if (System.console() != null) { - AnsiConsole.systemInstall(); //this gets ansi escape codes working on windows. this was a FUCKING PAIN IN MY ASS - } - - - info("Advanced Backups - Version " + AdvancedBackupsCLI.class.getPackage().getImplementationVersion()); - info("Searching for properties...", false); - - Properties props = new Properties(); - File file = new File(serverDir, "AdvancedBackups.properties"); - FileReader reader; - try { - reader = new FileReader(file); - props.load(reader); - - backupLocation = props.getProperty("config.advancedbackups.path"); - type = props.getProperty("config.advancedbackups.type"); - } catch (Exception e) { - error("ERROR LOADING PROPERTIES!"); - error(getStackTrace(e)); - error(""); - error(""); - error("Ensure you're running this from within the mods directory, and the config file is in the parent directory!"); - // Fatal, cannot proceed - return; - } - - if (backupLocation == null || type == null) { - error("ERROR LOADING PROPERTIES!"); - error("Backup location : " + backupLocation); - error("Type : " + type); - // Fatal, cannot proceed - return; - } - - info("Config loaded!"); - - type = getBackupType(); - - worldFile = getWorldFile(); - - if (!worldFile.exists()) { - error("Unable to find world folder!"); - error(worldFile.getAbsolutePath()); - error("Check if the location exists and the name is correct and try again."); - return; - - } - - - File backupDir; - - if (backupLocation.startsWith(Pattern.quote(File.separator))) { - backupDir = new File(backupLocation, File.separator + type + File.separator); - } - else { - backupDir = new File(serverDir, backupLocation.replaceAll(Pattern.quote("." + File.separator), "") + File.separator + type + File.separator); - } - - if (!backupDir.exists()) { - error("Could not find backup directory!"); - error(backupDir.getAbsolutePath()); - error("Have you made any backups before?"); - //Fatal, cannot continue - return; - } - - int backupDateIndex; - try { - backupDateIndex = getBackupDate(backupDir); - } catch (IOException e) { - error("ERROR VIEWING BACKUPS!"); - e.printStackTrace(); - return; - } - - - String restore = restoreWorldOrFile(); - - if (!confirmWarningMessage()) { - error("ABORTED - WILL NOT PROCEED."); - return; - } - - info("Preparing..."); - - - - switch(restore) { - case "world" : { - //No going back now! - //TODO : make a backup of current world state. - deleteEntireWorld(worldFile); - switch(type) { - case "zips" : { - restoreFullZip(backupDateIndex, worldFile); - return; - } - case "differential" : { - restoreFullDifferential(backupDateIndex, worldFile); - return; - } - case "incremental" : { - restoreFullIncremental(backupDateIndex, worldFile); - return; - } - } - } - case "file" : { - switch(type) { - case "zips" : { - restorePartialZip(backupDateIndex, worldFile); - return; - } - case "differential" : { - restorePartialDifferential(backupDateIndex, worldFile); - return; - } - case "incremental" : { - restorePartialIncremental(backupDateIndex, worldFile); - return; - } - } - } - } - - - } - - - - - - - - - - - - - - - - - - - //HELPER METHODS! - private static void info(String out, boolean line) { - if (line) System.out.println(out); - else System.out.print(out); - - } - - private static void warn(String out, boolean line) { - if (line) System.out.println("\u001B[33m" + out + "\u001B[0m"); - else System.out.print("\u001B[33m" + out + "\u001B[0m"); - - } - - private static void error(String out, boolean line) { - if (line) System.out.println("\u001B[31m" + out + "\u001B[0m"); - else System.out.print("\u001B[31m" + out + "\u001B[0m"); - - } - - private static void info(String out) { - info(out, true); - } - - private static void warn(String out) { - warn(out, true); - } - - private static void error(String out) { - error(out, true); - } - - - private static String getStackTrace(final Throwable throwable) { - final StringWriter sw = new StringWriter(); - final PrintWriter pw = new PrintWriter(sw, true); - throwable.printStackTrace(pw); - return sw.getBuffer().toString(); - } - - private static String getBackupType() { - // Select a type of backup to restore - info("Select a backup type to restore. Your server is currently set to use " + type + " backups."); - info("1: zip\n2: differential\n3: incremental"); - info("Enter a number or leave blank for " + type + "."); - int inputType; - try { - String line = input.nextLine(); - if (line == "") { - return type; - } - inputType = Integer.parseInt(line); - } catch (InputMismatchException | NumberFormatException e) { - warn("That was not a number. Please enter a number."); - return getBackupType(); - } - switch (inputType) { - case 1 : return "zips"; - case 2 : return "differential"; - case 3 : return "incremental"; - default : { - warn("Please pick an option between 1 and 3 inclusive."); - return getBackupType(); - } - } - } - - - private static File getWorldFile() { - info("Are you on a client or server?"); - info("1: Client\n2: Server"); - info("Enter a number."); - - int inputType; - File ret = new File(serverDir.getAbsolutePath()); - - try { - String line = input.nextLine(); - if (line == "") { - warn("Please enter a number."); - return getWorldFile(); - } - inputType = Integer.parseInt(line); - } catch (InputMismatchException | NumberFormatException e) { - warn("That was not a number. Please enter a number."); - return getWorldFile(); - } - - if (inputType < 1 || inputType > 2) { - warn("Please enter 1 or 2."); - return getWorldFile(); - } - - if (inputType == 1) { - ret = new File(ret, "/saves/"); - } - - ret = new File(ret, getWorldName(ret)); - return ret; - - } - - private static String getWorldName(File dir) { - ArrayList worlds = new ArrayList<>(); - int worldIndex; - for (File file : dir.listFiles()) { - boolean flag = false; - if (!file.isDirectory()) continue; - for (File file2 : file.listFiles()) { - if (file2.getName().contains("level.dat")) { - flag = true; - } - } - if (flag) { - worlds.add(file.getName()); - } - } - info("Please select your world. Default for servers is \"world\"."); - int index = 1; - for (String world : worlds) { - info (index + ". " + world); - index++; - } - try { - String line = input.nextLine(); - if (line == "") { - warn("Please enter a number."); - return getWorldName(dir); - } - worldIndex = Integer.parseInt(line); - } catch (InputMismatchException | NumberFormatException e) { - warn("That was not a number. Please enter a number."); - return getWorldName(dir); - } - if (worldIndex < 1 || worldIndex > worlds.size()) { - warn("Please enter a number between " + worlds.size() + "."); - return getWorldName(dir); - } - - worldPath = worlds.get(worldIndex -1).replaceAll(" ", "_"); - return worlds.get(worldIndex - 1); - - } - - - private static int getBackupDate(File backupDir) throws IOException { - fileNames.clear(); - int inputType; - - info("Select a backup to restore."); - - for (File file : backupDir.listFiles()) { - if (!file.getName().contains(worldPath)) continue; - fileNames.add(file.getAbsolutePath()); - String out = file.getName(); - out = out.replaceAll(".zip", ""); - out = out.replaceAll(worldPath + "_", ": "); - out = out.replaceAll("-partial", "\u001B[33m partial\u001B[0m"); - out = out.replaceAll("-full", "\u001B[32m full\u001B[0m"); - info(fileNames.size() + out); - } - - try { - String line = input.nextLine(); - if (line == "") { - warn("Please enter a number."); - return getBackupDate(backupDir); - } - inputType = Integer.parseInt(line); - } catch (InputMismatchException | NumberFormatException e) { - warn("That was not a number. Please enter a number."); - return getBackupDate(backupDir); - } - - if (inputType < 1 || inputType > fileNames.size()) { - warn("Please enter a number between " + fileNames.size() + "."); - return getBackupDate(backupDir); - } - - return inputType - 1; - } - - private static String restoreWorldOrFile() { - info("Do you want to restore the entire world state at this point, or a singular file?"); - info("1: Entire world\n2: Single file"); - info("Enter a number."); - int inputType; - try { - String line = input.nextLine(); - if (line == "") { - return type; - } - inputType = Integer.parseInt(line); - } catch (InputMismatchException | NumberFormatException e) { - warn("That was not a number. Please enter a number."); - return restoreWorldOrFile(); - } - switch (inputType) { - case 1 : return "world"; - case 2 : return "file"; - default : { - warn("Please pick 1 or 2."); - return restoreWorldOrFile(); - } - } - - } - - - - private static boolean confirmWarningMessage() { - warn(""); - warn(""); - warn("WARNING! DOING THIS WHILST THE SERVER IS RUNNING CAN CAUSE SEVERE CORRUPTION, PARTIAL RESTORATION, AND OTHER ISSUES."); - warn("TYPE \"continue\" IF YOU WISH TO CONTINUE...", false); - - - String line = input.nextLine(); - if (line.equals("")) { - return confirmWarningMessage(); - } - return line.equals("continue"); - } - - - private static void restoreFullZip(int index, File worldFile) { - byte[] buffer = new byte[1024]; - //The most basic of the bunch. - ZipEntry entry; - try { - FileInputStream fileInputStream = new FileInputStream(fileNames.get(index)); - ZipInputStream zip = new ZipInputStream(fileInputStream); - while ((entry = zip.getNextEntry()) != null) { - File outputFile; - - //FTB Backups and some other mods need special handling. - if (entry.getName().startsWith(worldFile.getName())) { - outputFile = new File(worldFile.getParentFile(), entry.getName()); - } - else { - outputFile = new File(worldFile, entry.getName()); - } - - if (!outputFile.getParentFile().exists()) { - outputFile.getParentFile().mkdirs(); - } - - FileOutputStream outputStream = new FileOutputStream(outputFile); - int length = 0; - while ((length = zip.read(buffer)) > 0) { - outputStream.write(buffer, 0, length); - } - outputStream.close(); - } - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - - private static void restoreFullDifferential(int index, File worldFile) { - //Do we need to check for past backups? if selected is a full backup, we do not. - File backup = new File(fileNames.get(index)); - if (backup.getName().contains("-full")) { - if (backup.isFile()) { - restoreFullZip(index, worldFile); - return; - } - restoreFolder(index, worldFile); - return; - } - //find last FULL backup - for (int i = index;i>0;i--) { - String name = fileNames.get(i); - if (name.contains("-full")) { - info("Restoring last full backup..."); - File file = new File(name); - if (file.isFile()) { - restoreFullZip(i, worldFile); - } - else { - restoreFolder(i, worldFile); - } - break; - } - } - info("\n\nRestoring selected backup..."); - if (backup.isFile()) { - restoreFullZip(index, worldFile); - } - else { - restoreFolder(index, worldFile); - } - } - - private static void restoreFullIncremental(int index, File worldFile) { - //Do we need to check for past backups? if selected is a full backup, we do not. - File backup = new File(fileNames.get(index)); - if (backup.getName().contains("-full")) { - if (backup.isFile()) { - restoreFullZip(index, worldFile); - return; - } - restoreFolder(index, worldFile); - return; - } - //find last FULL backup - int i = index; - while(i >= 0) { - String name = fileNames.get(i); - if (name.contains("-full")) { - info("Restoring last full backup..."); - File file = new File(name); - if (file.isFile()) { - restoreFullZip(i, worldFile); - } - else { - restoreFolder(i, worldFile); - } - break; - } - i--; - } - //restore backups up until the selected one - while(i < index) { - String name = fileNames.get(i); - info("Restoring chained backup..."); - File file = new File(name); - if (file.isFile()) { - restoreFullZip(i, worldFile); - } - else { - restoreFolder(i, worldFile); - } - i++; - } - - - info("\n\nRestoring selected backup..."); - if (backup.isFile()) { - restoreFullZip(index, worldFile); - } - else { - restoreFolder(index, worldFile); - } - } - - private static void restorePartialZip(int index, File worldFile) { - Path file; - HashMap entries = new HashMap<>(); - - try { - FileSystem zipFs = FileSystems.newFileSystem(new File(fileNames.get(index)).toPath(), AdvancedBackupsCLI.class.getClassLoader()); - Path root = zipFs.getPath(""); - Files.walkFileTree(root, new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) throws IOException { - entries.put(file.toString(), file); - return FileVisitResult.CONTINUE; - } - }); - - file = getFileToRestore(entries, ""); - info("Restoring " + file.toString() + "..."); - Path outputFile = new File(worldFile, file.toString()).toPath(); - Files.copy(file, outputFile, StandardCopyOption.REPLACE_EXISTING); - info("Done."); - - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - return; - } - - } - - private static void restorePartialDifferential(int index, File worldFile) { - //Do we need to check for past backups? if selected is a full backup, we do not. - HashMap filePaths = new HashMap<>(); - HashMap dates = new HashMap<>(); - HashMap entryOwners = new HashMap<>(); - try { - File backup = new File(fileNames.get(index)); - if (!backup.getName().contains("-full")) { - //find last FULL backup - for (int i = index;i>=0;i--) { - String name = fileNames.get(i); - if (name.contains("-full")) { - addBackupNamesToLists(new File(name), entryOwners, filePaths, dates, "\u001b[31m"); - break; - } - } - } - - File file = new File(fileNames.get(index)); - addBackupNamesToLists(file, entryOwners, filePaths, dates, "\u001B[32m"); - - HashMap properMapping = new HashMap<>(); - for (String date : dates.keySet()) { - properMapping.put( - date + " " + dates.get(date), - filePaths.get(date) - ); - } - - Object select = getFileToRestore(properMapping, ""); - if (select instanceof Path) { - Path input = (Path) select; - - - if (select.toString().replace("\\", "/").contains("-full/")) { - select = new File( - select.toString().replace("\\", "/") - .split("-full/")[1] - ).toPath(); - } - if (select.toString().replace("\\", "/").contains("-partial/")) { - select = new File( - select.toString().replace("\\", "/") - .split("-partial/")[1] - ).toPath(); - } - - File outputFile = new File(worldFile, select.toString()); - if (!outputFile.getParentFile().exists()) { - outputFile.getParentFile().mkdirs(); - } - info("\n\nRestoring file : " + select); - Files.copy(input, outputFile.toPath(), StandardCopyOption.REPLACE_EXISTING); - } - else if (select instanceof ZipEntry) { - ZipEntry entry = (ZipEntry) select; - - File outputFile = new File(worldFile, entry.toString()); - FileOutputStream outputStream = new FileOutputStream(outputFile); - - info("Restoring " + entry.toString() + "..."); - - byte[] buffer = new byte[1028]; - InputStream inputSteam = entryOwners.get(entry.toString()).getInputStream(entry); - int length; - while ((length = inputSteam.read(buffer, 0, buffer.length)) > 0) { - outputStream.write(buffer, 0, length); - } - outputStream.flush(); - outputStream.close(); - } - - - } - catch (IOException e){ - //TODO : Scream at user - e.printStackTrace(); - } - } - - private static void restorePartialIncremental(int index, File worldFile) { - //Do we need to check for past backups? if selected is a full backup, we do not. - HashMap filePaths = new HashMap<>(); - HashMap dates = new HashMap<>(); - HashMap entryOwners = new HashMap<>(); - try { - File backup = new File(fileNames.get(index)); - if (!backup.getName().contains("-full")) { - int i; - //find last FULL backup - for (i = index;i>=0;i--) { - String name = fileNames.get(i); - if (name.contains("-full")) { - addBackupNamesToLists(new File(name), entryOwners, filePaths, dates, "\u001b[31m"); - break; - } - } - while (i < index) { - String name = fileNames.get(i); - addBackupNamesToLists(new File(name), entryOwners, filePaths, dates, "\u001b[31m"); - i++; - } - - } - - File file = new File(fileNames.get(index)); - addBackupNamesToLists(file, entryOwners, filePaths, dates, "\u001B[32m"); - - HashMap properMapping = new HashMap<>(); - for (String date : dates.keySet()) { - properMapping.put( - date + " " + dates.get(date), - filePaths.get(date) - ); - } - - Object select = getFileToRestore(properMapping, ""); - if (select instanceof Path) { - Path input = (Path) select; - - - if (select.toString().replace("\\", "/").contains("-full/")) { - select = new File( - select.toString().replace("\\", "/") - .split("-full/")[1] - ).toPath(); - } - if (select.toString().replace("\\", "/").contains("-partial/")) { - select = new File( - select.toString().replace("\\", "/") - .split("-partial/")[1] - ).toPath(); - } - - File outputFile = new File(worldFile, select.toString()); - if (!outputFile.getParentFile().exists()) { - outputFile.getParentFile().mkdirs(); - } - info("\n\nRestoring file : " + select); - Files.copy(input, outputFile.toPath(), StandardCopyOption.REPLACE_EXISTING); - } - else if (select instanceof ZipEntry) { - ZipEntry entry = (ZipEntry) select; - - File outputFile = new File(worldFile, entry.toString()); - FileOutputStream outputStream = new FileOutputStream(outputFile); - - info("Restoring " + entry.toString() + "..."); - - byte[] buffer = new byte[1028]; - InputStream inputSteam = entryOwners.get(entry.toString()).getInputStream(entry); - int length; - while ((length = inputSteam.read(buffer, 0, buffer.length)) > 0) { - outputStream.write(buffer, 0, length); - } - outputStream.flush(); - outputStream.close(); - } - - - } - catch (IOException e){ - //TODO : Scream at user - e.printStackTrace(); - } - } - - - private static void restoreFolder(int index, File worldFile) { - File backup = new File(fileNames.get(index)); - - try { - Files.walkFileTree(backup.toPath(), new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) throws IOException { - File source = backup.toPath().relativize(file).toFile(); - File outputFile = new File(worldFile, source.getPath()); - - if (!outputFile.getParentFile().exists()) { - outputFile.getParentFile().mkdirs(); - } - Files.copy(file, outputFile.toPath()); - return FileVisitResult.CONTINUE; - } - }); - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - - - private static void deleteEntireWorld(File worldDir) { - backupExistingWorld(worldDir); - try { - Files.walkFileTree(worldDir.toPath(), new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { - file.toFile().delete(); - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult postVisitDirectory(Path file, java.io.IOException arg1) { - if (file.toFile().listFiles().length == 0) { - file.toFile().delete(); - } - return FileVisitResult.CONTINUE; - } - }); - } catch (IOException e) { - warn("Failed to delete file :"); - e.printStackTrace(); - } - } - - private static void backupExistingWorld(File worldDir) { - try { - File out = new File(worldDir, "../cli" + ThreadedBackup.serialiseBackupName("backup") + ".zip"); - FileOutputStream outputStream = new FileOutputStream(out); - ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream); - zipOutputStream.setLevel(4); - Files.walkFileTree(worldDir.toPath(), new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { - Path targetFile; - try { - targetFile = worldDir.toPath().relativize(file); - if (targetFile.toFile().getName().compareTo("session.lock") == 0) { - return FileVisitResult.CONTINUE; - } - zipOutputStream.putNextEntry(new ZipEntry(targetFile.toString())); - byte[] bytes = Files.readAllBytes(file); - zipOutputStream.write(bytes, 0, bytes.length); - zipOutputStream.closeEntry(); - - } catch (IOException e) { - // TODO : Scream at user - e.printStackTrace(); - } - - return FileVisitResult.CONTINUE; - } - }); - zipOutputStream.flush(); - zipOutputStream.close(); - } catch (Exception e) { - - } - } - - - private static T getFileToRestore(HashMap files, String directory) { - ArrayList toDisplay = new ArrayList<>(); - HashMap keyMap = new HashMap<>(); - int index = 1; - for (String name : files.keySet()) { - String name2 = name.replace("\\", "/"); // this replacement can fix some problems with wsl, and helps keep code neat. - if (name2.contains(directory)) { - name2 = name2.replace(directory, ""); - if (name2.startsWith(worldFile.getName())) { - name2 = name2.replace(worldFile.getName() + "/", ""); - } - if (name2.contains("/")) { - name2 = "\u001B[33mdirectory\u001B[0m " + name2.split("/")[0]; - } - if (!toDisplay.contains(name2)) { - toDisplay.add(name2); - keyMap.put(name2, name); - } - } - } - toDisplay = sortStringsAlphabeticallyWithDirectoryPriority(toDisplay); - info("Choose a file to restore.\n"); - for (String name : toDisplay) { - if (index < 10) { - info(index + ": " + name); - } - else { - info(index + ": " + name); - } - index++; - } - if (!directory.equals("")) { - info(index + ": ../"); - } - - - int userInput; - try { - String line = input.nextLine(); - if (line == "") { - warn("Please enter a number!"); - return getFileToRestore(files, directory); - } - userInput = Integer.parseInt(line); - } catch (InputMismatchException | NumberFormatException e) { - warn("That was not a number. Please enter a number."); - return getFileToRestore(files, directory); - } - - if (userInput <= 0 || userInput > (directory.equals("") ? toDisplay.size() : toDisplay.size() + 1)) { - warn("Please enter a number in the specified range!"); - return getFileToRestore(files, directory); - } - else if (userInput > toDisplay.size()) { - return null; - } - else if (!toDisplay.get(userInput - 1).contains("\u001B[33mdirectory\u001B[0m ")) { - return files.get(keyMap.get(toDisplay.get(userInput -1))); - } - - T result = getFileToRestore(files, directory + toDisplay.get(userInput -1).replace("\u001B[33mdirectory\u001B[0m ", "") + "/"); - if (result != null) { - return result; - } - else { - return getFileToRestore(files, directory); - } - } - - - private static ArrayList sortStringsAlphabeticallyWithDirectoryPriority(ArrayList in) { - ArrayList out = new ArrayList<>(); - Collections.sort(in); - for (String string : in) { - if (string.contains("\u001B[33mdirectory\u001B[0m")) { - out.add(string); - } - } - for (String string : in) { - if (!string.contains("\u001B[33mdirectory\u001B[0m")) { - out.add(string); - } - } - return out; - } - - - private static void addBackupNamesToLists(File file, HashMap entryOwners, HashMap filePaths, - HashMap dates, String colour) throws IOException { - - if (file.isFile()) { - - ZipFile zipFile = new ZipFile(file); - Enumeration entryEnum = zipFile.entries(); - - while (entryEnum.hasMoreElements()) { - ZipEntry entry = entryEnum.nextElement(); - - String backupName = file.toString().replace("\\", "/"); - filePaths.put(entry.toString().replace("\\", "/"), entry); - dates.put(entry.toString().replace("\\", "/"), "\u001b[31m" - + backupName - .substring(backupName.toString().lastIndexOf("/") + 1) - .replace(worldPath + "_", "") - .replace("-full.zip", "") - .replace("-partial.zip", "") - + "\u001B[0m"); - entryOwners.put(entry.toString(), zipFile); - } - } - - else { - Files.walkFileTree(file.toPath(), new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path path, BasicFileAttributes attributes) throws IOException { - String backupName = file.toString().replace("\\", "/"); - filePaths.put(file.toPath().relativize(path).toString().replace("\\", "/"), path); - dates.put(file.toPath().relativize(path).toString().replace("\\", "/"), "\u001b[31m" - + backupName - .substring(backupName.toString().lastIndexOf("/") + 1) - .replace(worldPath + "_", "") - .replace("-full", "") - .replace("-partial", "") - + "\u001B[0m"); - return FileVisitResult.CONTINUE; - } - }); - } - } - -} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java deleted file mode 100644 index 76e59aef..00000000 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java +++ /dev/null @@ -1,77 +0,0 @@ -package co.uk.mommyheather.advancedbackups.core; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileWriter; -import java.nio.file.Files; -import java.util.function.Consumer; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; - -import co.uk.mommyheather.advancedbackups.core.backups.BackupCheckEnum; -import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; -import co.uk.mommyheather.advancedbackups.core.backups.gson.DifferentialManifest; -import co.uk.mommyheather.advancedbackups.core.config.AVConfig; - -public class CoreCommandSystem { - private static GsonBuilder builder = new GsonBuilder(); - private static Gson gson; - static { - builder.setPrettyPrinting(); - gson = builder.create(); - } - - - //These methods are all called by relevant command classes in version specific code - public static void checkBackups(Consumer chat) { - BackupCheckEnum check = BackupWrapper.checkBackups(); - chat.accept(check.getCheckMessage()); - } - - public static void startBackup(Consumer chat) { - BackupCheckEnum check = BackupWrapper.checkBackups(); - chat.accept(check.getCheckMessage()); - if (check.success()) { - chat.accept("Starting backup..."); - BackupWrapper.makeSingleBackup(0); - } - } - - public static void forceBackup(Consumer chat) { - chat.accept("Forcing a backup..."); - BackupWrapper.makeSingleBackup(0); - } - - public static void reloadConfig(Consumer chat) { - chat.accept("Reloading config..."); - AVConfig.loadConfig(); - chat.accept("Done!"); - } - - public static void resetChainLength(Consumer chat) { - chat.accept("Resetting chain length... The next backup will be a complete backup."); - boolean differential = AVConfig.config.getBackupType().equals("differential") ? true : false; - File manifestFile = differential ? new File(AVConfig.config.getPath() + "/differential/manifest.json") : new File(AVConfig.config.getPath() + "/incremental/manifest.json"); - DifferentialManifest manifest; - try { - if (manifestFile.exists()) { - manifest = gson.fromJson(new String(Files.readAllBytes(manifestFile.toPath())), DifferentialManifest.class); - manifest.setChain(manifest.getChain() + AVConfig.config.getMaxDepth()); - FileWriter writer = new FileWriter(manifestFile); - writer.write(gson.toJson(manifest)); - writer.flush(); - writer.close(); - chat.accept("Done!"); - return; - } - else { - chat.accept("No manifest file exists!"); - return; - } - } catch (Exception e) { - chat.accept("Error resetting chain length. - check logs for more info."); - e.printStackTrace(); - } - } -} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupCheckEnum.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupCheckEnum.java deleted file mode 100644 index 06e00e14..00000000 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupCheckEnum.java +++ /dev/null @@ -1,38 +0,0 @@ -package co.uk.mommyheather.advancedbackups.core.backups; - -public enum BackupCheckEnum { - SUCCESS, - DISABLED, - NOACTIVITY, - TOORECENT; - - public boolean success() { - switch (this) { - case SUCCESS: { - return true; - } - default : return false; - } - } - - - public String getCheckMessage() { - switch(this) { - case SUCCESS : { - return "Checks successful!"; - } - case DISABLED : { - return "Backups are disabled!"; - } - case NOACTIVITY : { - return "Player activity is required, but none have been active!"; - } - case TOORECENT : { - return "The time since the last backup is less than the minimum time specified in config!"; - } - default : { - return "You should not see this message, report a bug!"; - } - } - } -} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java deleted file mode 100644 index b346e89c..00000000 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java +++ /dev/null @@ -1,74 +0,0 @@ -package co.uk.mommyheather.advancedbackups.core.backups; - -import java.time.LocalDateTime; -import java.util.ArrayList; - -import co.uk.mommyheather.advancedbackups.core.config.AVConfig; - -public class BackupTimingThread extends Thread { - private int loops = 0; - private int index = 0; - private long prev = 0; - - public BackupTimingThread() { - setName("AB Backup Timing Daemon"); - setDaemon(true); - } - - @Override - public void run() { - while (true) { - try { - long time = calculateNextBackupTime(); - sleep(time); - BackupWrapper.checkAndMakeBackups(); - } catch (InterruptedException e) { - // TODO Scream at user - e.printStackTrace(); - break; - } - } - } - - - private long calculateNextBackupTime() { - long forcedMillis = BackupWrapper.mostRecentBackupTime() + (long) (AVConfig.config.getMaxTimer() * 3600000L); - if (forcedMillis == AVConfig.config.getMaxTimer() * 3600000L || forcedMillis <= System.currentTimeMillis()) forcedMillis = 300000; //sets it to 5m if no backup exists or the timer is already execeeded to get the chain going - else forcedMillis -= System.currentTimeMillis(); - long ret = Long.MAX_VALUE; - if (AVConfig.config.getUptimeSchedule() && !BackupWrapper.configuredPlaytime.isEmpty()) { - ArrayList timings = new ArrayList(BackupWrapper.configuredPlaytime); - if (index >= timings.size()) { - index = 0; - loops++; - } - ret = (timings.get(index) + (timings.get(timings.size() - 1) * loops)); - ret -= prev; - prev += ret; - index++; - } - - else if (!BackupWrapper.configuredPlaytime.isEmpty()) { - long nextTime = 0; - long currentTime = System.currentTimeMillis(); - ArrayList timings = new ArrayList(BackupWrapper.configuredPlaytime); - for (long time : timings) { - if (time >= currentTime) { - nextTime = time; - break; - } - } - ret = nextTime >= currentTime ? nextTime - currentTime : 86640000 - currentTime; - } - - return Math.min(forcedMillis, ret); - - - - - - - } - - -} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java deleted file mode 100644 index f5960e0d..00000000 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java +++ /dev/null @@ -1,273 +0,0 @@ -package co.uk.mommyheather.advancedbackups.core.backups; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.FileWriter; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.StringReader; -import java.util.ArrayList; -import java.util.Date; - - -import co.uk.mommyheather.advancedbackups.PlatformMethodWrapper; -import co.uk.mommyheather.advancedbackups.core.config.AVConfig; - -public class BackupWrapper { - - public static ArrayList configuredPlaytime = new ArrayList<>(); - - - public static void checkStartupBackups () { - if (AVConfig.config.getForceOnStartup()) { - checkAndMakeBackups(Math.max(5000, AVConfig.config.getStartupDelay() * 1000)); - } - - new BackupTimingThread().start(); - } - - public static void checkShutdownBackups() { - if (AVConfig.config.getForceOnShutdown()) { - checkAndMakeBackups(); - } - } - - public static void checkAndMakeBackups(long delay) { - BackupCheckEnum e = checkBackups(); - if (e.success()) { - makeSingleBackup(delay); - } - } - - public static void checkAndMakeBackups() { - checkAndMakeBackups(0); - } - - - public static BackupCheckEnum checkBackups() { - prepareBackupDestination(); - if (!AVConfig.config.getEnabled()) return BackupCheckEnum.DISABLED; - if (AVConfig.config.getRequireActivity() && !PlatformMethodWrapper.activity) return BackupCheckEnum.NOACTIVITY; - if (checkMostRecentBackup()) return BackupCheckEnum.TOORECENT; - - return BackupCheckEnum.SUCCESS; - - } - - private static void prepareBackupDestination() { - File file = new File(AVConfig.config.getPath()); - - if (!file.exists()) { - file.mkdirs(); - } - prepareReadMe(file); - - File zipFile = new File(file, "/zips/"); - if (!zipFile.exists()) { - zipFile.mkdirs(); - } - File differential = new File(file, "/differential/"); - if (!differential.exists()) { - differential.mkdirs(); - } - File incremental = new File(file, "/incremental/"); - if (!incremental.exists()) { - incremental.mkdirs(); - } - } - - private static void prepareReadMe(File path) { - File readme = new File(path, "README-BEFORE-RESTORING.txt"); - if (!readme.exists()) { - try { - InputStream is = BackupWrapper.class.getClassLoader().getResourceAsStream("advancedbackups-readme.txt"); - readme.createNewFile(); - FileOutputStream outputStream = new FileOutputStream(readme); - byte[] buf = new byte[1028]; - int n; - while ((n = is.read(buf)) > 0) { - outputStream.write(buf, 0, n); - } - outputStream.flush(); - outputStream.close(); - - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - - } - } - - - public static boolean checkMostRecentBackup() { - // Return true if the time difference between the most recent backup and the backup-to-be - // is less than specified in the config. - - Date date = new Date(); - long configVal = (long) (3600000F * AVConfig.config.getMinTimer()); - return (date.getTime() - mostRecentBackupTime()) < configVal; - } - - - public static long mostRecentBackupTime() { - - File directory = new File(AVConfig.config.getPath()); - - switch(AVConfig.config.getBackupType()) { - case "zip" : { - directory = new File(directory, "/zips/"); - break; - } - case "differential" : { - directory = new File(directory, "/differential/"); - break; - } - case "incremental" : { - directory = new File(directory, "/incremental/"); - break; - } - - } - - File[] files = directory.listFiles(); - long lastModifiedTime = Long.MIN_VALUE; - if (files == null || files.length == 0) return 0L; - for (File file : files) { - if (file.lastModified() > lastModifiedTime && !file.getName().contains("manifest")) { - lastModifiedTime = file.lastModified(); - } - } - return lastModifiedTime; - } - - - public static void makeSingleBackup(long delay) { - - PlatformMethodWrapper.disableSaving(); - if (AVConfig.config.getSave()) { - PlatformMethodWrapper.saveOnce(); - } - - // Make new thread, run backup utility. - ThreadedBackup threadedBackup = new ThreadedBackup(delay); - threadedBackup.start(); - // Don't re-enable saving - leave that down to the backup thread. - - } - - public static void finishBackup() { - File directory = new File(AVConfig.config.getPath()); - ThreadedBackup.running = false; - PlatformMethodWrapper.enableSaving(); - - switch(AVConfig.config.getBackupType()) { - case "zip" : { - directory = new File(directory, "/zips/"); - long date = Long.MIN_VALUE; - while (true) { - if (calculateDirectorySize(directory) < AVConfig.config.getMaxSize() * 1000000000L) return; - File file = getFirstBackupAfterDate(directory, date); - date = file.lastModified(); - file.delete(); - } - } - case "differential" : { - directory = new File(directory, "/differential/"); - long date = Long.MIN_VALUE; - while (true) { - if (calculateDirectorySize(directory) < AVConfig.config.getMaxSize() * 1000000000L) return; - File file = getFirstBackupAfterDate(directory, date); - date = file.lastModified(); - if (file.getName().contains("full")) { - File nextFile = getFirstBackupAfterDate(directory, date); - if (nextFile.getName().contains("partial")) { - nextFile.delete(); - } - else { - file.delete(); - } - } - else { - file.delete(); - } - - } - } - case "incremental" : { - directory = new File(directory, "/incremental/"); - if (!AVConfig.config.getPurgeIncrementals()) return; - long date = Long.MIN_VALUE; - while (true) { - if (calculateDirectorySize(directory) < AVConfig.config.getMaxSize() * 1000000000L) return; - if (calculateChainCount(directory) < 2) return; - PlatformMethodWrapper.errorLogger.accept("Purging incremental backup chain - too much space taken up!"); - File file = getFirstBackupAfterDate(directory, date); - date = file.lastModified(); - if (file.getName().contains("full")) { - file.delete(); - while (true) { - file = getFirstBackupAfterDate(directory, date); - date = file.lastModified(); - if (file.getName().contains("full")) { - file.delete(); - } - else { - break; - } - } - } - else { - file.delete(); - } - - } - } - - } - } - - - public static long calculateDirectorySize(File directory) { - long size = 0; - File[] files = directory.listFiles(); - if (files == null || files.length == 0) return size; - for (File file : files) { - if (file.isFile()) { - size += file.length(); - } - else { - size += calculateDirectorySize(file); - } - } - return size; - } - - public static File getFirstBackupAfterDate(File directory, long date) { - File[] files = directory.listFiles(); - File oldestFile = null; - long currentDate = Long.MAX_VALUE; - if (files == null || files.length == 0) return null; - for (File file : files) { - if (file.lastModified() < currentDate && file.lastModified() > date) { - currentDate = file.lastModified(); - oldestFile = file; - } - } - - return oldestFile; - } - - public static int calculateChainCount(File directory) { - int count = 0; - File[] files = directory.listFiles(); - if (files == null || files.length == 0) return 0; - for (File file : files) { - if (file.getName().contains("full")) { - count++; - } - } - return count; - } -} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java deleted file mode 100644 index b331c31b..00000000 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java +++ /dev/null @@ -1,240 +0,0 @@ -package co.uk.mommyheather.advancedbackups.core.backups; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.FileWriter; -import java.io.IOException; -import java.nio.file.FileVisitResult; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.SimpleFileVisitor; -import java.nio.file.attribute.BasicFileAttributes; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Date; -import java.util.zip.ZipEntry; -import java.util.zip.ZipOutputStream; - - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; - -import co.uk.mommyheather.advancedbackups.PlatformMethodWrapper; -import co.uk.mommyheather.advancedbackups.core.backups.gson.DifferentialManifest; -import co.uk.mommyheather.advancedbackups.core.config.AVConfig; - -public class ThreadedBackup extends Thread { - private static GsonBuilder builder = new GsonBuilder(); - private static Gson gson; - private long delay; - private static int count; - private static float partialSize; - private static float completeSize; - public static boolean running = false; - private static String backupName; - - static { - builder.setPrettyPrinting(); - gson = builder.create(); - } - - public ThreadedBackup(long delay) { - setName("AB Active Backup Thread"); - this.delay = delay; - count = 0; - partialSize = 0F; - completeSize = 0F; - } - - @Override - public void run() { - try { - sleep(delay); - } catch (InterruptedException e) { - return; - } - if (running) { - return; - } - running = true; - - File file = new File(AVConfig.config.getPath()); - backupName = serialiseBackupName(PlatformMethodWrapper.worldDir.getParent().toFile().getName().replaceAll(" ", "_")); - - switch(AVConfig.config.getBackupType()) { - case "zip" : { - makeZipBackup(file); - break; - } - case "differential" : { - makeDifferentialOrIncrementalBackup(file, true); - break; - } - case "incremental" : { - makeDifferentialOrIncrementalBackup(file, false); - break; - } - } - - BackupWrapper.finishBackup(); - } - - - private static void makeZipBackup(File file) { - try { - - File zip = new File(file.toString() + "/zips/", backupName + ".zip"); - PlatformMethodWrapper.infoLogger.accept("Preparing zip backup name: " + zip.getName()); - FileOutputStream outputStream = new FileOutputStream(zip); - ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream); - zipOutputStream.setLevel(AVConfig.config.getCompressionLevel()); - - Files.walkFileTree(PlatformMethodWrapper.worldDir, new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { - Path targetFile; - try { - targetFile = PlatformMethodWrapper.worldDir.relativize(file); - if (targetFile.toFile().getName().compareTo("session.lock") == 0) { - return FileVisitResult.CONTINUE; - } - zipOutputStream.putNextEntry(new ZipEntry(targetFile.toString())); - byte[] bytes = Files.readAllBytes(file); - zipOutputStream.write(bytes, 0, bytes.length); - zipOutputStream.closeEntry(); - - } catch (IOException e) { - // TODO : Scream at user - e.printStackTrace(); - PlatformMethodWrapper.errorLogger.accept(file.toString()); - } - - return FileVisitResult.CONTINUE; - } - }); - zipOutputStream.flush(); - zipOutputStream.close(); - - } catch (IOException e){ - // TODO : Scream at user - e.printStackTrace(); - } - - } - - - private static void makeDifferentialOrIncrementalBackup(File location, boolean differential) { - try { - PlatformMethodWrapper.infoLogger.accept("Preparing " + (differential ? "differential" : "incremental") + " backup name: " + backupName); - long time = 0; - File manifestFile = differential ? new File(location.toString() + "/differential/manifest.json") : new File(location.toString() + "/incremental/manifest.json"); - DifferentialManifest manifest; - if (manifestFile.exists()) { - manifest = gson.fromJson(new String(Files.readAllBytes(manifestFile.toPath())), DifferentialManifest.class); - } - else { - manifest = DifferentialManifest.defaultValues(); - } - - long comp = differential ? manifest.getLastFull() : manifest.getLastPartial(); - ArrayList toBackup = new ArrayList<>(); - ArrayList completeBackup = new ArrayList<>(); - - - boolean completeTemp = manifest.getComplete().size() == 0 || manifest.getChain() >= AVConfig.config.getMaxDepth() ? true : false; - - Files.walkFileTree(PlatformMethodWrapper.worldDir, new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { - Path targetFile; - targetFile = PlatformMethodWrapper.worldDir.relativize(file); - if (targetFile.toFile().getName().compareTo("session.lock") == 0) { - return FileVisitResult.CONTINUE; - } - count++; - completeSize += attributes.size(); - completeBackup.add(targetFile); - if (completeTemp || attributes.lastModifiedTime().toMillis() >= comp) { - toBackup.add(targetFile); - partialSize += attributes.size(); - } - return FileVisitResult.CONTINUE; - } - }); - boolean complete = completeTemp; - if (toBackup.size() >= count) { - complete = true; - } - if ((partialSize / completeSize) * 100F > AVConfig.config.getMaxSizePercent()) { - complete = true; - toBackup.clear(); - toBackup.addAll(completeBackup); - } - - backupName += complete? "-full":"-partial"; - - - - if (AVConfig.config.getCompressChains()) { - File zip = differential ? new File(location.toString() + "/differential/", backupName +".zip") : new File(location.toString() + "/incremental/", backupName +".zip"); - FileOutputStream outputStream = new FileOutputStream(zip); - ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream); - zipOutputStream.setLevel(AVConfig.config.getCompressionLevel()); - - for (Path path : toBackup) { - zipOutputStream.putNextEntry(new ZipEntry(path.toString())); - byte[] bytes = Files.readAllBytes(new File(PlatformMethodWrapper.worldDir.toString(), path.toString()).toPath()); - zipOutputStream.write(bytes, 0, bytes.length); - zipOutputStream.closeEntry(); - } - zipOutputStream.flush(); - zipOutputStream.close(); - - time = zip.lastModified(); - } - else { - File dest = differential ? new File(location.toString() + "/differential/", backupName + "/") :new File(location.toString() + "/incremental/", backupName + "/"); - dest.mkdirs(); - for (Path path : toBackup) { - File out = new File(dest, path.toString()); - if (!out.getParentFile().exists()) { - out.getParentFile().mkdirs(); - } - Files.copy(new File(PlatformMethodWrapper.worldDir.toString(), path.toString()).toPath(), out.toPath()); - } - time = dest.lastModified(); - } - - //Finally, update + write the manifest - if (complete || toBackup.size() >= count) { - manifest.setChain(0); - manifest.getComplete().add(time); - manifest.setLastFull(time); - } - else { - manifest.setChain(manifest.getChain() + 1); - manifest.getPartial().add(new Date().getTime()); - manifest.setLastPartial(new Date().getTime()); - } - - FileWriter writer = new FileWriter(manifestFile); - writer.write(gson.toJson(manifest)); - writer.flush(); - writer.close(); - - } catch (IOException e) { - // TODO Scream at user - e.printStackTrace(); - } - - - } - - - public static String serialiseBackupName(String in) { - Date date = new Date(); - String pattern = "yyyy-MM-dd_hh-mm-ss"; - - return in + "_" + new SimpleDateFormat(pattern).format(date); - } -} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/gson/DifferentialManifest.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/gson/DifferentialManifest.java deleted file mode 100644 index ca1385cc..00000000 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/gson/DifferentialManifest.java +++ /dev/null @@ -1,73 +0,0 @@ -package co.uk.mommyheather.advancedbackups.core.backups.gson; - -import java.util.ArrayList; -import java.util.List; - -public class DifferentialManifest { - private List complete; - private List partial; - private int chain; - private long lastFull; - private long lastPartial; - - - public List getComplete() { - return complete; - } - - - public void setComplete(List complete) { - this.complete = complete; - } - - - public List getPartial() { - return partial; - } - - - public void setPartial(List partial) { - this.partial = partial; - } - - - public int getChain() { - return chain; - } - - - public void setChain(int chain) { - this.chain = chain; - } - - - public long getLastFull() { - return lastFull; - } - - - public void setLastFull(long lastFull) { - this.lastFull = lastFull; - } - - - public long getLastPartial() { - return Math.max(lastFull, lastPartial); - } - - - public void setLastPartial(long lastPartial) { - this.lastPartial = lastPartial; - } - - - public static DifferentialManifest defaultValues() { - DifferentialManifest manifest = new DifferentialManifest(); - manifest.complete = new ArrayList<>(); - manifest.partial = new ArrayList<>(); - manifest.chain = 0; - manifest.lastFull = 0; - manifest.lastPartial = 0; - return manifest; - } -} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java deleted file mode 100644 index b56eed0c..00000000 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java +++ /dev/null @@ -1,165 +0,0 @@ -package co.uk.mommyheather.advancedbackups.core.config; - -import java.io.File; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Properties; - -import co.uk.mommyheather.advancedbackups.PlatformMethodWrapper; -import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; - -public class AVConfig { - - private static final String[] supportedProps = { - "config.advancedbackups.enabled", - "config.advancedbackups.save", - "config.advancedbackups.activity", - "config.advancedbackups.type", - "config.advancedbackups.path", - "config.advancedbackups.size", - "config.advancedbackups.frequency.min", - "config.advancedbackups.frequency.max", - "config.advancedbackups.frequency.uptime", - "config.advancedbackups.frequency.schedule", - "config.advancedbackups.frequency.shutdown", - "config.advancedbackups.frequency.startup", - "config.advancedbackups.frequency.delay", - "config.advancedbackups.logging.silent", - - "config.advancedbackups.zips.compression", - - "config.advancedbackups.chains.length", - "config.advancedbackups.chains.compress", - "config.advancedbackups.chains.smart", - "config.advancedbackups.chains.maxpercent", - - "config.advancedbackups.purge.incrementals" - - }; - - public static ConfigData config; - - public static void loadOrCreateConfig() { - // Called when the config needs to be loaded, but one may not exist. - // Creates a new config it one doesn't exist, then loads it. - File file = new File("./AdvancedBackups.properties"); - if (!file.exists()) { - initConfig(); - } - loadConfig(); - } - - public static void initConfig() { - // Called when no config file is present. - // Create a complete properties file in the cwd - File file = new File("./AdvancedBackups.properties"); - try { - if (!file.exists()) { - file.createNewFile(); - file.setWritable(true); - } - FileWriter writer = new FileWriter(file); - writer.write(ConfigData.defaults()); - writer.close(); - } catch (IOException e) { - // TODO : Scream to user - e.printStackTrace(); - } - - - } - - public static void loadConfig() { - // Called when the config needs to be loaded. - // Populates all values of ConfigData.class - - Properties props = new Properties(); - File file = new File("./AdvancedBackups.properties"); - FileReader reader; - try { - reader = new FileReader(file); - props.load(reader); - } catch (IOException e) { - // TODO : Scream to user - e.printStackTrace(); - } - - config = new ConfigData(); - - config.setEnabled(props.getProperty("config.advancedbackups.enabled", "true")); - config.setSave(props.getProperty("config.advancedbackups.save", "false")); - config.setRequireActivity(props.getProperty("config.advancedbackups.activity", "false")); - config.setBackupType(props.getProperty("config.advancedbackups.type", "differential")); - config.setPath(props.getProperty("config.advancedbackups.path", "./backups")); - config.setMaxSize(props.getProperty("config.advancedbackups.size", "50")); - config.setMinTimer(props.getProperty("config.advancedbackups.frequency.min", "0.5")); - config.setMaxTimer(props.getProperty("config.advancedbackups.frequency.max", "24")); - config.setUptimeSchedule(props.getProperty("config.advancedbackups.frequency.uptime", "true")); - config.setSchedule(props.getProperty("config.advancedbackups.frequency.schedule", "12:00")); - config.setForceOnShutdown(props.getProperty("config.advancedbackups.frequency.shutdown", "false")); - config.setForceOnStartup(props.getProperty("config.advancedbackups.frequency.startup", "false")); - config.setStartupDelay(props.getProperty("config.advancedbackups.frequency.delay", "5")); - config.setSilent(props.getProperty("config.advancedbackups.logging.silent", "false")); - - config.setCompressionLevel(props.getProperty("config.advancedbackups.zips.compression", "5")); - - config.setMaxDepth(props.getProperty("config.advancedbackups.chains.length", "50")); - config.setCompressChains(props.getProperty("config.advancedbackups.chains.compress", "true")); - config.setSmartChains(props.getProperty("config.advancedbackups.chains.smart", "true")); - config.setMaxSizePercent(props.getProperty("config.advancedbackups.chains.maxpercent", "75")); - - config.setPurgeIncrementals(props.getProperty("config.advancedbackups.purge.incrementals", "false")); - - - - String timingsString = config.getSchedule(); - if (timingsString.length() != 0) { - BackupWrapper.configuredPlaytime = new ArrayList<>(); - for (String time : timingsString.split(",")) { - String[] hm = time.split(":"); - long hours = Long.parseLong(hm[0]) * 3600000L; - long mins = Long.parseLong(hm[1]) * 60000; - BackupWrapper.configuredPlaytime.add(hours + mins); - } - } - - boolean flag = false; - - for (String prop : supportedProps) { - if (!props.containsKey(prop)) { - flag = true; - break; - } - } - - if (flag) { - PlatformMethodWrapper.warningLogger.accept("Broken, incomplete or misising config found! Generating new file whilst preserving any existing config values..."); - - File newPropsFile = new File("./AdvancedBackups.properties"); - try { - if (!newPropsFile.exists()) { - newPropsFile.createNewFile(); - } - FileWriter writer = new FileWriter(newPropsFile); - writer.write(ConfigData.config(config.getEnabled(), config.getSave(), - config.getRequireActivity(), config.getBackupType(), config.getPath(), - config.getMaxSize(), config.getMinTimer(), config.getMaxTimer(), - config.getUptimeSchedule(), config.getSchedule(), config.getForceOnShutdown(), - config.getForceOnStartup(), config.getStartupDelay(), config.getSilent(), - config.getCompressionLevel(), config.getMaxDepth(), config.getCompressChains(), - config.getSmartChains(), config.getMaxSizePercent(), config.getPurgeIncrementals() - )); - writer.close(); - } catch (IOException e) { - // TODO : Scream to user - e.printStackTrace(); - - } - loadConfig(); - } - - } - -} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java deleted file mode 100644 index ecf162c9..00000000 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java +++ /dev/null @@ -1,378 +0,0 @@ -package co.uk.mommyheather.advancedbackups.core.config; - -public class ConfigData { - - private Boolean enabled; - //Allows outright disabling of backups. - //OPTIONS = "TRUE", "FALSE" - - private Boolean save; - //Whether to save before a backup. - //OPTIONS = "TRUE", "FALSE" - - private Boolean requireActivity; - //Whether to require player activity between backups. - //OPTIONS = "TRUE", "FALSE" - - private String backupType; - //The type of backup to make. Each has a separate file structure, but only the currently selected backup type is scanned for. - //OPTIONS = "ZIP", "DIFFERENTIAL", "INCREMENTAL" - - private long maxSize; - //Maximum size of backups. With zips, deletes the absolute oldest file if size is exceeded after making a backup, and repeats until below max size. - //RANGE = 5GB - 9999GB - - private float minTimer; - //Ensure this amount of time is waited between backups, in hours. - //RANGE = 0.5 - 500 - - private float maxTimer; - //Triggers a backup if none has already happened within this time. Can be combined with an uptime-based schedule. - //RANGE = 0.5 - 500 - - private boolean uptimeSchedule; - //Whether the schedule is based off of server uptime (true) or world-time (false). - - private String schedule; - //A comma seperated schedule. About it. - - private String path; - //The path for backups. Defaults to ./backups. Can be absolute or relative. - //ANY STRING IS TESTED, WILL CREATE DIRECTORIES IF MISSING - - private Boolean silent; - //Whether to supress all information. Does not affect debug.log. - // TRUE OR FALSE - - private Boolean forceOnShutdown; - //Whether to build a backup when the server shuts down. - // TRUE OR FALSE - - private Boolean forceOnStartup; - //Whether to build a backup when the server starts up. - // TRUE OR FALSE - - //Startup backup delay, in seconds. - private long startupDelay; - - - //BELOW ONLY APPLIES TO ZIP FILES! (affects export command) - private int compressionLevel; - //The compression level to be passed to zip streams. - // RANGE = 1 - 9 - - - //BELOW ONLY APPLIES TO INCREMENTAL AND DIFFERENTIAL BACKUPS! - private int maxDepth; - //The maximum "depth" of partial backups to create before creating a full backup. Higher numbers are reccomended if using incremental. Lower numbers increase storage usage but reduce restoration times. - // RANGE = 5 - 500 - - private boolean compressChains; - //Whether to compress chains. Useful for size reduction and manual restoration. - // TRUE OR FALSE - - private boolean smartChains; - // Smart chain resetting. - // TRUE OR FALSE - - private int maxSizePercent; - // Resets chain length if what gets backed up is over the defined % size. - // 1-100 range. - - private boolean purgeIncrementals; - // Whether to purge incremental backups if over the limit. - // TRUE OR FALSE - - public Boolean getEnabled() { - return enabled; - } - - public void setEnabled(String enabled) { - this.enabled = Boolean.parseBoolean(enabled); - } - - public Boolean getSave() { - return save; - } - - public void setSave(String save) { - this.save = Boolean.parseBoolean(save); - } - - public Boolean getRequireActivity() { - return requireActivity; - } - - public void setRequireActivity(String requireActivity) { - this.requireActivity = Boolean.parseBoolean(requireActivity); - } - - public String getBackupType() { - return backupType; - } - - public void setBackupType(String backupType) { - this.backupType = backupType; - } - - public long getMaxSize() { - return maxSize; - } - - public void setMaxSize(String maxSize) { - this.maxSize = Long.parseLong(maxSize); - } - - public float getMinTimer() { - return minTimer; - } - - public void setMinTimer(String minTimer) { - this.minTimer = Float.parseFloat(minTimer); - } - - - public float getMaxTimer() { - return maxTimer; - } - - public void setUptimeSchedule(String uptimeSchedule) { - this.uptimeSchedule = Boolean.parseBoolean(uptimeSchedule); - } - - public boolean getUptimeSchedule() { - return uptimeSchedule; - } - - public void setSchedule(String schedule) { - this.schedule = schedule; - } - - public String getSchedule() { - return schedule; - } - - public void setMaxTimer(String maxTimer) { - this.maxTimer = Float.parseFloat(maxTimer); - } - - public String getPath() { - return path; - } - - public void setPath(String path) { - this.path = path; - } - - public Boolean getSilent() { - return silent; - } - - public void setSilent(String silent) { - this.silent = Boolean.parseBoolean(silent); - } - - public Boolean getForceOnShutdown() { - return forceOnShutdown; - } - - public void setForceOnShutdown(String forceOnShutdown) { - this.forceOnShutdown = Boolean.parseBoolean(forceOnShutdown); - } - - public Boolean getForceOnStartup() { - return forceOnStartup; - } - - public void setForceOnStartup(String forceOnStartup) { - this.forceOnStartup = Boolean.parseBoolean(forceOnStartup); - } - - public void setStartupDelay(String delay) { - this.startupDelay = Long.parseLong(delay); - } - - public long getStartupDelay() { - return startupDelay; - } - - public int getCompressionLevel() { - return compressionLevel; - } - - public void setCompressionLevel(String compressionLevel) { - this.compressionLevel = Integer.parseInt(compressionLevel); - } - - public int getMaxDepth() { - return maxDepth; - } - - public void setMaxDepth(String maxDepth) { - this.maxDepth = Integer.parseInt(maxDepth); - } - - public boolean getCompressChains() { - return compressChains; - } - - public void setCompressChains(String compressChains) { - this.compressChains = Boolean.parseBoolean(compressChains); - } - - public boolean getSmartChains() { - return smartChains; - } - - public void setSmartChains(String smartChains) { - this.smartChains = Boolean.parseBoolean(smartChains); - } - - - public boolean getPurgeIncrementals() { - return purgeIncrementals; - } - - public void setPurgeIncrementals(String purgeIncrementals) { - this.purgeIncrementals = Boolean.parseBoolean(purgeIncrementals); - } - - public int getMaxSizePercent() { - return maxSizePercent; - } - - public void setMaxSizePercent(String maxSizePercent) { - this.maxSizePercent = Integer.parseInt(maxSizePercent); - } - - - - - //default config output - can be ignored - public static String config(Object enabled, Object save, - Object activity, Object type, Object location, - Object size, Object min, Object max, - Object uptime, Object schedule, Object shutdown, - Object startup, Object delay, Object silent, - Object compression, Object chainLength, Object compressChains, - Object smartChains, Object maxPercent, Object purgeIncrementals) { - return String.join("\n", - -"#Enable or disable automatic backups.", -"#Options : true, false #Default : true,", -"config.advancedbackups.enabled=" + enabled, -"", -"#Whether to save before making a backup.", -"#Options : true, false #Default : false", -"config.advancedbackups.save=" + save, -"", -"#Whether to require player activity between backups.", -"#Options : true, false #Default : false", -"config.advancedbackups.activity=" + activity, -"", -"#The type of backups to use.", -"#Options : zip, differential, incremental #Default : differential", -"config.advancedbackups.type=" + type, -"", -"#The absolute or relative path to the backup location.", -"#Options : any file path. Default : ./backups", -"config.advancedbackups.path=" + location, -"", -"#The maximum size to keep, in GB. Keep relatively high for zips, tighter space requirements should instead use differential or incremental backups.", -"#Range : 5 - 9999 #Default : 50", -"config.advancedbackups.size=" + size, -"", -"#Minimum time between backups, in hours. This can prevent a shutdown backup from triggering immediately after a scheduled backup or similar situations.", -"#Range : 0.5 - 500 #Default : 0.5", -"config.advancedbackups.frequency.min=" + min, -"", -"#Triggers a backup if none has already happened within this time. Can be combined with an uptime-based schedule.", -"#Range : 0.5 - 500 #Default : 24", -"config.advancedbackups.frequency.max=" + max, -"", -"#Whether the schedule below uses uptime (true) or real-world time (false).", -"#Default : true", -"config.advancedbackups.frequency.uptime=" + uptime, -"", -"#When using server uptime:", -" #A looping comma-separated backup schedule, based off of server uptime, hours:minutes. Examples:", -" #4:00 - Makes a backup every four hours.", -" #4:00,7:00 - Makes a backup after four hours, then three, then four, and so on.", -" #1:00 - Makes a backup every hour.", -" #4:00,8:00,12:00,16:00,17:00,18:00,19:00,20:00,21:00,24:00 - Makes a backup following a strict schedule.", -"", -"#When using real-world time:", -" #A strict schedule, using hours:minutes to follow real-world time. Examples:", -" #4:00 - Makes a backup at 4am each day.", -" #4:00,8:00,12:00,16:00,17:00,18:00,19:00,20:00,21:00,24:00 - Makes a backup at specific times of day.", -"", -"#Default : 12:00", -"config.advancedbackups.frequency.schedule=" + schedule, -"", -"#Whether to force a backup on server shutdown. Respects min frequency.", -"#Options : true, false #Default : false", -"config.advancedbackups.frequency.shutdown=" + shutdown, -"", -"#Whether to force a backup on server startup. Respects min frequency.", -"#Options : true, false #Default : false", -"config.advancedbackups.frequency.startup=" + startup, -"", -"#Delay to use after startup, in seconds. Is always at least 5 seconds.", -"#Range : 5-9999999999", -"config.advancedbackups.frequency.delay=" + delay, -"", -"#Whether to disable console and chat logging. Does not affect debug.log, does not affect error messages.", -"#Options : true, false #Default : false", -"config.advancedbackups.logging.silent=" + silent, -"", -"", -"", -"#--------------------------------------------------------------------------------------------------------------------", -"##The following options only affect zip files, whether that's for zip backups, export commands or some other option.", -"#--------------------------------------------------------------------------------------------------------------------", -"", -"#The compression level to use for zip files. Higher numbers space usage, but decrease performance.", -"#Range : 1-9 #Default : 4", -"config.advancedbackups.zips.compression=" + compression, -"", -"", -"", -"#--------------------------------------------------------------------------------------------------------------------", -"##The following options only affect differential and incremental backups.", -"#--------------------------------------------------------------------------------------------------------------------", -"", -"#The maximum 'chain' length to keep.", -"#Range : 5-500 #Default : 50", -"config.advancedbackups.chains.length=" + chainLength, -"", -"#Whether to compress 'chains'. This compresses the base backup and all sequential backups. Reduces space usage, but decreases performance.", -"#Options : true, false #Default : true", -"config.advancedbackups.chains.compress=" + compressChains, -"", -"#Whether to enable \"smart\" reset for chains - if every file is being backed up, mark the backup as complete and reset chain length regardless of intended backup type.", -"#Options : true, false #Default : true", -"config.advancedbackups.chains.smart=" + smartChains, -"", -"#What % of a full backup is allowed to be contained in a partial before forcing it into a full backup. Useful for reducing partial backup size.", -"config.advancedbackups.chains.maxpercent=" + maxPercent, -"", -"#Whether to delete incremental backup chains if max size is exceeded. If not, incremental backups do not respect the max size config and never delete.", -"#Options : true, false #Default : false", -"config.advancedbackups.purge.incrementals=" + purgeIncrementals - - - ); - } - - public static String defaults() { - return config( - "true", "false", "false", - "differential", "./backups", "50", - "0.5", "24", "true", - "12:00", "false", "false", - "5", "false", "4", - "50", "true", "true", - "75","false"); - - } -} From b1cc1c76247a978030184e1d9ee1bbd2766fd869 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Fri, 1 Sep 2023 17:55:32 +0100 Subject: [PATCH 223/580] Version bump --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 5a7e8b72..93932248 100644 --- a/build.gradle +++ b/build.gradle @@ -16,7 +16,7 @@ plugins { apply plugin: 'net.minecraftforge.gradle' -version = '1.0' +version = '2.0' group = 'co.uk.mommyheather.advancedbackups' // http://maven.apache.org/guides/mini/guide-naming-conventions.html archivesBaseName = 'AdvancedBackups-' + modloaderName + "-" + minecraftVersion From 9b34a24e138d337b46e82ec66a81e3a560d8f837 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Sat, 2 Sep 2023 00:32:09 +0100 Subject: [PATCH 224/580] Support the new core separation changes. --- build.gradle | 8 +- .../advancedbackups/AdvancedBackups.java | 57 +- .../PlatformMethodWrapper.java | 49 - .../cli/AdvancedBackupsCLI.java | 954 ------------------ .../core/CoreCommandSystem.java | 77 -- .../core/backups/BackupCheckEnum.java | 38 - .../core/backups/BackupTimingThread.java | 74 -- .../core/backups/BackupWrapper.java | 273 ----- .../core/backups/ThreadedBackup.java | 240 ----- .../backups/gson/DifferentialManifest.java | 73 -- .../advancedbackups/core/config/AVConfig.java | 165 --- .../core/config/ConfigData.java | 378 ------- 12 files changed, 56 insertions(+), 2330 deletions(-) delete mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/PlatformMethodWrapper.java delete mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java delete mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java delete mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupCheckEnum.java delete mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java delete mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java delete mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java delete mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/core/backups/gson/DifferentialManifest.java delete mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java delete mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java diff --git a/build.gradle b/build.gradle index 6dfc2189..80a789b8 100644 --- a/build.gradle +++ b/build.gradle @@ -12,8 +12,8 @@ apply plugin: 'net.minecraftforge.gradle' apply plugin: 'eclipse' apply plugin: 'maven-publish' -version = '1.0' -group = 'com.github.raveninthedark.advancedbackups' // http://maven.apache.org/guides/mini/guide-naming-conventions.html +version = '2.0' +group = 'co.uk.mommyheather.advancedbackups' // http://maven.apache.org/guides/mini/guide-naming-conventions.html archivesBaseName = 'AdvancedBackups-' + modloaderName + "-" + minecraftVersion java.toolchain.languageVersion = JavaLanguageVersion.of(8) // Mojang ships Java 8 to end users, so your mod should target Java 8. @@ -124,8 +124,8 @@ dependencies { // The userdev artifact is a special name and will get all sorts of transformations applied to it. minecraft 'net.minecraftforge:forge:1.16.5-36.1.0' - implementation files('dependencies/jansi-2.4.0.jar') - extraLibs files('dependencies/jansi-2.4.0.jar') + implementation files ('../advancedbackups-corelib.jar') + extraLibs files ('../advancedbackups-corelib.jar') // You may put jars on which you depend on in ./libs or you may define them like so.. // compile "some.group:artifact:version:classifier" // compile "some.group:artifact:version" diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index f77c2c0b..ad9f4945 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -1,8 +1,12 @@ package co.uk.mommyheather.advancedbackups; +import co.uk.mommyheather.advancedbackups.core.ABCore; import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; -import co.uk.mommyheather.advancedbackups.core.config.AVConfig; +import co.uk.mommyheather.advancedbackups.core.config.ABConfig; +import net.minecraft.server.MinecraftServer; +import net.minecraft.world.server.ServerWorld; +import net.minecraft.world.storage.FolderName; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.RegisterCommandsEvent; import net.minecraftforge.event.entity.player.PlayerEvent.PlayerLoggedInEvent; @@ -11,6 +15,7 @@ import net.minecraftforge.fml.event.server.FMLServerStartedEvent; import net.minecraftforge.fml.event.server.FMLServerStartingEvent; import net.minecraftforge.fml.event.server.FMLServerStoppingEvent; +import net.minecraftforge.fml.server.ServerLifecycleHooks; import java.util.function.Consumer; import org.apache.logging.log4j.LogManager; @@ -37,10 +42,19 @@ public AdvancedBackups() public void onServerStarting(FMLServerStartingEvent event) { // Do something when the server starts - AVConfig.loadOrCreateConfig(); + ABConfig.loadOrCreateConfig(); LOGGER.info("Config loaded!!"); - PlatformMethodWrapper.worldName = event.getServer().getWorldData().getLevelName(); - PlatformMethodWrapper.worldDir = event.getServer().storageSource.getWorldDir(); + ABCore.worldName = event.getServer().getWorldData().getLevelName(); + ABCore.worldDir = event.getServer().getWorldPath(FolderName.ROOT); + + + ABCore.disableSaving = AdvancedBackups::disableSaving; + ABCore.enableSaving = AdvancedBackups::enableSaving; + ABCore.saveOnce = AdvancedBackups::saveOnce; + + ABCore.infoLogger = infoLogger; + ABCore.warningLogger = warningLogger; + ABCore.errorLogger = errorLogger; } @@ -56,7 +70,7 @@ public void onServerStopping(FMLServerStoppingEvent event) { @SubscribeEvent public void onPlayerConneccted(PlayerLoggedInEvent event) { - PlatformMethodWrapper.activity = true; + ABCore.activity = true; } @SubscribeEvent @@ -64,4 +78,37 @@ public void registerCommands(RegisterCommandsEvent event){ AdvancedBackupsCommand.register(event.getDispatcher()); } + + + public static final String savesDisabledMessage = "\n\n\n***************************************\nSAVING DISABLED - PREPARING FOR BACKUP!\n***************************************"; + public static final String savesEnabledMessage = "\n\n\n*********************************\nSAVING ENABLED - BACKUP COMPLETE!\n*********************************"; + public static final String saveCompleteMessage = "\n\n\n*************************************\nSAVE COMPLETE - PREPARING FOR BACKUP!\n*************************************"; + + + public static void disableSaving() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + for (ServerWorld level : server.getAllLevels()) { + if (level != null && !level.noSave) { + level.noSave = true; + } + } + warningLogger.accept(savesDisabledMessage); + } + + public static void enableSaving() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + for (ServerWorld level : server.getAllLevels()) { + if (level != null && !level.noSave) { + level.noSave = false; + } + } + warningLogger.accept(savesEnabledMessage); + } + + public static void saveOnce() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + server.saveAllChunks(true, true, true); + warningLogger.accept(saveCompleteMessage); + } + } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/PlatformMethodWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/PlatformMethodWrapper.java deleted file mode 100644 index 95d30f37..00000000 --- a/src/main/java/co/uk/mommyheather/advancedbackups/PlatformMethodWrapper.java +++ /dev/null @@ -1,49 +0,0 @@ -package co.uk.mommyheather.advancedbackups; - -import java.nio.file.Path; -import java.util.function.Consumer; - -import net.minecraft.server.MinecraftServer; -import net.minecraft.world.server.ServerWorld; -import net.minecraftforge.fml.server.ServerLifecycleHooks; - -public class PlatformMethodWrapper { - - public static String worldName = ""; - public static Path worldDir = null; - public static Boolean activity = false; - public static final Consumer infoLogger = AdvancedBackups.infoLogger; - public static final Consumer warningLogger = AdvancedBackups.warningLogger; - public static final Consumer errorLogger = AdvancedBackups.errorLogger; - - public static final String savesDisabledMessage = "\n\n\n***************************************\nSAVING DISABLED - PREPARING FOR BACKUP!\n***************************************"; - public static final String savesEnabledMessage = "\n\n\n*********************************\nSAVING ENABLED - BACKUP COMPLETE!\n*********************************"; - public static final String saveCompleteMessage = "\n\n\n*************************************\nSAVE COMPLETE - PREPARING FOR BACKUP!\n*************************************"; - - - public static void disableSaving() { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - for (ServerWorld level : server.getAllLevels()) { - if (level != null && !level.noSave) { - level.noSave = true; - } - } - warningLogger.accept(savesDisabledMessage); - } - - public static void enableSaving() { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - for (ServerWorld level : server.getAllLevels()) { - if (level != null && !level.noSave) { - level.noSave = false; - } - } - warningLogger.accept(savesEnabledMessage); - } - - public static void saveOnce() { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - server.saveAllChunks(true, true, true); - warningLogger.accept(saveCompleteMessage); - } -} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java deleted file mode 100644 index 5787b961..00000000 --- a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java +++ /dev/null @@ -1,954 +0,0 @@ -package co.uk.mommyheather.advancedbackups.cli; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.FileReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.nio.file.FileSystem; -import java.nio.file.FileSystems; -import java.nio.file.FileVisitResult; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.SimpleFileVisitor; -import java.nio.file.StandardCopyOption; -import java.nio.file.attribute.BasicFileAttributes; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.InputMismatchException; -import java.util.Properties; -import java.util.Scanner; -import java.util.regex.Pattern; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; -import java.util.zip.ZipInputStream; -import java.util.zip.ZipOutputStream; - -import org.fusesource.jansi.AnsiConsole; - -import co.uk.mommyheather.advancedbackups.core.backups.ThreadedBackup; - -public class AdvancedBackupsCLI { - - private static String backupLocation; - private static File serverDir = new File(new File("").toPath().toAbsolutePath().getParent().toString()); - private static String type; - private static Scanner input = new Scanner(System.in); - private static ArrayList fileNames = new ArrayList<>(); - private static File worldFile; - private static String worldPath; - public static void main(String args[]){ - - - System.out.print("\033[H\033[2J"); - System.out.flush(); - - if (System.console() != null) { - AnsiConsole.systemInstall(); //this gets ansi escape codes working on windows. this was a FUCKING PAIN IN MY ASS - } - - - info("Advanced Backups - Version " + AdvancedBackupsCLI.class.getPackage().getImplementationVersion()); - info("Searching for properties...", false); - - Properties props = new Properties(); - File file = new File(serverDir, "AdvancedBackups.properties"); - FileReader reader; - try { - reader = new FileReader(file); - props.load(reader); - - backupLocation = props.getProperty("config.advancedbackups.path"); - type = props.getProperty("config.advancedbackups.type"); - } catch (Exception e) { - error("ERROR LOADING PROPERTIES!"); - error(getStackTrace(e)); - error(""); - error(""); - error("Ensure you're running this from within the mods directory, and the config file is in the parent directory!"); - // Fatal, cannot proceed - return; - } - - if (backupLocation == null || type == null) { - error("ERROR LOADING PROPERTIES!"); - error("Backup location : " + backupLocation); - error("Type : " + type); - // Fatal, cannot proceed - return; - } - - info("Config loaded!"); - - type = getBackupType(); - - worldFile = getWorldFile(); - - if (!worldFile.exists()) { - error("Unable to find world folder!"); - error(worldFile.getAbsolutePath()); - error("Check if the location exists and the name is correct and try again."); - return; - - } - - - File backupDir; - - if (backupLocation.startsWith(Pattern.quote(File.separator))) { - backupDir = new File(backupLocation, File.separator + type + File.separator); - } - else { - backupDir = new File(serverDir, backupLocation.replaceAll(Pattern.quote("." + File.separator), "") + File.separator + type + File.separator); - } - - if (!backupDir.exists()) { - error("Could not find backup directory!"); - error(backupDir.getAbsolutePath()); - error("Have you made any backups before?"); - //Fatal, cannot continue - return; - } - - int backupDateIndex; - try { - backupDateIndex = getBackupDate(backupDir); - } catch (IOException e) { - error("ERROR VIEWING BACKUPS!"); - e.printStackTrace(); - return; - } - - - String restore = restoreWorldOrFile(); - - if (!confirmWarningMessage()) { - error("ABORTED - WILL NOT PROCEED."); - return; - } - - info("Preparing..."); - - - - switch(restore) { - case "world" : { - //No going back now! - //TODO : make a backup of current world state. - deleteEntireWorld(worldFile); - switch(type) { - case "zips" : { - restoreFullZip(backupDateIndex, worldFile); - return; - } - case "differential" : { - restoreFullDifferential(backupDateIndex, worldFile); - return; - } - case "incremental" : { - restoreFullIncremental(backupDateIndex, worldFile); - return; - } - } - } - case "file" : { - switch(type) { - case "zips" : { - restorePartialZip(backupDateIndex, worldFile); - return; - } - case "differential" : { - restorePartialDifferential(backupDateIndex, worldFile); - return; - } - case "incremental" : { - restorePartialIncremental(backupDateIndex, worldFile); - return; - } - } - } - } - - - } - - - - - - - - - - - - - - - - - - - //HELPER METHODS! - private static void info(String out, boolean line) { - if (line) System.out.println(out); - else System.out.print(out); - - } - - private static void warn(String out, boolean line) { - if (line) System.out.println("\u001B[33m" + out + "\u001B[0m"); - else System.out.print("\u001B[33m" + out + "\u001B[0m"); - - } - - private static void error(String out, boolean line) { - if (line) System.out.println("\u001B[31m" + out + "\u001B[0m"); - else System.out.print("\u001B[31m" + out + "\u001B[0m"); - - } - - private static void info(String out) { - info(out, true); - } - - private static void warn(String out) { - warn(out, true); - } - - private static void error(String out) { - error(out, true); - } - - - private static String getStackTrace(final Throwable throwable) { - final StringWriter sw = new StringWriter(); - final PrintWriter pw = new PrintWriter(sw, true); - throwable.printStackTrace(pw); - return sw.getBuffer().toString(); - } - - private static String getBackupType() { - // Select a type of backup to restore - info("Select a backup type to restore. Your server is currently set to use " + type + " backups."); - info("1: zip\n2: differential\n3: incremental"); - info("Enter a number or leave blank for " + type + "."); - int inputType; - try { - String line = input.nextLine(); - if (line == "") { - return type; - } - inputType = Integer.parseInt(line); - } catch (InputMismatchException | NumberFormatException e) { - warn("That was not a number. Please enter a number."); - return getBackupType(); - } - switch (inputType) { - case 1 : return "zips"; - case 2 : return "differential"; - case 3 : return "incremental"; - default : { - warn("Please pick an option between 1 and 3 inclusive."); - return getBackupType(); - } - } - } - - - private static File getWorldFile() { - info("Are you on a client or server?"); - info("1: Client\n2: Server"); - info("Enter a number."); - - int inputType; - File ret = new File(serverDir.getAbsolutePath()); - - try { - String line = input.nextLine(); - if (line == "") { - warn("Please enter a number."); - return getWorldFile(); - } - inputType = Integer.parseInt(line); - } catch (InputMismatchException | NumberFormatException e) { - warn("That was not a number. Please enter a number."); - return getWorldFile(); - } - - if (inputType < 1 || inputType > 2) { - warn("Please enter 1 or 2."); - return getWorldFile(); - } - - if (inputType == 1) { - ret = new File(ret, "/saves/"); - } - - ret = new File(ret, getWorldName(ret)); - return ret; - - } - - private static String getWorldName(File dir) { - ArrayList worlds = new ArrayList<>(); - int worldIndex; - for (File file : dir.listFiles()) { - boolean flag = false; - if (!file.isDirectory()) continue; - for (File file2 : file.listFiles()) { - if (file2.getName().contains("level.dat")) { - flag = true; - } - } - if (flag) { - worlds.add(file.getName()); - } - } - info("Please select your world. Default for servers is \"world\"."); - int index = 1; - for (String world : worlds) { - info (index + ". " + world); - index++; - } - try { - String line = input.nextLine(); - if (line == "") { - warn("Please enter a number."); - return getWorldName(dir); - } - worldIndex = Integer.parseInt(line); - } catch (InputMismatchException | NumberFormatException e) { - warn("That was not a number. Please enter a number."); - return getWorldName(dir); - } - if (worldIndex < 1 || worldIndex > worlds.size()) { - warn("Please enter a number between " + worlds.size() + "."); - return getWorldName(dir); - } - - worldPath = worlds.get(worldIndex -1).replaceAll(" ", "_"); - return worlds.get(worldIndex - 1); - - } - - - private static int getBackupDate(File backupDir) throws IOException { - fileNames.clear(); - int inputType; - - info("Select a backup to restore."); - - for (File file : backupDir.listFiles()) { - if (!file.getName().contains(worldPath)) continue; - fileNames.add(file.getAbsolutePath()); - String out = file.getName(); - out = out.replaceAll(".zip", ""); - out = out.replaceAll(worldPath + "_", ": "); - out = out.replaceAll("-partial", "\u001B[33m partial\u001B[0m"); - out = out.replaceAll("-full", "\u001B[32m full\u001B[0m"); - info(fileNames.size() + out); - } - - try { - String line = input.nextLine(); - if (line == "") { - warn("Please enter a number."); - return getBackupDate(backupDir); - } - inputType = Integer.parseInt(line); - } catch (InputMismatchException | NumberFormatException e) { - warn("That was not a number. Please enter a number."); - return getBackupDate(backupDir); - } - - if (inputType < 1 || inputType > fileNames.size()) { - warn("Please enter a number between " + fileNames.size() + "."); - return getBackupDate(backupDir); - } - - return inputType - 1; - } - - private static String restoreWorldOrFile() { - info("Do you want to restore the entire world state at this point, or a singular file?"); - info("1: Entire world\n2: Single file"); - info("Enter a number."); - int inputType; - try { - String line = input.nextLine(); - if (line == "") { - return type; - } - inputType = Integer.parseInt(line); - } catch (InputMismatchException | NumberFormatException e) { - warn("That was not a number. Please enter a number."); - return restoreWorldOrFile(); - } - switch (inputType) { - case 1 : return "world"; - case 2 : return "file"; - default : { - warn("Please pick 1 or 2."); - return restoreWorldOrFile(); - } - } - - } - - - - private static boolean confirmWarningMessage() { - warn(""); - warn(""); - warn("WARNING! DOING THIS WHILST THE SERVER IS RUNNING CAN CAUSE SEVERE CORRUPTION, PARTIAL RESTORATION, AND OTHER ISSUES."); - warn("TYPE \"continue\" IF YOU WISH TO CONTINUE...", false); - - - String line = input.nextLine(); - if (line.equals("")) { - return confirmWarningMessage(); - } - return line.equals("continue"); - } - - - private static void restoreFullZip(int index, File worldFile) { - byte[] buffer = new byte[1024]; - //The most basic of the bunch. - ZipEntry entry; - try { - FileInputStream fileInputStream = new FileInputStream(fileNames.get(index)); - ZipInputStream zip = new ZipInputStream(fileInputStream); - while ((entry = zip.getNextEntry()) != null) { - File outputFile; - - //FTB Backups and some other mods need special handling. - if (entry.getName().startsWith(worldFile.getName())) { - outputFile = new File(worldFile.getParentFile(), entry.getName()); - } - else { - outputFile = new File(worldFile, entry.getName()); - } - - if (!outputFile.getParentFile().exists()) { - outputFile.getParentFile().mkdirs(); - } - - FileOutputStream outputStream = new FileOutputStream(outputFile); - int length = 0; - while ((length = zip.read(buffer)) > 0) { - outputStream.write(buffer, 0, length); - } - outputStream.close(); - } - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - - private static void restoreFullDifferential(int index, File worldFile) { - //Do we need to check for past backups? if selected is a full backup, we do not. - File backup = new File(fileNames.get(index)); - if (backup.getName().contains("-full")) { - if (backup.isFile()) { - restoreFullZip(index, worldFile); - return; - } - restoreFolder(index, worldFile); - return; - } - //find last FULL backup - for (int i = index;i>0;i--) { - String name = fileNames.get(i); - if (name.contains("-full")) { - info("Restoring last full backup..."); - File file = new File(name); - if (file.isFile()) { - restoreFullZip(i, worldFile); - } - else { - restoreFolder(i, worldFile); - } - break; - } - } - info("\n\nRestoring selected backup..."); - if (backup.isFile()) { - restoreFullZip(index, worldFile); - } - else { - restoreFolder(index, worldFile); - } - } - - private static void restoreFullIncremental(int index, File worldFile) { - //Do we need to check for past backups? if selected is a full backup, we do not. - File backup = new File(fileNames.get(index)); - if (backup.getName().contains("-full")) { - if (backup.isFile()) { - restoreFullZip(index, worldFile); - return; - } - restoreFolder(index, worldFile); - return; - } - //find last FULL backup - int i = index; - while(i >= 0) { - String name = fileNames.get(i); - if (name.contains("-full")) { - info("Restoring last full backup..."); - File file = new File(name); - if (file.isFile()) { - restoreFullZip(i, worldFile); - } - else { - restoreFolder(i, worldFile); - } - break; - } - i--; - } - //restore backups up until the selected one - while(i < index) { - String name = fileNames.get(i); - info("Restoring chained backup..."); - File file = new File(name); - if (file.isFile()) { - restoreFullZip(i, worldFile); - } - else { - restoreFolder(i, worldFile); - } - i++; - } - - - info("\n\nRestoring selected backup..."); - if (backup.isFile()) { - restoreFullZip(index, worldFile); - } - else { - restoreFolder(index, worldFile); - } - } - - private static void restorePartialZip(int index, File worldFile) { - Path file; - HashMap entries = new HashMap<>(); - - try { - FileSystem zipFs = FileSystems.newFileSystem(new File(fileNames.get(index)).toPath(), AdvancedBackupsCLI.class.getClassLoader()); - Path root = zipFs.getPath(""); - Files.walkFileTree(root, new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) throws IOException { - entries.put(file.toString(), file); - return FileVisitResult.CONTINUE; - } - }); - - file = getFileToRestore(entries, ""); - info("Restoring " + file.toString() + "..."); - Path outputFile = new File(worldFile, file.toString()).toPath(); - Files.copy(file, outputFile, StandardCopyOption.REPLACE_EXISTING); - info("Done."); - - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - return; - } - - } - - private static void restorePartialDifferential(int index, File worldFile) { - //Do we need to check for past backups? if selected is a full backup, we do not. - HashMap filePaths = new HashMap<>(); - HashMap dates = new HashMap<>(); - HashMap entryOwners = new HashMap<>(); - try { - File backup = new File(fileNames.get(index)); - if (!backup.getName().contains("-full")) { - //find last FULL backup - for (int i = index;i>=0;i--) { - String name = fileNames.get(i); - if (name.contains("-full")) { - addBackupNamesToLists(new File(name), entryOwners, filePaths, dates, "\u001b[31m"); - break; - } - } - } - - File file = new File(fileNames.get(index)); - addBackupNamesToLists(file, entryOwners, filePaths, dates, "\u001B[32m"); - - HashMap properMapping = new HashMap<>(); - for (String date : dates.keySet()) { - properMapping.put( - date + " " + dates.get(date), - filePaths.get(date) - ); - } - - Object select = getFileToRestore(properMapping, ""); - if (select instanceof Path) { - Path input = (Path) select; - - - if (select.toString().replace("\\", "/").contains("-full/")) { - select = new File( - select.toString().replace("\\", "/") - .split("-full/")[1] - ).toPath(); - } - if (select.toString().replace("\\", "/").contains("-partial/")) { - select = new File( - select.toString().replace("\\", "/") - .split("-partial/")[1] - ).toPath(); - } - - File outputFile = new File(worldFile, select.toString()); - if (!outputFile.getParentFile().exists()) { - outputFile.getParentFile().mkdirs(); - } - info("\n\nRestoring file : " + select); - Files.copy(input, outputFile.toPath(), StandardCopyOption.REPLACE_EXISTING); - } - else if (select instanceof ZipEntry) { - ZipEntry entry = (ZipEntry) select; - - File outputFile = new File(worldFile, entry.toString()); - FileOutputStream outputStream = new FileOutputStream(outputFile); - - info("Restoring " + entry.toString() + "..."); - - byte[] buffer = new byte[1028]; - InputStream inputSteam = entryOwners.get(entry.toString()).getInputStream(entry); - int length; - while ((length = inputSteam.read(buffer, 0, buffer.length)) > 0) { - outputStream.write(buffer, 0, length); - } - outputStream.flush(); - outputStream.close(); - } - - - } - catch (IOException e){ - //TODO : Scream at user - e.printStackTrace(); - } - } - - private static void restorePartialIncremental(int index, File worldFile) { - //Do we need to check for past backups? if selected is a full backup, we do not. - HashMap filePaths = new HashMap<>(); - HashMap dates = new HashMap<>(); - HashMap entryOwners = new HashMap<>(); - try { - File backup = new File(fileNames.get(index)); - if (!backup.getName().contains("-full")) { - int i; - //find last FULL backup - for (i = index;i>=0;i--) { - String name = fileNames.get(i); - if (name.contains("-full")) { - addBackupNamesToLists(new File(name), entryOwners, filePaths, dates, "\u001b[31m"); - break; - } - } - while (i < index) { - String name = fileNames.get(i); - addBackupNamesToLists(new File(name), entryOwners, filePaths, dates, "\u001b[31m"); - i++; - } - - } - - File file = new File(fileNames.get(index)); - addBackupNamesToLists(file, entryOwners, filePaths, dates, "\u001B[32m"); - - HashMap properMapping = new HashMap<>(); - for (String date : dates.keySet()) { - properMapping.put( - date + " " + dates.get(date), - filePaths.get(date) - ); - } - - Object select = getFileToRestore(properMapping, ""); - if (select instanceof Path) { - Path input = (Path) select; - - - if (select.toString().replace("\\", "/").contains("-full/")) { - select = new File( - select.toString().replace("\\", "/") - .split("-full/")[1] - ).toPath(); - } - if (select.toString().replace("\\", "/").contains("-partial/")) { - select = new File( - select.toString().replace("\\", "/") - .split("-partial/")[1] - ).toPath(); - } - - File outputFile = new File(worldFile, select.toString()); - if (!outputFile.getParentFile().exists()) { - outputFile.getParentFile().mkdirs(); - } - info("\n\nRestoring file : " + select); - Files.copy(input, outputFile.toPath(), StandardCopyOption.REPLACE_EXISTING); - } - else if (select instanceof ZipEntry) { - ZipEntry entry = (ZipEntry) select; - - File outputFile = new File(worldFile, entry.toString()); - FileOutputStream outputStream = new FileOutputStream(outputFile); - - info("Restoring " + entry.toString() + "..."); - - byte[] buffer = new byte[1028]; - InputStream inputSteam = entryOwners.get(entry.toString()).getInputStream(entry); - int length; - while ((length = inputSteam.read(buffer, 0, buffer.length)) > 0) { - outputStream.write(buffer, 0, length); - } - outputStream.flush(); - outputStream.close(); - } - - - } - catch (IOException e){ - //TODO : Scream at user - e.printStackTrace(); - } - } - - - private static void restoreFolder(int index, File worldFile) { - File backup = new File(fileNames.get(index)); - - try { - Files.walkFileTree(backup.toPath(), new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) throws IOException { - File source = backup.toPath().relativize(file).toFile(); - File outputFile = new File(worldFile, source.getPath()); - - if (!outputFile.getParentFile().exists()) { - outputFile.getParentFile().mkdirs(); - } - Files.copy(file, outputFile.toPath()); - return FileVisitResult.CONTINUE; - } - }); - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - - - private static void deleteEntireWorld(File worldDir) { - backupExistingWorld(worldDir); - try { - Files.walkFileTree(worldDir.toPath(), new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { - file.toFile().delete(); - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult postVisitDirectory(Path file, java.io.IOException arg1) { - if (file.toFile().listFiles().length == 0) { - file.toFile().delete(); - } - return FileVisitResult.CONTINUE; - } - }); - } catch (IOException e) { - warn("Failed to delete file :"); - e.printStackTrace(); - } - } - - private static void backupExistingWorld(File worldDir) { - try { - File out = new File(worldDir, "../cli" + ThreadedBackup.serialiseBackupName("backup") + ".zip"); - FileOutputStream outputStream = new FileOutputStream(out); - ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream); - zipOutputStream.setLevel(4); - Files.walkFileTree(worldDir.toPath(), new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { - Path targetFile; - try { - targetFile = worldDir.toPath().relativize(file); - if (targetFile.toFile().getName().compareTo("session.lock") == 0) { - return FileVisitResult.CONTINUE; - } - zipOutputStream.putNextEntry(new ZipEntry(targetFile.toString())); - byte[] bytes = Files.readAllBytes(file); - zipOutputStream.write(bytes, 0, bytes.length); - zipOutputStream.closeEntry(); - - } catch (IOException e) { - // TODO : Scream at user - e.printStackTrace(); - } - - return FileVisitResult.CONTINUE; - } - }); - zipOutputStream.flush(); - zipOutputStream.close(); - } catch (Exception e) { - - } - } - - - private static T getFileToRestore(HashMap files, String directory) { - ArrayList toDisplay = new ArrayList<>(); - HashMap keyMap = new HashMap<>(); - int index = 1; - for (String name : files.keySet()) { - String name2 = name.replace("\\", "/"); // this replacement can fix some problems with wsl, and helps keep code neat. - if (name2.contains(directory)) { - name2 = name2.replace(directory, ""); - if (name2.startsWith(worldFile.getName())) { - name2 = name2.replace(worldFile.getName() + "/", ""); - } - if (name2.contains("/")) { - name2 = "\u001B[33mdirectory\u001B[0m " + name2.split("/")[0]; - } - if (!toDisplay.contains(name2)) { - toDisplay.add(name2); - keyMap.put(name2, name); - } - } - } - toDisplay = sortStringsAlphabeticallyWithDirectoryPriority(toDisplay); - info("Choose a file to restore.\n"); - for (String name : toDisplay) { - if (index < 10) { - info(index + ": " + name); - } - else { - info(index + ": " + name); - } - index++; - } - if (!directory.equals("")) { - info(index + ": ../"); - } - - - int userInput; - try { - String line = input.nextLine(); - if (line == "") { - warn("Please enter a number!"); - return getFileToRestore(files, directory); - } - userInput = Integer.parseInt(line); - } catch (InputMismatchException | NumberFormatException e) { - warn("That was not a number. Please enter a number."); - return getFileToRestore(files, directory); - } - - if (userInput <= 0 || userInput > (directory.equals("") ? toDisplay.size() : toDisplay.size() + 1)) { - warn("Please enter a number in the specified range!"); - return getFileToRestore(files, directory); - } - else if (userInput > toDisplay.size()) { - return null; - } - else if (!toDisplay.get(userInput - 1).contains("\u001B[33mdirectory\u001B[0m ")) { - return files.get(keyMap.get(toDisplay.get(userInput -1))); - } - - T result = getFileToRestore(files, directory + toDisplay.get(userInput -1).replace("\u001B[33mdirectory\u001B[0m ", "") + "/"); - if (result != null) { - return result; - } - else { - return getFileToRestore(files, directory); - } - } - - - private static ArrayList sortStringsAlphabeticallyWithDirectoryPriority(ArrayList in) { - ArrayList out = new ArrayList<>(); - Collections.sort(in); - for (String string : in) { - if (string.contains("\u001B[33mdirectory\u001B[0m")) { - out.add(string); - } - } - for (String string : in) { - if (!string.contains("\u001B[33mdirectory\u001B[0m")) { - out.add(string); - } - } - return out; - } - - - private static void addBackupNamesToLists(File file, HashMap entryOwners, HashMap filePaths, - HashMap dates, String colour) throws IOException { - - if (file.isFile()) { - - ZipFile zipFile = new ZipFile(file); - Enumeration entryEnum = zipFile.entries(); - - while (entryEnum.hasMoreElements()) { - ZipEntry entry = entryEnum.nextElement(); - - String backupName = file.toString().replace("\\", "/"); - filePaths.put(entry.toString().replace("\\", "/"), entry); - dates.put(entry.toString().replace("\\", "/"), "\u001b[31m" - + backupName - .substring(backupName.toString().lastIndexOf("/") + 1) - .replace(worldPath + "_", "") - .replace("-full.zip", "") - .replace("-partial.zip", "") - + "\u001B[0m"); - entryOwners.put(entry.toString(), zipFile); - } - } - - else { - Files.walkFileTree(file.toPath(), new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path path, BasicFileAttributes attributes) throws IOException { - String backupName = file.toString().replace("\\", "/"); - filePaths.put(file.toPath().relativize(path).toString().replace("\\", "/"), path); - dates.put(file.toPath().relativize(path).toString().replace("\\", "/"), "\u001b[31m" - + backupName - .substring(backupName.toString().lastIndexOf("/") + 1) - .replace(worldPath + "_", "") - .replace("-full", "") - .replace("-partial", "") - + "\u001B[0m"); - return FileVisitResult.CONTINUE; - } - }); - } - } - -} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java deleted file mode 100644 index 76e59aef..00000000 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java +++ /dev/null @@ -1,77 +0,0 @@ -package co.uk.mommyheather.advancedbackups.core; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileWriter; -import java.nio.file.Files; -import java.util.function.Consumer; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; - -import co.uk.mommyheather.advancedbackups.core.backups.BackupCheckEnum; -import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; -import co.uk.mommyheather.advancedbackups.core.backups.gson.DifferentialManifest; -import co.uk.mommyheather.advancedbackups.core.config.AVConfig; - -public class CoreCommandSystem { - private static GsonBuilder builder = new GsonBuilder(); - private static Gson gson; - static { - builder.setPrettyPrinting(); - gson = builder.create(); - } - - - //These methods are all called by relevant command classes in version specific code - public static void checkBackups(Consumer chat) { - BackupCheckEnum check = BackupWrapper.checkBackups(); - chat.accept(check.getCheckMessage()); - } - - public static void startBackup(Consumer chat) { - BackupCheckEnum check = BackupWrapper.checkBackups(); - chat.accept(check.getCheckMessage()); - if (check.success()) { - chat.accept("Starting backup..."); - BackupWrapper.makeSingleBackup(0); - } - } - - public static void forceBackup(Consumer chat) { - chat.accept("Forcing a backup..."); - BackupWrapper.makeSingleBackup(0); - } - - public static void reloadConfig(Consumer chat) { - chat.accept("Reloading config..."); - AVConfig.loadConfig(); - chat.accept("Done!"); - } - - public static void resetChainLength(Consumer chat) { - chat.accept("Resetting chain length... The next backup will be a complete backup."); - boolean differential = AVConfig.config.getBackupType().equals("differential") ? true : false; - File manifestFile = differential ? new File(AVConfig.config.getPath() + "/differential/manifest.json") : new File(AVConfig.config.getPath() + "/incremental/manifest.json"); - DifferentialManifest manifest; - try { - if (manifestFile.exists()) { - manifest = gson.fromJson(new String(Files.readAllBytes(manifestFile.toPath())), DifferentialManifest.class); - manifest.setChain(manifest.getChain() + AVConfig.config.getMaxDepth()); - FileWriter writer = new FileWriter(manifestFile); - writer.write(gson.toJson(manifest)); - writer.flush(); - writer.close(); - chat.accept("Done!"); - return; - } - else { - chat.accept("No manifest file exists!"); - return; - } - } catch (Exception e) { - chat.accept("Error resetting chain length. - check logs for more info."); - e.printStackTrace(); - } - } -} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupCheckEnum.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupCheckEnum.java deleted file mode 100644 index 06e00e14..00000000 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupCheckEnum.java +++ /dev/null @@ -1,38 +0,0 @@ -package co.uk.mommyheather.advancedbackups.core.backups; - -public enum BackupCheckEnum { - SUCCESS, - DISABLED, - NOACTIVITY, - TOORECENT; - - public boolean success() { - switch (this) { - case SUCCESS: { - return true; - } - default : return false; - } - } - - - public String getCheckMessage() { - switch(this) { - case SUCCESS : { - return "Checks successful!"; - } - case DISABLED : { - return "Backups are disabled!"; - } - case NOACTIVITY : { - return "Player activity is required, but none have been active!"; - } - case TOORECENT : { - return "The time since the last backup is less than the minimum time specified in config!"; - } - default : { - return "You should not see this message, report a bug!"; - } - } - } -} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java deleted file mode 100644 index b346e89c..00000000 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java +++ /dev/null @@ -1,74 +0,0 @@ -package co.uk.mommyheather.advancedbackups.core.backups; - -import java.time.LocalDateTime; -import java.util.ArrayList; - -import co.uk.mommyheather.advancedbackups.core.config.AVConfig; - -public class BackupTimingThread extends Thread { - private int loops = 0; - private int index = 0; - private long prev = 0; - - public BackupTimingThread() { - setName("AB Backup Timing Daemon"); - setDaemon(true); - } - - @Override - public void run() { - while (true) { - try { - long time = calculateNextBackupTime(); - sleep(time); - BackupWrapper.checkAndMakeBackups(); - } catch (InterruptedException e) { - // TODO Scream at user - e.printStackTrace(); - break; - } - } - } - - - private long calculateNextBackupTime() { - long forcedMillis = BackupWrapper.mostRecentBackupTime() + (long) (AVConfig.config.getMaxTimer() * 3600000L); - if (forcedMillis == AVConfig.config.getMaxTimer() * 3600000L || forcedMillis <= System.currentTimeMillis()) forcedMillis = 300000; //sets it to 5m if no backup exists or the timer is already execeeded to get the chain going - else forcedMillis -= System.currentTimeMillis(); - long ret = Long.MAX_VALUE; - if (AVConfig.config.getUptimeSchedule() && !BackupWrapper.configuredPlaytime.isEmpty()) { - ArrayList timings = new ArrayList(BackupWrapper.configuredPlaytime); - if (index >= timings.size()) { - index = 0; - loops++; - } - ret = (timings.get(index) + (timings.get(timings.size() - 1) * loops)); - ret -= prev; - prev += ret; - index++; - } - - else if (!BackupWrapper.configuredPlaytime.isEmpty()) { - long nextTime = 0; - long currentTime = System.currentTimeMillis(); - ArrayList timings = new ArrayList(BackupWrapper.configuredPlaytime); - for (long time : timings) { - if (time >= currentTime) { - nextTime = time; - break; - } - } - ret = nextTime >= currentTime ? nextTime - currentTime : 86640000 - currentTime; - } - - return Math.min(forcedMillis, ret); - - - - - - - } - - -} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java deleted file mode 100644 index f5960e0d..00000000 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java +++ /dev/null @@ -1,273 +0,0 @@ -package co.uk.mommyheather.advancedbackups.core.backups; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.FileWriter; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.StringReader; -import java.util.ArrayList; -import java.util.Date; - - -import co.uk.mommyheather.advancedbackups.PlatformMethodWrapper; -import co.uk.mommyheather.advancedbackups.core.config.AVConfig; - -public class BackupWrapper { - - public static ArrayList configuredPlaytime = new ArrayList<>(); - - - public static void checkStartupBackups () { - if (AVConfig.config.getForceOnStartup()) { - checkAndMakeBackups(Math.max(5000, AVConfig.config.getStartupDelay() * 1000)); - } - - new BackupTimingThread().start(); - } - - public static void checkShutdownBackups() { - if (AVConfig.config.getForceOnShutdown()) { - checkAndMakeBackups(); - } - } - - public static void checkAndMakeBackups(long delay) { - BackupCheckEnum e = checkBackups(); - if (e.success()) { - makeSingleBackup(delay); - } - } - - public static void checkAndMakeBackups() { - checkAndMakeBackups(0); - } - - - public static BackupCheckEnum checkBackups() { - prepareBackupDestination(); - if (!AVConfig.config.getEnabled()) return BackupCheckEnum.DISABLED; - if (AVConfig.config.getRequireActivity() && !PlatformMethodWrapper.activity) return BackupCheckEnum.NOACTIVITY; - if (checkMostRecentBackup()) return BackupCheckEnum.TOORECENT; - - return BackupCheckEnum.SUCCESS; - - } - - private static void prepareBackupDestination() { - File file = new File(AVConfig.config.getPath()); - - if (!file.exists()) { - file.mkdirs(); - } - prepareReadMe(file); - - File zipFile = new File(file, "/zips/"); - if (!zipFile.exists()) { - zipFile.mkdirs(); - } - File differential = new File(file, "/differential/"); - if (!differential.exists()) { - differential.mkdirs(); - } - File incremental = new File(file, "/incremental/"); - if (!incremental.exists()) { - incremental.mkdirs(); - } - } - - private static void prepareReadMe(File path) { - File readme = new File(path, "README-BEFORE-RESTORING.txt"); - if (!readme.exists()) { - try { - InputStream is = BackupWrapper.class.getClassLoader().getResourceAsStream("advancedbackups-readme.txt"); - readme.createNewFile(); - FileOutputStream outputStream = new FileOutputStream(readme); - byte[] buf = new byte[1028]; - int n; - while ((n = is.read(buf)) > 0) { - outputStream.write(buf, 0, n); - } - outputStream.flush(); - outputStream.close(); - - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - - } - } - - - public static boolean checkMostRecentBackup() { - // Return true if the time difference between the most recent backup and the backup-to-be - // is less than specified in the config. - - Date date = new Date(); - long configVal = (long) (3600000F * AVConfig.config.getMinTimer()); - return (date.getTime() - mostRecentBackupTime()) < configVal; - } - - - public static long mostRecentBackupTime() { - - File directory = new File(AVConfig.config.getPath()); - - switch(AVConfig.config.getBackupType()) { - case "zip" : { - directory = new File(directory, "/zips/"); - break; - } - case "differential" : { - directory = new File(directory, "/differential/"); - break; - } - case "incremental" : { - directory = new File(directory, "/incremental/"); - break; - } - - } - - File[] files = directory.listFiles(); - long lastModifiedTime = Long.MIN_VALUE; - if (files == null || files.length == 0) return 0L; - for (File file : files) { - if (file.lastModified() > lastModifiedTime && !file.getName().contains("manifest")) { - lastModifiedTime = file.lastModified(); - } - } - return lastModifiedTime; - } - - - public static void makeSingleBackup(long delay) { - - PlatformMethodWrapper.disableSaving(); - if (AVConfig.config.getSave()) { - PlatformMethodWrapper.saveOnce(); - } - - // Make new thread, run backup utility. - ThreadedBackup threadedBackup = new ThreadedBackup(delay); - threadedBackup.start(); - // Don't re-enable saving - leave that down to the backup thread. - - } - - public static void finishBackup() { - File directory = new File(AVConfig.config.getPath()); - ThreadedBackup.running = false; - PlatformMethodWrapper.enableSaving(); - - switch(AVConfig.config.getBackupType()) { - case "zip" : { - directory = new File(directory, "/zips/"); - long date = Long.MIN_VALUE; - while (true) { - if (calculateDirectorySize(directory) < AVConfig.config.getMaxSize() * 1000000000L) return; - File file = getFirstBackupAfterDate(directory, date); - date = file.lastModified(); - file.delete(); - } - } - case "differential" : { - directory = new File(directory, "/differential/"); - long date = Long.MIN_VALUE; - while (true) { - if (calculateDirectorySize(directory) < AVConfig.config.getMaxSize() * 1000000000L) return; - File file = getFirstBackupAfterDate(directory, date); - date = file.lastModified(); - if (file.getName().contains("full")) { - File nextFile = getFirstBackupAfterDate(directory, date); - if (nextFile.getName().contains("partial")) { - nextFile.delete(); - } - else { - file.delete(); - } - } - else { - file.delete(); - } - - } - } - case "incremental" : { - directory = new File(directory, "/incremental/"); - if (!AVConfig.config.getPurgeIncrementals()) return; - long date = Long.MIN_VALUE; - while (true) { - if (calculateDirectorySize(directory) < AVConfig.config.getMaxSize() * 1000000000L) return; - if (calculateChainCount(directory) < 2) return; - PlatformMethodWrapper.errorLogger.accept("Purging incremental backup chain - too much space taken up!"); - File file = getFirstBackupAfterDate(directory, date); - date = file.lastModified(); - if (file.getName().contains("full")) { - file.delete(); - while (true) { - file = getFirstBackupAfterDate(directory, date); - date = file.lastModified(); - if (file.getName().contains("full")) { - file.delete(); - } - else { - break; - } - } - } - else { - file.delete(); - } - - } - } - - } - } - - - public static long calculateDirectorySize(File directory) { - long size = 0; - File[] files = directory.listFiles(); - if (files == null || files.length == 0) return size; - for (File file : files) { - if (file.isFile()) { - size += file.length(); - } - else { - size += calculateDirectorySize(file); - } - } - return size; - } - - public static File getFirstBackupAfterDate(File directory, long date) { - File[] files = directory.listFiles(); - File oldestFile = null; - long currentDate = Long.MAX_VALUE; - if (files == null || files.length == 0) return null; - for (File file : files) { - if (file.lastModified() < currentDate && file.lastModified() > date) { - currentDate = file.lastModified(); - oldestFile = file; - } - } - - return oldestFile; - } - - public static int calculateChainCount(File directory) { - int count = 0; - File[] files = directory.listFiles(); - if (files == null || files.length == 0) return 0; - for (File file : files) { - if (file.getName().contains("full")) { - count++; - } - } - return count; - } -} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java deleted file mode 100644 index b331c31b..00000000 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java +++ /dev/null @@ -1,240 +0,0 @@ -package co.uk.mommyheather.advancedbackups.core.backups; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.FileWriter; -import java.io.IOException; -import java.nio.file.FileVisitResult; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.SimpleFileVisitor; -import java.nio.file.attribute.BasicFileAttributes; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Date; -import java.util.zip.ZipEntry; -import java.util.zip.ZipOutputStream; - - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; - -import co.uk.mommyheather.advancedbackups.PlatformMethodWrapper; -import co.uk.mommyheather.advancedbackups.core.backups.gson.DifferentialManifest; -import co.uk.mommyheather.advancedbackups.core.config.AVConfig; - -public class ThreadedBackup extends Thread { - private static GsonBuilder builder = new GsonBuilder(); - private static Gson gson; - private long delay; - private static int count; - private static float partialSize; - private static float completeSize; - public static boolean running = false; - private static String backupName; - - static { - builder.setPrettyPrinting(); - gson = builder.create(); - } - - public ThreadedBackup(long delay) { - setName("AB Active Backup Thread"); - this.delay = delay; - count = 0; - partialSize = 0F; - completeSize = 0F; - } - - @Override - public void run() { - try { - sleep(delay); - } catch (InterruptedException e) { - return; - } - if (running) { - return; - } - running = true; - - File file = new File(AVConfig.config.getPath()); - backupName = serialiseBackupName(PlatformMethodWrapper.worldDir.getParent().toFile().getName().replaceAll(" ", "_")); - - switch(AVConfig.config.getBackupType()) { - case "zip" : { - makeZipBackup(file); - break; - } - case "differential" : { - makeDifferentialOrIncrementalBackup(file, true); - break; - } - case "incremental" : { - makeDifferentialOrIncrementalBackup(file, false); - break; - } - } - - BackupWrapper.finishBackup(); - } - - - private static void makeZipBackup(File file) { - try { - - File zip = new File(file.toString() + "/zips/", backupName + ".zip"); - PlatformMethodWrapper.infoLogger.accept("Preparing zip backup name: " + zip.getName()); - FileOutputStream outputStream = new FileOutputStream(zip); - ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream); - zipOutputStream.setLevel(AVConfig.config.getCompressionLevel()); - - Files.walkFileTree(PlatformMethodWrapper.worldDir, new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { - Path targetFile; - try { - targetFile = PlatformMethodWrapper.worldDir.relativize(file); - if (targetFile.toFile().getName().compareTo("session.lock") == 0) { - return FileVisitResult.CONTINUE; - } - zipOutputStream.putNextEntry(new ZipEntry(targetFile.toString())); - byte[] bytes = Files.readAllBytes(file); - zipOutputStream.write(bytes, 0, bytes.length); - zipOutputStream.closeEntry(); - - } catch (IOException e) { - // TODO : Scream at user - e.printStackTrace(); - PlatformMethodWrapper.errorLogger.accept(file.toString()); - } - - return FileVisitResult.CONTINUE; - } - }); - zipOutputStream.flush(); - zipOutputStream.close(); - - } catch (IOException e){ - // TODO : Scream at user - e.printStackTrace(); - } - - } - - - private static void makeDifferentialOrIncrementalBackup(File location, boolean differential) { - try { - PlatformMethodWrapper.infoLogger.accept("Preparing " + (differential ? "differential" : "incremental") + " backup name: " + backupName); - long time = 0; - File manifestFile = differential ? new File(location.toString() + "/differential/manifest.json") : new File(location.toString() + "/incremental/manifest.json"); - DifferentialManifest manifest; - if (manifestFile.exists()) { - manifest = gson.fromJson(new String(Files.readAllBytes(manifestFile.toPath())), DifferentialManifest.class); - } - else { - manifest = DifferentialManifest.defaultValues(); - } - - long comp = differential ? manifest.getLastFull() : manifest.getLastPartial(); - ArrayList toBackup = new ArrayList<>(); - ArrayList completeBackup = new ArrayList<>(); - - - boolean completeTemp = manifest.getComplete().size() == 0 || manifest.getChain() >= AVConfig.config.getMaxDepth() ? true : false; - - Files.walkFileTree(PlatformMethodWrapper.worldDir, new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { - Path targetFile; - targetFile = PlatformMethodWrapper.worldDir.relativize(file); - if (targetFile.toFile().getName().compareTo("session.lock") == 0) { - return FileVisitResult.CONTINUE; - } - count++; - completeSize += attributes.size(); - completeBackup.add(targetFile); - if (completeTemp || attributes.lastModifiedTime().toMillis() >= comp) { - toBackup.add(targetFile); - partialSize += attributes.size(); - } - return FileVisitResult.CONTINUE; - } - }); - boolean complete = completeTemp; - if (toBackup.size() >= count) { - complete = true; - } - if ((partialSize / completeSize) * 100F > AVConfig.config.getMaxSizePercent()) { - complete = true; - toBackup.clear(); - toBackup.addAll(completeBackup); - } - - backupName += complete? "-full":"-partial"; - - - - if (AVConfig.config.getCompressChains()) { - File zip = differential ? new File(location.toString() + "/differential/", backupName +".zip") : new File(location.toString() + "/incremental/", backupName +".zip"); - FileOutputStream outputStream = new FileOutputStream(zip); - ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream); - zipOutputStream.setLevel(AVConfig.config.getCompressionLevel()); - - for (Path path : toBackup) { - zipOutputStream.putNextEntry(new ZipEntry(path.toString())); - byte[] bytes = Files.readAllBytes(new File(PlatformMethodWrapper.worldDir.toString(), path.toString()).toPath()); - zipOutputStream.write(bytes, 0, bytes.length); - zipOutputStream.closeEntry(); - } - zipOutputStream.flush(); - zipOutputStream.close(); - - time = zip.lastModified(); - } - else { - File dest = differential ? new File(location.toString() + "/differential/", backupName + "/") :new File(location.toString() + "/incremental/", backupName + "/"); - dest.mkdirs(); - for (Path path : toBackup) { - File out = new File(dest, path.toString()); - if (!out.getParentFile().exists()) { - out.getParentFile().mkdirs(); - } - Files.copy(new File(PlatformMethodWrapper.worldDir.toString(), path.toString()).toPath(), out.toPath()); - } - time = dest.lastModified(); - } - - //Finally, update + write the manifest - if (complete || toBackup.size() >= count) { - manifest.setChain(0); - manifest.getComplete().add(time); - manifest.setLastFull(time); - } - else { - manifest.setChain(manifest.getChain() + 1); - manifest.getPartial().add(new Date().getTime()); - manifest.setLastPartial(new Date().getTime()); - } - - FileWriter writer = new FileWriter(manifestFile); - writer.write(gson.toJson(manifest)); - writer.flush(); - writer.close(); - - } catch (IOException e) { - // TODO Scream at user - e.printStackTrace(); - } - - - } - - - public static String serialiseBackupName(String in) { - Date date = new Date(); - String pattern = "yyyy-MM-dd_hh-mm-ss"; - - return in + "_" + new SimpleDateFormat(pattern).format(date); - } -} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/gson/DifferentialManifest.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/gson/DifferentialManifest.java deleted file mode 100644 index ca1385cc..00000000 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/gson/DifferentialManifest.java +++ /dev/null @@ -1,73 +0,0 @@ -package co.uk.mommyheather.advancedbackups.core.backups.gson; - -import java.util.ArrayList; -import java.util.List; - -public class DifferentialManifest { - private List complete; - private List partial; - private int chain; - private long lastFull; - private long lastPartial; - - - public List getComplete() { - return complete; - } - - - public void setComplete(List complete) { - this.complete = complete; - } - - - public List getPartial() { - return partial; - } - - - public void setPartial(List partial) { - this.partial = partial; - } - - - public int getChain() { - return chain; - } - - - public void setChain(int chain) { - this.chain = chain; - } - - - public long getLastFull() { - return lastFull; - } - - - public void setLastFull(long lastFull) { - this.lastFull = lastFull; - } - - - public long getLastPartial() { - return Math.max(lastFull, lastPartial); - } - - - public void setLastPartial(long lastPartial) { - this.lastPartial = lastPartial; - } - - - public static DifferentialManifest defaultValues() { - DifferentialManifest manifest = new DifferentialManifest(); - manifest.complete = new ArrayList<>(); - manifest.partial = new ArrayList<>(); - manifest.chain = 0; - manifest.lastFull = 0; - manifest.lastPartial = 0; - return manifest; - } -} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java deleted file mode 100644 index b56eed0c..00000000 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java +++ /dev/null @@ -1,165 +0,0 @@ -package co.uk.mommyheather.advancedbackups.core.config; - -import java.io.File; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Properties; - -import co.uk.mommyheather.advancedbackups.PlatformMethodWrapper; -import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; - -public class AVConfig { - - private static final String[] supportedProps = { - "config.advancedbackups.enabled", - "config.advancedbackups.save", - "config.advancedbackups.activity", - "config.advancedbackups.type", - "config.advancedbackups.path", - "config.advancedbackups.size", - "config.advancedbackups.frequency.min", - "config.advancedbackups.frequency.max", - "config.advancedbackups.frequency.uptime", - "config.advancedbackups.frequency.schedule", - "config.advancedbackups.frequency.shutdown", - "config.advancedbackups.frequency.startup", - "config.advancedbackups.frequency.delay", - "config.advancedbackups.logging.silent", - - "config.advancedbackups.zips.compression", - - "config.advancedbackups.chains.length", - "config.advancedbackups.chains.compress", - "config.advancedbackups.chains.smart", - "config.advancedbackups.chains.maxpercent", - - "config.advancedbackups.purge.incrementals" - - }; - - public static ConfigData config; - - public static void loadOrCreateConfig() { - // Called when the config needs to be loaded, but one may not exist. - // Creates a new config it one doesn't exist, then loads it. - File file = new File("./AdvancedBackups.properties"); - if (!file.exists()) { - initConfig(); - } - loadConfig(); - } - - public static void initConfig() { - // Called when no config file is present. - // Create a complete properties file in the cwd - File file = new File("./AdvancedBackups.properties"); - try { - if (!file.exists()) { - file.createNewFile(); - file.setWritable(true); - } - FileWriter writer = new FileWriter(file); - writer.write(ConfigData.defaults()); - writer.close(); - } catch (IOException e) { - // TODO : Scream to user - e.printStackTrace(); - } - - - } - - public static void loadConfig() { - // Called when the config needs to be loaded. - // Populates all values of ConfigData.class - - Properties props = new Properties(); - File file = new File("./AdvancedBackups.properties"); - FileReader reader; - try { - reader = new FileReader(file); - props.load(reader); - } catch (IOException e) { - // TODO : Scream to user - e.printStackTrace(); - } - - config = new ConfigData(); - - config.setEnabled(props.getProperty("config.advancedbackups.enabled", "true")); - config.setSave(props.getProperty("config.advancedbackups.save", "false")); - config.setRequireActivity(props.getProperty("config.advancedbackups.activity", "false")); - config.setBackupType(props.getProperty("config.advancedbackups.type", "differential")); - config.setPath(props.getProperty("config.advancedbackups.path", "./backups")); - config.setMaxSize(props.getProperty("config.advancedbackups.size", "50")); - config.setMinTimer(props.getProperty("config.advancedbackups.frequency.min", "0.5")); - config.setMaxTimer(props.getProperty("config.advancedbackups.frequency.max", "24")); - config.setUptimeSchedule(props.getProperty("config.advancedbackups.frequency.uptime", "true")); - config.setSchedule(props.getProperty("config.advancedbackups.frequency.schedule", "12:00")); - config.setForceOnShutdown(props.getProperty("config.advancedbackups.frequency.shutdown", "false")); - config.setForceOnStartup(props.getProperty("config.advancedbackups.frequency.startup", "false")); - config.setStartupDelay(props.getProperty("config.advancedbackups.frequency.delay", "5")); - config.setSilent(props.getProperty("config.advancedbackups.logging.silent", "false")); - - config.setCompressionLevel(props.getProperty("config.advancedbackups.zips.compression", "5")); - - config.setMaxDepth(props.getProperty("config.advancedbackups.chains.length", "50")); - config.setCompressChains(props.getProperty("config.advancedbackups.chains.compress", "true")); - config.setSmartChains(props.getProperty("config.advancedbackups.chains.smart", "true")); - config.setMaxSizePercent(props.getProperty("config.advancedbackups.chains.maxpercent", "75")); - - config.setPurgeIncrementals(props.getProperty("config.advancedbackups.purge.incrementals", "false")); - - - - String timingsString = config.getSchedule(); - if (timingsString.length() != 0) { - BackupWrapper.configuredPlaytime = new ArrayList<>(); - for (String time : timingsString.split(",")) { - String[] hm = time.split(":"); - long hours = Long.parseLong(hm[0]) * 3600000L; - long mins = Long.parseLong(hm[1]) * 60000; - BackupWrapper.configuredPlaytime.add(hours + mins); - } - } - - boolean flag = false; - - for (String prop : supportedProps) { - if (!props.containsKey(prop)) { - flag = true; - break; - } - } - - if (flag) { - PlatformMethodWrapper.warningLogger.accept("Broken, incomplete or misising config found! Generating new file whilst preserving any existing config values..."); - - File newPropsFile = new File("./AdvancedBackups.properties"); - try { - if (!newPropsFile.exists()) { - newPropsFile.createNewFile(); - } - FileWriter writer = new FileWriter(newPropsFile); - writer.write(ConfigData.config(config.getEnabled(), config.getSave(), - config.getRequireActivity(), config.getBackupType(), config.getPath(), - config.getMaxSize(), config.getMinTimer(), config.getMaxTimer(), - config.getUptimeSchedule(), config.getSchedule(), config.getForceOnShutdown(), - config.getForceOnStartup(), config.getStartupDelay(), config.getSilent(), - config.getCompressionLevel(), config.getMaxDepth(), config.getCompressChains(), - config.getSmartChains(), config.getMaxSizePercent(), config.getPurgeIncrementals() - )); - writer.close(); - } catch (IOException e) { - // TODO : Scream to user - e.printStackTrace(); - - } - loadConfig(); - } - - } - -} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java deleted file mode 100644 index ecf162c9..00000000 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java +++ /dev/null @@ -1,378 +0,0 @@ -package co.uk.mommyheather.advancedbackups.core.config; - -public class ConfigData { - - private Boolean enabled; - //Allows outright disabling of backups. - //OPTIONS = "TRUE", "FALSE" - - private Boolean save; - //Whether to save before a backup. - //OPTIONS = "TRUE", "FALSE" - - private Boolean requireActivity; - //Whether to require player activity between backups. - //OPTIONS = "TRUE", "FALSE" - - private String backupType; - //The type of backup to make. Each has a separate file structure, but only the currently selected backup type is scanned for. - //OPTIONS = "ZIP", "DIFFERENTIAL", "INCREMENTAL" - - private long maxSize; - //Maximum size of backups. With zips, deletes the absolute oldest file if size is exceeded after making a backup, and repeats until below max size. - //RANGE = 5GB - 9999GB - - private float minTimer; - //Ensure this amount of time is waited between backups, in hours. - //RANGE = 0.5 - 500 - - private float maxTimer; - //Triggers a backup if none has already happened within this time. Can be combined with an uptime-based schedule. - //RANGE = 0.5 - 500 - - private boolean uptimeSchedule; - //Whether the schedule is based off of server uptime (true) or world-time (false). - - private String schedule; - //A comma seperated schedule. About it. - - private String path; - //The path for backups. Defaults to ./backups. Can be absolute or relative. - //ANY STRING IS TESTED, WILL CREATE DIRECTORIES IF MISSING - - private Boolean silent; - //Whether to supress all information. Does not affect debug.log. - // TRUE OR FALSE - - private Boolean forceOnShutdown; - //Whether to build a backup when the server shuts down. - // TRUE OR FALSE - - private Boolean forceOnStartup; - //Whether to build a backup when the server starts up. - // TRUE OR FALSE - - //Startup backup delay, in seconds. - private long startupDelay; - - - //BELOW ONLY APPLIES TO ZIP FILES! (affects export command) - private int compressionLevel; - //The compression level to be passed to zip streams. - // RANGE = 1 - 9 - - - //BELOW ONLY APPLIES TO INCREMENTAL AND DIFFERENTIAL BACKUPS! - private int maxDepth; - //The maximum "depth" of partial backups to create before creating a full backup. Higher numbers are reccomended if using incremental. Lower numbers increase storage usage but reduce restoration times. - // RANGE = 5 - 500 - - private boolean compressChains; - //Whether to compress chains. Useful for size reduction and manual restoration. - // TRUE OR FALSE - - private boolean smartChains; - // Smart chain resetting. - // TRUE OR FALSE - - private int maxSizePercent; - // Resets chain length if what gets backed up is over the defined % size. - // 1-100 range. - - private boolean purgeIncrementals; - // Whether to purge incremental backups if over the limit. - // TRUE OR FALSE - - public Boolean getEnabled() { - return enabled; - } - - public void setEnabled(String enabled) { - this.enabled = Boolean.parseBoolean(enabled); - } - - public Boolean getSave() { - return save; - } - - public void setSave(String save) { - this.save = Boolean.parseBoolean(save); - } - - public Boolean getRequireActivity() { - return requireActivity; - } - - public void setRequireActivity(String requireActivity) { - this.requireActivity = Boolean.parseBoolean(requireActivity); - } - - public String getBackupType() { - return backupType; - } - - public void setBackupType(String backupType) { - this.backupType = backupType; - } - - public long getMaxSize() { - return maxSize; - } - - public void setMaxSize(String maxSize) { - this.maxSize = Long.parseLong(maxSize); - } - - public float getMinTimer() { - return minTimer; - } - - public void setMinTimer(String minTimer) { - this.minTimer = Float.parseFloat(minTimer); - } - - - public float getMaxTimer() { - return maxTimer; - } - - public void setUptimeSchedule(String uptimeSchedule) { - this.uptimeSchedule = Boolean.parseBoolean(uptimeSchedule); - } - - public boolean getUptimeSchedule() { - return uptimeSchedule; - } - - public void setSchedule(String schedule) { - this.schedule = schedule; - } - - public String getSchedule() { - return schedule; - } - - public void setMaxTimer(String maxTimer) { - this.maxTimer = Float.parseFloat(maxTimer); - } - - public String getPath() { - return path; - } - - public void setPath(String path) { - this.path = path; - } - - public Boolean getSilent() { - return silent; - } - - public void setSilent(String silent) { - this.silent = Boolean.parseBoolean(silent); - } - - public Boolean getForceOnShutdown() { - return forceOnShutdown; - } - - public void setForceOnShutdown(String forceOnShutdown) { - this.forceOnShutdown = Boolean.parseBoolean(forceOnShutdown); - } - - public Boolean getForceOnStartup() { - return forceOnStartup; - } - - public void setForceOnStartup(String forceOnStartup) { - this.forceOnStartup = Boolean.parseBoolean(forceOnStartup); - } - - public void setStartupDelay(String delay) { - this.startupDelay = Long.parseLong(delay); - } - - public long getStartupDelay() { - return startupDelay; - } - - public int getCompressionLevel() { - return compressionLevel; - } - - public void setCompressionLevel(String compressionLevel) { - this.compressionLevel = Integer.parseInt(compressionLevel); - } - - public int getMaxDepth() { - return maxDepth; - } - - public void setMaxDepth(String maxDepth) { - this.maxDepth = Integer.parseInt(maxDepth); - } - - public boolean getCompressChains() { - return compressChains; - } - - public void setCompressChains(String compressChains) { - this.compressChains = Boolean.parseBoolean(compressChains); - } - - public boolean getSmartChains() { - return smartChains; - } - - public void setSmartChains(String smartChains) { - this.smartChains = Boolean.parseBoolean(smartChains); - } - - - public boolean getPurgeIncrementals() { - return purgeIncrementals; - } - - public void setPurgeIncrementals(String purgeIncrementals) { - this.purgeIncrementals = Boolean.parseBoolean(purgeIncrementals); - } - - public int getMaxSizePercent() { - return maxSizePercent; - } - - public void setMaxSizePercent(String maxSizePercent) { - this.maxSizePercent = Integer.parseInt(maxSizePercent); - } - - - - - //default config output - can be ignored - public static String config(Object enabled, Object save, - Object activity, Object type, Object location, - Object size, Object min, Object max, - Object uptime, Object schedule, Object shutdown, - Object startup, Object delay, Object silent, - Object compression, Object chainLength, Object compressChains, - Object smartChains, Object maxPercent, Object purgeIncrementals) { - return String.join("\n", - -"#Enable or disable automatic backups.", -"#Options : true, false #Default : true,", -"config.advancedbackups.enabled=" + enabled, -"", -"#Whether to save before making a backup.", -"#Options : true, false #Default : false", -"config.advancedbackups.save=" + save, -"", -"#Whether to require player activity between backups.", -"#Options : true, false #Default : false", -"config.advancedbackups.activity=" + activity, -"", -"#The type of backups to use.", -"#Options : zip, differential, incremental #Default : differential", -"config.advancedbackups.type=" + type, -"", -"#The absolute or relative path to the backup location.", -"#Options : any file path. Default : ./backups", -"config.advancedbackups.path=" + location, -"", -"#The maximum size to keep, in GB. Keep relatively high for zips, tighter space requirements should instead use differential or incremental backups.", -"#Range : 5 - 9999 #Default : 50", -"config.advancedbackups.size=" + size, -"", -"#Minimum time between backups, in hours. This can prevent a shutdown backup from triggering immediately after a scheduled backup or similar situations.", -"#Range : 0.5 - 500 #Default : 0.5", -"config.advancedbackups.frequency.min=" + min, -"", -"#Triggers a backup if none has already happened within this time. Can be combined with an uptime-based schedule.", -"#Range : 0.5 - 500 #Default : 24", -"config.advancedbackups.frequency.max=" + max, -"", -"#Whether the schedule below uses uptime (true) or real-world time (false).", -"#Default : true", -"config.advancedbackups.frequency.uptime=" + uptime, -"", -"#When using server uptime:", -" #A looping comma-separated backup schedule, based off of server uptime, hours:minutes. Examples:", -" #4:00 - Makes a backup every four hours.", -" #4:00,7:00 - Makes a backup after four hours, then three, then four, and so on.", -" #1:00 - Makes a backup every hour.", -" #4:00,8:00,12:00,16:00,17:00,18:00,19:00,20:00,21:00,24:00 - Makes a backup following a strict schedule.", -"", -"#When using real-world time:", -" #A strict schedule, using hours:minutes to follow real-world time. Examples:", -" #4:00 - Makes a backup at 4am each day.", -" #4:00,8:00,12:00,16:00,17:00,18:00,19:00,20:00,21:00,24:00 - Makes a backup at specific times of day.", -"", -"#Default : 12:00", -"config.advancedbackups.frequency.schedule=" + schedule, -"", -"#Whether to force a backup on server shutdown. Respects min frequency.", -"#Options : true, false #Default : false", -"config.advancedbackups.frequency.shutdown=" + shutdown, -"", -"#Whether to force a backup on server startup. Respects min frequency.", -"#Options : true, false #Default : false", -"config.advancedbackups.frequency.startup=" + startup, -"", -"#Delay to use after startup, in seconds. Is always at least 5 seconds.", -"#Range : 5-9999999999", -"config.advancedbackups.frequency.delay=" + delay, -"", -"#Whether to disable console and chat logging. Does not affect debug.log, does not affect error messages.", -"#Options : true, false #Default : false", -"config.advancedbackups.logging.silent=" + silent, -"", -"", -"", -"#--------------------------------------------------------------------------------------------------------------------", -"##The following options only affect zip files, whether that's for zip backups, export commands or some other option.", -"#--------------------------------------------------------------------------------------------------------------------", -"", -"#The compression level to use for zip files. Higher numbers space usage, but decrease performance.", -"#Range : 1-9 #Default : 4", -"config.advancedbackups.zips.compression=" + compression, -"", -"", -"", -"#--------------------------------------------------------------------------------------------------------------------", -"##The following options only affect differential and incremental backups.", -"#--------------------------------------------------------------------------------------------------------------------", -"", -"#The maximum 'chain' length to keep.", -"#Range : 5-500 #Default : 50", -"config.advancedbackups.chains.length=" + chainLength, -"", -"#Whether to compress 'chains'. This compresses the base backup and all sequential backups. Reduces space usage, but decreases performance.", -"#Options : true, false #Default : true", -"config.advancedbackups.chains.compress=" + compressChains, -"", -"#Whether to enable \"smart\" reset for chains - if every file is being backed up, mark the backup as complete and reset chain length regardless of intended backup type.", -"#Options : true, false #Default : true", -"config.advancedbackups.chains.smart=" + smartChains, -"", -"#What % of a full backup is allowed to be contained in a partial before forcing it into a full backup. Useful for reducing partial backup size.", -"config.advancedbackups.chains.maxpercent=" + maxPercent, -"", -"#Whether to delete incremental backup chains if max size is exceeded. If not, incremental backups do not respect the max size config and never delete.", -"#Options : true, false #Default : false", -"config.advancedbackups.purge.incrementals=" + purgeIncrementals - - - ); - } - - public static String defaults() { - return config( - "true", "false", "false", - "differential", "./backups", "50", - "0.5", "24", "true", - "12:00", "false", "false", - "5", "false", "4", - "50", "true", "true", - "75","false"); - - } -} From 60f2a74c0067abbf90e244f8f1c7494f5ee2a48c Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Sat, 2 Sep 2023 01:57:11 +0100 Subject: [PATCH 225/580] Support the new system. Yy. --- build.gradle | 6 +- .../advancedbackups/AdvancedBackups.java | 55 +- .../PlatformMethodWrapper.java | 50 - .../cli/AdvancedBackupsCLI.java | 954 ------------------ .../core/CoreCommandSystem.java | 77 -- .../core/backups/BackupCheckEnum.java | 38 - .../core/backups/BackupTimingThread.java | 74 -- .../core/backups/BackupWrapper.java | 273 ----- .../core/backups/ThreadedBackup.java | 240 ----- .../backups/gson/DifferentialManifest.java | 73 -- .../advancedbackups/core/config/AVConfig.java | 165 --- .../core/config/ConfigData.java | 378 ------- 12 files changed, 52 insertions(+), 2331 deletions(-) delete mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/PlatformMethodWrapper.java delete mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java delete mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java delete mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupCheckEnum.java delete mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java delete mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java delete mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java delete mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/core/backups/gson/DifferentialManifest.java delete mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java delete mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java diff --git a/build.gradle b/build.gradle index a7485fe5..6b81fc16 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ plugins { } -version = '1.0' +version = '2.0' group = 'co.uk.mommyheather.advancedbackups' // http://maven.apache.org/guides/mini/guide-naming-conventions.html archivesBaseName = 'AdvancedBackups-' + modloaderName + "-" + minecraftVersion @@ -57,8 +57,8 @@ dependencies { // that the dep is a ForgeGradle 'patcher' dependency. And it's patches will be applied. // The userdev artifact is a special name and will get all sorts of transformations applied to it. minecraft 'net.minecraftforge:forge:1.12.2-14.23.5.2855' - implementation files('dependencies/jansi-2.4.0.jar') - extraLibs files('dependencies/jansi-2.4.0.jar') + implementation files ('../advancedbackups-corelib.jar') + extraLibs files ('../advancedbackups-corelib.jar') // You may put jars on which you depend on in ./libs or you may define them like so.. // compile "some.group:artifact:version:classifier" diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 8b6b231a..f0a33b15 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -2,6 +2,7 @@ import net.minecraft.init.Blocks; import net.minecraft.server.MinecraftServer; +import net.minecraft.world.WorldServer; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod.EventBusSubscriber; import net.minecraftforge.fml.common.Mod.EventHandler; @@ -16,8 +17,9 @@ import org.apache.logging.log4j.Logger; +import co.uk.mommyheather.advancedbackups.core.ABCore; import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; -import co.uk.mommyheather.advancedbackups.core.config.AVConfig; +import co.uk.mommyheather.advancedbackups.core.config.ABConfig; import net.minecraftforge.common.MinecraftForge; import java.io.File; @@ -60,18 +62,29 @@ public AdvancedBackups() public void onServerStarting(FMLServerStartingEvent event) { // Do something when the server starts - AVConfig.loadOrCreateConfig(); + ABConfig.loadOrCreateConfig(); LOGGER.info("Config loaded!!"); - PlatformMethodWrapper.worldName = event.getServer().worlds[0].getWorldInfo().getWorldName(); + ABCore.worldName = event.getServer().worlds[0].getWorldInfo().getWorldName(); + + //Yes, this works. Yes, it feels FUCKING ILLEGAL if (event.getSide() == Side.SERVER) { - PlatformMethodWrapper.worldDir = new File(event.getServer().getFolderName()).toPath(); + ABCore.worldDir = new File(event.getServer().getFolderName(), "./").toPath(); } else { - PlatformMethodWrapper.worldDir = new File("saves/" + event.getServer().getFolderName()).toPath(); + ABCore.worldDir = new File("saves/" + event.getServer().getFolderName(), "./").toPath(); } + // the extra ./ is because some of the code in core calls a getParent as it was required when devving in my forge 1.18 instance, but versions earlier than 1.16 do not have this requirement server = event.getServer(); + ABCore.disableSaving = AdvancedBackups::disableSaving; + ABCore.enableSaving = AdvancedBackups::enableSaving; + ABCore.saveOnce = AdvancedBackups::saveOnce; + + ABCore.infoLogger = infoLogger; + ABCore.warningLogger = warningLogger; + ABCore.errorLogger = errorLogger; + event.registerServerCommand(new AdvancedBackupsCommand()); } @@ -88,7 +101,37 @@ public void onServerStopping(FMLServerStoppingEvent event) { @SubscribeEvent public void onPlayerConnect(PlayerEvent.PlayerLoggedInEvent event) { - PlatformMethodWrapper.activity = true; + ABCore.activity = true; + } + + + + public static final String savesDisabledMessage = "\n\n\n***************************************\nSAVING DISABLED - PREPARING FOR BACKUP!\n***************************************"; + public static final String savesEnabledMessage = "\n\n\n*********************************\nSAVING ENABLED - BACKUP COMPLETE!\n*********************************"; + public static final String saveCompleteMessage = "\n\n\n*************************************\nSAVE COMPLETE - PREPARING FOR BACKUP!\n*************************************"; + + + public static void disableSaving() { + for (WorldServer level : server.worlds) { + if (level != null && !level.disableLevelSaving) { + level.disableLevelSaving = true; + } + } + warningLogger.accept(savesDisabledMessage); + } + + public static void enableSaving() { + for (WorldServer level : server.worlds) { + if (level != null && !level.disableLevelSaving) { + level.disableLevelSaving = false; + } + } + warningLogger.accept(savesEnabledMessage); + } + + public static void saveOnce() { + server.saveAllWorlds(false); + warningLogger.accept(saveCompleteMessage); } } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/PlatformMethodWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/PlatformMethodWrapper.java deleted file mode 100644 index 72fa0e4d..00000000 --- a/src/main/java/co/uk/mommyheather/advancedbackups/PlatformMethodWrapper.java +++ /dev/null @@ -1,50 +0,0 @@ -package co.uk.mommyheather.advancedbackups; - -import java.nio.file.Path; -import java.util.function.Consumer; - -import net.minecraft.server.MinecraftServer; -import net.minecraft.world.World; -import net.minecraft.world.WorldServer; -import net.minecraftforge.fml.server.FMLServerHandler; - -public class PlatformMethodWrapper { - - public static String worldName = ""; - public static Path worldDir = null; - public static Boolean activity = false; - public static final Consumer infoLogger = AdvancedBackups.infoLogger; - public static final Consumer warningLogger = AdvancedBackups.warningLogger; - public static final Consumer errorLogger = AdvancedBackups.errorLogger; - - public static final String savesDisabledMessage = "\n\n\n***************************************\nSAVING DISABLED - PREPARING FOR BACKUP!\n***************************************"; - public static final String savesEnabledMessage = "\n\n\n*********************************\nSAVING ENABLED - BACKUP COMPLETE!\n*********************************"; - public static final String saveCompleteMessage = "\n\n\n*************************************\nSAVE COMPLETE - PREPARING FOR BACKUP!\n*************************************"; - - - public static void disableSaving() { - MinecraftServer server = AdvancedBackups.server; - for (WorldServer level : server.worlds) { - if (level != null && !level.disableLevelSaving) { - level.disableLevelSaving = true; - } - } - warningLogger.accept(savesDisabledMessage); - } - - public static void enableSaving() { - MinecraftServer server = AdvancedBackups.server; - for (WorldServer level : server.worlds) { - if (level != null && !level.disableLevelSaving) { - level.disableLevelSaving = false; - } - } - warningLogger.accept(savesEnabledMessage); - } - - public static void saveOnce() { - MinecraftServer server = AdvancedBackups.server; - server.saveAllWorlds(false); - warningLogger.accept(saveCompleteMessage); - } -} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java deleted file mode 100644 index 5787b961..00000000 --- a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java +++ /dev/null @@ -1,954 +0,0 @@ -package co.uk.mommyheather.advancedbackups.cli; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.FileReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.nio.file.FileSystem; -import java.nio.file.FileSystems; -import java.nio.file.FileVisitResult; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.SimpleFileVisitor; -import java.nio.file.StandardCopyOption; -import java.nio.file.attribute.BasicFileAttributes; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.InputMismatchException; -import java.util.Properties; -import java.util.Scanner; -import java.util.regex.Pattern; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; -import java.util.zip.ZipInputStream; -import java.util.zip.ZipOutputStream; - -import org.fusesource.jansi.AnsiConsole; - -import co.uk.mommyheather.advancedbackups.core.backups.ThreadedBackup; - -public class AdvancedBackupsCLI { - - private static String backupLocation; - private static File serverDir = new File(new File("").toPath().toAbsolutePath().getParent().toString()); - private static String type; - private static Scanner input = new Scanner(System.in); - private static ArrayList fileNames = new ArrayList<>(); - private static File worldFile; - private static String worldPath; - public static void main(String args[]){ - - - System.out.print("\033[H\033[2J"); - System.out.flush(); - - if (System.console() != null) { - AnsiConsole.systemInstall(); //this gets ansi escape codes working on windows. this was a FUCKING PAIN IN MY ASS - } - - - info("Advanced Backups - Version " + AdvancedBackupsCLI.class.getPackage().getImplementationVersion()); - info("Searching for properties...", false); - - Properties props = new Properties(); - File file = new File(serverDir, "AdvancedBackups.properties"); - FileReader reader; - try { - reader = new FileReader(file); - props.load(reader); - - backupLocation = props.getProperty("config.advancedbackups.path"); - type = props.getProperty("config.advancedbackups.type"); - } catch (Exception e) { - error("ERROR LOADING PROPERTIES!"); - error(getStackTrace(e)); - error(""); - error(""); - error("Ensure you're running this from within the mods directory, and the config file is in the parent directory!"); - // Fatal, cannot proceed - return; - } - - if (backupLocation == null || type == null) { - error("ERROR LOADING PROPERTIES!"); - error("Backup location : " + backupLocation); - error("Type : " + type); - // Fatal, cannot proceed - return; - } - - info("Config loaded!"); - - type = getBackupType(); - - worldFile = getWorldFile(); - - if (!worldFile.exists()) { - error("Unable to find world folder!"); - error(worldFile.getAbsolutePath()); - error("Check if the location exists and the name is correct and try again."); - return; - - } - - - File backupDir; - - if (backupLocation.startsWith(Pattern.quote(File.separator))) { - backupDir = new File(backupLocation, File.separator + type + File.separator); - } - else { - backupDir = new File(serverDir, backupLocation.replaceAll(Pattern.quote("." + File.separator), "") + File.separator + type + File.separator); - } - - if (!backupDir.exists()) { - error("Could not find backup directory!"); - error(backupDir.getAbsolutePath()); - error("Have you made any backups before?"); - //Fatal, cannot continue - return; - } - - int backupDateIndex; - try { - backupDateIndex = getBackupDate(backupDir); - } catch (IOException e) { - error("ERROR VIEWING BACKUPS!"); - e.printStackTrace(); - return; - } - - - String restore = restoreWorldOrFile(); - - if (!confirmWarningMessage()) { - error("ABORTED - WILL NOT PROCEED."); - return; - } - - info("Preparing..."); - - - - switch(restore) { - case "world" : { - //No going back now! - //TODO : make a backup of current world state. - deleteEntireWorld(worldFile); - switch(type) { - case "zips" : { - restoreFullZip(backupDateIndex, worldFile); - return; - } - case "differential" : { - restoreFullDifferential(backupDateIndex, worldFile); - return; - } - case "incremental" : { - restoreFullIncremental(backupDateIndex, worldFile); - return; - } - } - } - case "file" : { - switch(type) { - case "zips" : { - restorePartialZip(backupDateIndex, worldFile); - return; - } - case "differential" : { - restorePartialDifferential(backupDateIndex, worldFile); - return; - } - case "incremental" : { - restorePartialIncremental(backupDateIndex, worldFile); - return; - } - } - } - } - - - } - - - - - - - - - - - - - - - - - - - //HELPER METHODS! - private static void info(String out, boolean line) { - if (line) System.out.println(out); - else System.out.print(out); - - } - - private static void warn(String out, boolean line) { - if (line) System.out.println("\u001B[33m" + out + "\u001B[0m"); - else System.out.print("\u001B[33m" + out + "\u001B[0m"); - - } - - private static void error(String out, boolean line) { - if (line) System.out.println("\u001B[31m" + out + "\u001B[0m"); - else System.out.print("\u001B[31m" + out + "\u001B[0m"); - - } - - private static void info(String out) { - info(out, true); - } - - private static void warn(String out) { - warn(out, true); - } - - private static void error(String out) { - error(out, true); - } - - - private static String getStackTrace(final Throwable throwable) { - final StringWriter sw = new StringWriter(); - final PrintWriter pw = new PrintWriter(sw, true); - throwable.printStackTrace(pw); - return sw.getBuffer().toString(); - } - - private static String getBackupType() { - // Select a type of backup to restore - info("Select a backup type to restore. Your server is currently set to use " + type + " backups."); - info("1: zip\n2: differential\n3: incremental"); - info("Enter a number or leave blank for " + type + "."); - int inputType; - try { - String line = input.nextLine(); - if (line == "") { - return type; - } - inputType = Integer.parseInt(line); - } catch (InputMismatchException | NumberFormatException e) { - warn("That was not a number. Please enter a number."); - return getBackupType(); - } - switch (inputType) { - case 1 : return "zips"; - case 2 : return "differential"; - case 3 : return "incremental"; - default : { - warn("Please pick an option between 1 and 3 inclusive."); - return getBackupType(); - } - } - } - - - private static File getWorldFile() { - info("Are you on a client or server?"); - info("1: Client\n2: Server"); - info("Enter a number."); - - int inputType; - File ret = new File(serverDir.getAbsolutePath()); - - try { - String line = input.nextLine(); - if (line == "") { - warn("Please enter a number."); - return getWorldFile(); - } - inputType = Integer.parseInt(line); - } catch (InputMismatchException | NumberFormatException e) { - warn("That was not a number. Please enter a number."); - return getWorldFile(); - } - - if (inputType < 1 || inputType > 2) { - warn("Please enter 1 or 2."); - return getWorldFile(); - } - - if (inputType == 1) { - ret = new File(ret, "/saves/"); - } - - ret = new File(ret, getWorldName(ret)); - return ret; - - } - - private static String getWorldName(File dir) { - ArrayList worlds = new ArrayList<>(); - int worldIndex; - for (File file : dir.listFiles()) { - boolean flag = false; - if (!file.isDirectory()) continue; - for (File file2 : file.listFiles()) { - if (file2.getName().contains("level.dat")) { - flag = true; - } - } - if (flag) { - worlds.add(file.getName()); - } - } - info("Please select your world. Default for servers is \"world\"."); - int index = 1; - for (String world : worlds) { - info (index + ". " + world); - index++; - } - try { - String line = input.nextLine(); - if (line == "") { - warn("Please enter a number."); - return getWorldName(dir); - } - worldIndex = Integer.parseInt(line); - } catch (InputMismatchException | NumberFormatException e) { - warn("That was not a number. Please enter a number."); - return getWorldName(dir); - } - if (worldIndex < 1 || worldIndex > worlds.size()) { - warn("Please enter a number between " + worlds.size() + "."); - return getWorldName(dir); - } - - worldPath = worlds.get(worldIndex -1).replaceAll(" ", "_"); - return worlds.get(worldIndex - 1); - - } - - - private static int getBackupDate(File backupDir) throws IOException { - fileNames.clear(); - int inputType; - - info("Select a backup to restore."); - - for (File file : backupDir.listFiles()) { - if (!file.getName().contains(worldPath)) continue; - fileNames.add(file.getAbsolutePath()); - String out = file.getName(); - out = out.replaceAll(".zip", ""); - out = out.replaceAll(worldPath + "_", ": "); - out = out.replaceAll("-partial", "\u001B[33m partial\u001B[0m"); - out = out.replaceAll("-full", "\u001B[32m full\u001B[0m"); - info(fileNames.size() + out); - } - - try { - String line = input.nextLine(); - if (line == "") { - warn("Please enter a number."); - return getBackupDate(backupDir); - } - inputType = Integer.parseInt(line); - } catch (InputMismatchException | NumberFormatException e) { - warn("That was not a number. Please enter a number."); - return getBackupDate(backupDir); - } - - if (inputType < 1 || inputType > fileNames.size()) { - warn("Please enter a number between " + fileNames.size() + "."); - return getBackupDate(backupDir); - } - - return inputType - 1; - } - - private static String restoreWorldOrFile() { - info("Do you want to restore the entire world state at this point, or a singular file?"); - info("1: Entire world\n2: Single file"); - info("Enter a number."); - int inputType; - try { - String line = input.nextLine(); - if (line == "") { - return type; - } - inputType = Integer.parseInt(line); - } catch (InputMismatchException | NumberFormatException e) { - warn("That was not a number. Please enter a number."); - return restoreWorldOrFile(); - } - switch (inputType) { - case 1 : return "world"; - case 2 : return "file"; - default : { - warn("Please pick 1 or 2."); - return restoreWorldOrFile(); - } - } - - } - - - - private static boolean confirmWarningMessage() { - warn(""); - warn(""); - warn("WARNING! DOING THIS WHILST THE SERVER IS RUNNING CAN CAUSE SEVERE CORRUPTION, PARTIAL RESTORATION, AND OTHER ISSUES."); - warn("TYPE \"continue\" IF YOU WISH TO CONTINUE...", false); - - - String line = input.nextLine(); - if (line.equals("")) { - return confirmWarningMessage(); - } - return line.equals("continue"); - } - - - private static void restoreFullZip(int index, File worldFile) { - byte[] buffer = new byte[1024]; - //The most basic of the bunch. - ZipEntry entry; - try { - FileInputStream fileInputStream = new FileInputStream(fileNames.get(index)); - ZipInputStream zip = new ZipInputStream(fileInputStream); - while ((entry = zip.getNextEntry()) != null) { - File outputFile; - - //FTB Backups and some other mods need special handling. - if (entry.getName().startsWith(worldFile.getName())) { - outputFile = new File(worldFile.getParentFile(), entry.getName()); - } - else { - outputFile = new File(worldFile, entry.getName()); - } - - if (!outputFile.getParentFile().exists()) { - outputFile.getParentFile().mkdirs(); - } - - FileOutputStream outputStream = new FileOutputStream(outputFile); - int length = 0; - while ((length = zip.read(buffer)) > 0) { - outputStream.write(buffer, 0, length); - } - outputStream.close(); - } - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - - private static void restoreFullDifferential(int index, File worldFile) { - //Do we need to check for past backups? if selected is a full backup, we do not. - File backup = new File(fileNames.get(index)); - if (backup.getName().contains("-full")) { - if (backup.isFile()) { - restoreFullZip(index, worldFile); - return; - } - restoreFolder(index, worldFile); - return; - } - //find last FULL backup - for (int i = index;i>0;i--) { - String name = fileNames.get(i); - if (name.contains("-full")) { - info("Restoring last full backup..."); - File file = new File(name); - if (file.isFile()) { - restoreFullZip(i, worldFile); - } - else { - restoreFolder(i, worldFile); - } - break; - } - } - info("\n\nRestoring selected backup..."); - if (backup.isFile()) { - restoreFullZip(index, worldFile); - } - else { - restoreFolder(index, worldFile); - } - } - - private static void restoreFullIncremental(int index, File worldFile) { - //Do we need to check for past backups? if selected is a full backup, we do not. - File backup = new File(fileNames.get(index)); - if (backup.getName().contains("-full")) { - if (backup.isFile()) { - restoreFullZip(index, worldFile); - return; - } - restoreFolder(index, worldFile); - return; - } - //find last FULL backup - int i = index; - while(i >= 0) { - String name = fileNames.get(i); - if (name.contains("-full")) { - info("Restoring last full backup..."); - File file = new File(name); - if (file.isFile()) { - restoreFullZip(i, worldFile); - } - else { - restoreFolder(i, worldFile); - } - break; - } - i--; - } - //restore backups up until the selected one - while(i < index) { - String name = fileNames.get(i); - info("Restoring chained backup..."); - File file = new File(name); - if (file.isFile()) { - restoreFullZip(i, worldFile); - } - else { - restoreFolder(i, worldFile); - } - i++; - } - - - info("\n\nRestoring selected backup..."); - if (backup.isFile()) { - restoreFullZip(index, worldFile); - } - else { - restoreFolder(index, worldFile); - } - } - - private static void restorePartialZip(int index, File worldFile) { - Path file; - HashMap entries = new HashMap<>(); - - try { - FileSystem zipFs = FileSystems.newFileSystem(new File(fileNames.get(index)).toPath(), AdvancedBackupsCLI.class.getClassLoader()); - Path root = zipFs.getPath(""); - Files.walkFileTree(root, new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) throws IOException { - entries.put(file.toString(), file); - return FileVisitResult.CONTINUE; - } - }); - - file = getFileToRestore(entries, ""); - info("Restoring " + file.toString() + "..."); - Path outputFile = new File(worldFile, file.toString()).toPath(); - Files.copy(file, outputFile, StandardCopyOption.REPLACE_EXISTING); - info("Done."); - - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - return; - } - - } - - private static void restorePartialDifferential(int index, File worldFile) { - //Do we need to check for past backups? if selected is a full backup, we do not. - HashMap filePaths = new HashMap<>(); - HashMap dates = new HashMap<>(); - HashMap entryOwners = new HashMap<>(); - try { - File backup = new File(fileNames.get(index)); - if (!backup.getName().contains("-full")) { - //find last FULL backup - for (int i = index;i>=0;i--) { - String name = fileNames.get(i); - if (name.contains("-full")) { - addBackupNamesToLists(new File(name), entryOwners, filePaths, dates, "\u001b[31m"); - break; - } - } - } - - File file = new File(fileNames.get(index)); - addBackupNamesToLists(file, entryOwners, filePaths, dates, "\u001B[32m"); - - HashMap properMapping = new HashMap<>(); - for (String date : dates.keySet()) { - properMapping.put( - date + " " + dates.get(date), - filePaths.get(date) - ); - } - - Object select = getFileToRestore(properMapping, ""); - if (select instanceof Path) { - Path input = (Path) select; - - - if (select.toString().replace("\\", "/").contains("-full/")) { - select = new File( - select.toString().replace("\\", "/") - .split("-full/")[1] - ).toPath(); - } - if (select.toString().replace("\\", "/").contains("-partial/")) { - select = new File( - select.toString().replace("\\", "/") - .split("-partial/")[1] - ).toPath(); - } - - File outputFile = new File(worldFile, select.toString()); - if (!outputFile.getParentFile().exists()) { - outputFile.getParentFile().mkdirs(); - } - info("\n\nRestoring file : " + select); - Files.copy(input, outputFile.toPath(), StandardCopyOption.REPLACE_EXISTING); - } - else if (select instanceof ZipEntry) { - ZipEntry entry = (ZipEntry) select; - - File outputFile = new File(worldFile, entry.toString()); - FileOutputStream outputStream = new FileOutputStream(outputFile); - - info("Restoring " + entry.toString() + "..."); - - byte[] buffer = new byte[1028]; - InputStream inputSteam = entryOwners.get(entry.toString()).getInputStream(entry); - int length; - while ((length = inputSteam.read(buffer, 0, buffer.length)) > 0) { - outputStream.write(buffer, 0, length); - } - outputStream.flush(); - outputStream.close(); - } - - - } - catch (IOException e){ - //TODO : Scream at user - e.printStackTrace(); - } - } - - private static void restorePartialIncremental(int index, File worldFile) { - //Do we need to check for past backups? if selected is a full backup, we do not. - HashMap filePaths = new HashMap<>(); - HashMap dates = new HashMap<>(); - HashMap entryOwners = new HashMap<>(); - try { - File backup = new File(fileNames.get(index)); - if (!backup.getName().contains("-full")) { - int i; - //find last FULL backup - for (i = index;i>=0;i--) { - String name = fileNames.get(i); - if (name.contains("-full")) { - addBackupNamesToLists(new File(name), entryOwners, filePaths, dates, "\u001b[31m"); - break; - } - } - while (i < index) { - String name = fileNames.get(i); - addBackupNamesToLists(new File(name), entryOwners, filePaths, dates, "\u001b[31m"); - i++; - } - - } - - File file = new File(fileNames.get(index)); - addBackupNamesToLists(file, entryOwners, filePaths, dates, "\u001B[32m"); - - HashMap properMapping = new HashMap<>(); - for (String date : dates.keySet()) { - properMapping.put( - date + " " + dates.get(date), - filePaths.get(date) - ); - } - - Object select = getFileToRestore(properMapping, ""); - if (select instanceof Path) { - Path input = (Path) select; - - - if (select.toString().replace("\\", "/").contains("-full/")) { - select = new File( - select.toString().replace("\\", "/") - .split("-full/")[1] - ).toPath(); - } - if (select.toString().replace("\\", "/").contains("-partial/")) { - select = new File( - select.toString().replace("\\", "/") - .split("-partial/")[1] - ).toPath(); - } - - File outputFile = new File(worldFile, select.toString()); - if (!outputFile.getParentFile().exists()) { - outputFile.getParentFile().mkdirs(); - } - info("\n\nRestoring file : " + select); - Files.copy(input, outputFile.toPath(), StandardCopyOption.REPLACE_EXISTING); - } - else if (select instanceof ZipEntry) { - ZipEntry entry = (ZipEntry) select; - - File outputFile = new File(worldFile, entry.toString()); - FileOutputStream outputStream = new FileOutputStream(outputFile); - - info("Restoring " + entry.toString() + "..."); - - byte[] buffer = new byte[1028]; - InputStream inputSteam = entryOwners.get(entry.toString()).getInputStream(entry); - int length; - while ((length = inputSteam.read(buffer, 0, buffer.length)) > 0) { - outputStream.write(buffer, 0, length); - } - outputStream.flush(); - outputStream.close(); - } - - - } - catch (IOException e){ - //TODO : Scream at user - e.printStackTrace(); - } - } - - - private static void restoreFolder(int index, File worldFile) { - File backup = new File(fileNames.get(index)); - - try { - Files.walkFileTree(backup.toPath(), new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) throws IOException { - File source = backup.toPath().relativize(file).toFile(); - File outputFile = new File(worldFile, source.getPath()); - - if (!outputFile.getParentFile().exists()) { - outputFile.getParentFile().mkdirs(); - } - Files.copy(file, outputFile.toPath()); - return FileVisitResult.CONTINUE; - } - }); - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - - - private static void deleteEntireWorld(File worldDir) { - backupExistingWorld(worldDir); - try { - Files.walkFileTree(worldDir.toPath(), new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { - file.toFile().delete(); - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult postVisitDirectory(Path file, java.io.IOException arg1) { - if (file.toFile().listFiles().length == 0) { - file.toFile().delete(); - } - return FileVisitResult.CONTINUE; - } - }); - } catch (IOException e) { - warn("Failed to delete file :"); - e.printStackTrace(); - } - } - - private static void backupExistingWorld(File worldDir) { - try { - File out = new File(worldDir, "../cli" + ThreadedBackup.serialiseBackupName("backup") + ".zip"); - FileOutputStream outputStream = new FileOutputStream(out); - ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream); - zipOutputStream.setLevel(4); - Files.walkFileTree(worldDir.toPath(), new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { - Path targetFile; - try { - targetFile = worldDir.toPath().relativize(file); - if (targetFile.toFile().getName().compareTo("session.lock") == 0) { - return FileVisitResult.CONTINUE; - } - zipOutputStream.putNextEntry(new ZipEntry(targetFile.toString())); - byte[] bytes = Files.readAllBytes(file); - zipOutputStream.write(bytes, 0, bytes.length); - zipOutputStream.closeEntry(); - - } catch (IOException e) { - // TODO : Scream at user - e.printStackTrace(); - } - - return FileVisitResult.CONTINUE; - } - }); - zipOutputStream.flush(); - zipOutputStream.close(); - } catch (Exception e) { - - } - } - - - private static T getFileToRestore(HashMap files, String directory) { - ArrayList toDisplay = new ArrayList<>(); - HashMap keyMap = new HashMap<>(); - int index = 1; - for (String name : files.keySet()) { - String name2 = name.replace("\\", "/"); // this replacement can fix some problems with wsl, and helps keep code neat. - if (name2.contains(directory)) { - name2 = name2.replace(directory, ""); - if (name2.startsWith(worldFile.getName())) { - name2 = name2.replace(worldFile.getName() + "/", ""); - } - if (name2.contains("/")) { - name2 = "\u001B[33mdirectory\u001B[0m " + name2.split("/")[0]; - } - if (!toDisplay.contains(name2)) { - toDisplay.add(name2); - keyMap.put(name2, name); - } - } - } - toDisplay = sortStringsAlphabeticallyWithDirectoryPriority(toDisplay); - info("Choose a file to restore.\n"); - for (String name : toDisplay) { - if (index < 10) { - info(index + ": " + name); - } - else { - info(index + ": " + name); - } - index++; - } - if (!directory.equals("")) { - info(index + ": ../"); - } - - - int userInput; - try { - String line = input.nextLine(); - if (line == "") { - warn("Please enter a number!"); - return getFileToRestore(files, directory); - } - userInput = Integer.parseInt(line); - } catch (InputMismatchException | NumberFormatException e) { - warn("That was not a number. Please enter a number."); - return getFileToRestore(files, directory); - } - - if (userInput <= 0 || userInput > (directory.equals("") ? toDisplay.size() : toDisplay.size() + 1)) { - warn("Please enter a number in the specified range!"); - return getFileToRestore(files, directory); - } - else if (userInput > toDisplay.size()) { - return null; - } - else if (!toDisplay.get(userInput - 1).contains("\u001B[33mdirectory\u001B[0m ")) { - return files.get(keyMap.get(toDisplay.get(userInput -1))); - } - - T result = getFileToRestore(files, directory + toDisplay.get(userInput -1).replace("\u001B[33mdirectory\u001B[0m ", "") + "/"); - if (result != null) { - return result; - } - else { - return getFileToRestore(files, directory); - } - } - - - private static ArrayList sortStringsAlphabeticallyWithDirectoryPriority(ArrayList in) { - ArrayList out = new ArrayList<>(); - Collections.sort(in); - for (String string : in) { - if (string.contains("\u001B[33mdirectory\u001B[0m")) { - out.add(string); - } - } - for (String string : in) { - if (!string.contains("\u001B[33mdirectory\u001B[0m")) { - out.add(string); - } - } - return out; - } - - - private static void addBackupNamesToLists(File file, HashMap entryOwners, HashMap filePaths, - HashMap dates, String colour) throws IOException { - - if (file.isFile()) { - - ZipFile zipFile = new ZipFile(file); - Enumeration entryEnum = zipFile.entries(); - - while (entryEnum.hasMoreElements()) { - ZipEntry entry = entryEnum.nextElement(); - - String backupName = file.toString().replace("\\", "/"); - filePaths.put(entry.toString().replace("\\", "/"), entry); - dates.put(entry.toString().replace("\\", "/"), "\u001b[31m" - + backupName - .substring(backupName.toString().lastIndexOf("/") + 1) - .replace(worldPath + "_", "") - .replace("-full.zip", "") - .replace("-partial.zip", "") - + "\u001B[0m"); - entryOwners.put(entry.toString(), zipFile); - } - } - - else { - Files.walkFileTree(file.toPath(), new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path path, BasicFileAttributes attributes) throws IOException { - String backupName = file.toString().replace("\\", "/"); - filePaths.put(file.toPath().relativize(path).toString().replace("\\", "/"), path); - dates.put(file.toPath().relativize(path).toString().replace("\\", "/"), "\u001b[31m" - + backupName - .substring(backupName.toString().lastIndexOf("/") + 1) - .replace(worldPath + "_", "") - .replace("-full", "") - .replace("-partial", "") - + "\u001B[0m"); - return FileVisitResult.CONTINUE; - } - }); - } - } - -} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java deleted file mode 100644 index 76e59aef..00000000 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java +++ /dev/null @@ -1,77 +0,0 @@ -package co.uk.mommyheather.advancedbackups.core; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileWriter; -import java.nio.file.Files; -import java.util.function.Consumer; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; - -import co.uk.mommyheather.advancedbackups.core.backups.BackupCheckEnum; -import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; -import co.uk.mommyheather.advancedbackups.core.backups.gson.DifferentialManifest; -import co.uk.mommyheather.advancedbackups.core.config.AVConfig; - -public class CoreCommandSystem { - private static GsonBuilder builder = new GsonBuilder(); - private static Gson gson; - static { - builder.setPrettyPrinting(); - gson = builder.create(); - } - - - //These methods are all called by relevant command classes in version specific code - public static void checkBackups(Consumer chat) { - BackupCheckEnum check = BackupWrapper.checkBackups(); - chat.accept(check.getCheckMessage()); - } - - public static void startBackup(Consumer chat) { - BackupCheckEnum check = BackupWrapper.checkBackups(); - chat.accept(check.getCheckMessage()); - if (check.success()) { - chat.accept("Starting backup..."); - BackupWrapper.makeSingleBackup(0); - } - } - - public static void forceBackup(Consumer chat) { - chat.accept("Forcing a backup..."); - BackupWrapper.makeSingleBackup(0); - } - - public static void reloadConfig(Consumer chat) { - chat.accept("Reloading config..."); - AVConfig.loadConfig(); - chat.accept("Done!"); - } - - public static void resetChainLength(Consumer chat) { - chat.accept("Resetting chain length... The next backup will be a complete backup."); - boolean differential = AVConfig.config.getBackupType().equals("differential") ? true : false; - File manifestFile = differential ? new File(AVConfig.config.getPath() + "/differential/manifest.json") : new File(AVConfig.config.getPath() + "/incremental/manifest.json"); - DifferentialManifest manifest; - try { - if (manifestFile.exists()) { - manifest = gson.fromJson(new String(Files.readAllBytes(manifestFile.toPath())), DifferentialManifest.class); - manifest.setChain(manifest.getChain() + AVConfig.config.getMaxDepth()); - FileWriter writer = new FileWriter(manifestFile); - writer.write(gson.toJson(manifest)); - writer.flush(); - writer.close(); - chat.accept("Done!"); - return; - } - else { - chat.accept("No manifest file exists!"); - return; - } - } catch (Exception e) { - chat.accept("Error resetting chain length. - check logs for more info."); - e.printStackTrace(); - } - } -} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupCheckEnum.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupCheckEnum.java deleted file mode 100644 index 06e00e14..00000000 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupCheckEnum.java +++ /dev/null @@ -1,38 +0,0 @@ -package co.uk.mommyheather.advancedbackups.core.backups; - -public enum BackupCheckEnum { - SUCCESS, - DISABLED, - NOACTIVITY, - TOORECENT; - - public boolean success() { - switch (this) { - case SUCCESS: { - return true; - } - default : return false; - } - } - - - public String getCheckMessage() { - switch(this) { - case SUCCESS : { - return "Checks successful!"; - } - case DISABLED : { - return "Backups are disabled!"; - } - case NOACTIVITY : { - return "Player activity is required, but none have been active!"; - } - case TOORECENT : { - return "The time since the last backup is less than the minimum time specified in config!"; - } - default : { - return "You should not see this message, report a bug!"; - } - } - } -} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java deleted file mode 100644 index b346e89c..00000000 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java +++ /dev/null @@ -1,74 +0,0 @@ -package co.uk.mommyheather.advancedbackups.core.backups; - -import java.time.LocalDateTime; -import java.util.ArrayList; - -import co.uk.mommyheather.advancedbackups.core.config.AVConfig; - -public class BackupTimingThread extends Thread { - private int loops = 0; - private int index = 0; - private long prev = 0; - - public BackupTimingThread() { - setName("AB Backup Timing Daemon"); - setDaemon(true); - } - - @Override - public void run() { - while (true) { - try { - long time = calculateNextBackupTime(); - sleep(time); - BackupWrapper.checkAndMakeBackups(); - } catch (InterruptedException e) { - // TODO Scream at user - e.printStackTrace(); - break; - } - } - } - - - private long calculateNextBackupTime() { - long forcedMillis = BackupWrapper.mostRecentBackupTime() + (long) (AVConfig.config.getMaxTimer() * 3600000L); - if (forcedMillis == AVConfig.config.getMaxTimer() * 3600000L || forcedMillis <= System.currentTimeMillis()) forcedMillis = 300000; //sets it to 5m if no backup exists or the timer is already execeeded to get the chain going - else forcedMillis -= System.currentTimeMillis(); - long ret = Long.MAX_VALUE; - if (AVConfig.config.getUptimeSchedule() && !BackupWrapper.configuredPlaytime.isEmpty()) { - ArrayList timings = new ArrayList(BackupWrapper.configuredPlaytime); - if (index >= timings.size()) { - index = 0; - loops++; - } - ret = (timings.get(index) + (timings.get(timings.size() - 1) * loops)); - ret -= prev; - prev += ret; - index++; - } - - else if (!BackupWrapper.configuredPlaytime.isEmpty()) { - long nextTime = 0; - long currentTime = System.currentTimeMillis(); - ArrayList timings = new ArrayList(BackupWrapper.configuredPlaytime); - for (long time : timings) { - if (time >= currentTime) { - nextTime = time; - break; - } - } - ret = nextTime >= currentTime ? nextTime - currentTime : 86640000 - currentTime; - } - - return Math.min(forcedMillis, ret); - - - - - - - } - - -} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java deleted file mode 100644 index f5960e0d..00000000 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java +++ /dev/null @@ -1,273 +0,0 @@ -package co.uk.mommyheather.advancedbackups.core.backups; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.FileWriter; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.StringReader; -import java.util.ArrayList; -import java.util.Date; - - -import co.uk.mommyheather.advancedbackups.PlatformMethodWrapper; -import co.uk.mommyheather.advancedbackups.core.config.AVConfig; - -public class BackupWrapper { - - public static ArrayList configuredPlaytime = new ArrayList<>(); - - - public static void checkStartupBackups () { - if (AVConfig.config.getForceOnStartup()) { - checkAndMakeBackups(Math.max(5000, AVConfig.config.getStartupDelay() * 1000)); - } - - new BackupTimingThread().start(); - } - - public static void checkShutdownBackups() { - if (AVConfig.config.getForceOnShutdown()) { - checkAndMakeBackups(); - } - } - - public static void checkAndMakeBackups(long delay) { - BackupCheckEnum e = checkBackups(); - if (e.success()) { - makeSingleBackup(delay); - } - } - - public static void checkAndMakeBackups() { - checkAndMakeBackups(0); - } - - - public static BackupCheckEnum checkBackups() { - prepareBackupDestination(); - if (!AVConfig.config.getEnabled()) return BackupCheckEnum.DISABLED; - if (AVConfig.config.getRequireActivity() && !PlatformMethodWrapper.activity) return BackupCheckEnum.NOACTIVITY; - if (checkMostRecentBackup()) return BackupCheckEnum.TOORECENT; - - return BackupCheckEnum.SUCCESS; - - } - - private static void prepareBackupDestination() { - File file = new File(AVConfig.config.getPath()); - - if (!file.exists()) { - file.mkdirs(); - } - prepareReadMe(file); - - File zipFile = new File(file, "/zips/"); - if (!zipFile.exists()) { - zipFile.mkdirs(); - } - File differential = new File(file, "/differential/"); - if (!differential.exists()) { - differential.mkdirs(); - } - File incremental = new File(file, "/incremental/"); - if (!incremental.exists()) { - incremental.mkdirs(); - } - } - - private static void prepareReadMe(File path) { - File readme = new File(path, "README-BEFORE-RESTORING.txt"); - if (!readme.exists()) { - try { - InputStream is = BackupWrapper.class.getClassLoader().getResourceAsStream("advancedbackups-readme.txt"); - readme.createNewFile(); - FileOutputStream outputStream = new FileOutputStream(readme); - byte[] buf = new byte[1028]; - int n; - while ((n = is.read(buf)) > 0) { - outputStream.write(buf, 0, n); - } - outputStream.flush(); - outputStream.close(); - - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - - } - } - - - public static boolean checkMostRecentBackup() { - // Return true if the time difference between the most recent backup and the backup-to-be - // is less than specified in the config. - - Date date = new Date(); - long configVal = (long) (3600000F * AVConfig.config.getMinTimer()); - return (date.getTime() - mostRecentBackupTime()) < configVal; - } - - - public static long mostRecentBackupTime() { - - File directory = new File(AVConfig.config.getPath()); - - switch(AVConfig.config.getBackupType()) { - case "zip" : { - directory = new File(directory, "/zips/"); - break; - } - case "differential" : { - directory = new File(directory, "/differential/"); - break; - } - case "incremental" : { - directory = new File(directory, "/incremental/"); - break; - } - - } - - File[] files = directory.listFiles(); - long lastModifiedTime = Long.MIN_VALUE; - if (files == null || files.length == 0) return 0L; - for (File file : files) { - if (file.lastModified() > lastModifiedTime && !file.getName().contains("manifest")) { - lastModifiedTime = file.lastModified(); - } - } - return lastModifiedTime; - } - - - public static void makeSingleBackup(long delay) { - - PlatformMethodWrapper.disableSaving(); - if (AVConfig.config.getSave()) { - PlatformMethodWrapper.saveOnce(); - } - - // Make new thread, run backup utility. - ThreadedBackup threadedBackup = new ThreadedBackup(delay); - threadedBackup.start(); - // Don't re-enable saving - leave that down to the backup thread. - - } - - public static void finishBackup() { - File directory = new File(AVConfig.config.getPath()); - ThreadedBackup.running = false; - PlatformMethodWrapper.enableSaving(); - - switch(AVConfig.config.getBackupType()) { - case "zip" : { - directory = new File(directory, "/zips/"); - long date = Long.MIN_VALUE; - while (true) { - if (calculateDirectorySize(directory) < AVConfig.config.getMaxSize() * 1000000000L) return; - File file = getFirstBackupAfterDate(directory, date); - date = file.lastModified(); - file.delete(); - } - } - case "differential" : { - directory = new File(directory, "/differential/"); - long date = Long.MIN_VALUE; - while (true) { - if (calculateDirectorySize(directory) < AVConfig.config.getMaxSize() * 1000000000L) return; - File file = getFirstBackupAfterDate(directory, date); - date = file.lastModified(); - if (file.getName().contains("full")) { - File nextFile = getFirstBackupAfterDate(directory, date); - if (nextFile.getName().contains("partial")) { - nextFile.delete(); - } - else { - file.delete(); - } - } - else { - file.delete(); - } - - } - } - case "incremental" : { - directory = new File(directory, "/incremental/"); - if (!AVConfig.config.getPurgeIncrementals()) return; - long date = Long.MIN_VALUE; - while (true) { - if (calculateDirectorySize(directory) < AVConfig.config.getMaxSize() * 1000000000L) return; - if (calculateChainCount(directory) < 2) return; - PlatformMethodWrapper.errorLogger.accept("Purging incremental backup chain - too much space taken up!"); - File file = getFirstBackupAfterDate(directory, date); - date = file.lastModified(); - if (file.getName().contains("full")) { - file.delete(); - while (true) { - file = getFirstBackupAfterDate(directory, date); - date = file.lastModified(); - if (file.getName().contains("full")) { - file.delete(); - } - else { - break; - } - } - } - else { - file.delete(); - } - - } - } - - } - } - - - public static long calculateDirectorySize(File directory) { - long size = 0; - File[] files = directory.listFiles(); - if (files == null || files.length == 0) return size; - for (File file : files) { - if (file.isFile()) { - size += file.length(); - } - else { - size += calculateDirectorySize(file); - } - } - return size; - } - - public static File getFirstBackupAfterDate(File directory, long date) { - File[] files = directory.listFiles(); - File oldestFile = null; - long currentDate = Long.MAX_VALUE; - if (files == null || files.length == 0) return null; - for (File file : files) { - if (file.lastModified() < currentDate && file.lastModified() > date) { - currentDate = file.lastModified(); - oldestFile = file; - } - } - - return oldestFile; - } - - public static int calculateChainCount(File directory) { - int count = 0; - File[] files = directory.listFiles(); - if (files == null || files.length == 0) return 0; - for (File file : files) { - if (file.getName().contains("full")) { - count++; - } - } - return count; - } -} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java deleted file mode 100644 index b331c31b..00000000 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java +++ /dev/null @@ -1,240 +0,0 @@ -package co.uk.mommyheather.advancedbackups.core.backups; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.FileWriter; -import java.io.IOException; -import java.nio.file.FileVisitResult; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.SimpleFileVisitor; -import java.nio.file.attribute.BasicFileAttributes; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Date; -import java.util.zip.ZipEntry; -import java.util.zip.ZipOutputStream; - - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; - -import co.uk.mommyheather.advancedbackups.PlatformMethodWrapper; -import co.uk.mommyheather.advancedbackups.core.backups.gson.DifferentialManifest; -import co.uk.mommyheather.advancedbackups.core.config.AVConfig; - -public class ThreadedBackup extends Thread { - private static GsonBuilder builder = new GsonBuilder(); - private static Gson gson; - private long delay; - private static int count; - private static float partialSize; - private static float completeSize; - public static boolean running = false; - private static String backupName; - - static { - builder.setPrettyPrinting(); - gson = builder.create(); - } - - public ThreadedBackup(long delay) { - setName("AB Active Backup Thread"); - this.delay = delay; - count = 0; - partialSize = 0F; - completeSize = 0F; - } - - @Override - public void run() { - try { - sleep(delay); - } catch (InterruptedException e) { - return; - } - if (running) { - return; - } - running = true; - - File file = new File(AVConfig.config.getPath()); - backupName = serialiseBackupName(PlatformMethodWrapper.worldDir.getParent().toFile().getName().replaceAll(" ", "_")); - - switch(AVConfig.config.getBackupType()) { - case "zip" : { - makeZipBackup(file); - break; - } - case "differential" : { - makeDifferentialOrIncrementalBackup(file, true); - break; - } - case "incremental" : { - makeDifferentialOrIncrementalBackup(file, false); - break; - } - } - - BackupWrapper.finishBackup(); - } - - - private static void makeZipBackup(File file) { - try { - - File zip = new File(file.toString() + "/zips/", backupName + ".zip"); - PlatformMethodWrapper.infoLogger.accept("Preparing zip backup name: " + zip.getName()); - FileOutputStream outputStream = new FileOutputStream(zip); - ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream); - zipOutputStream.setLevel(AVConfig.config.getCompressionLevel()); - - Files.walkFileTree(PlatformMethodWrapper.worldDir, new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { - Path targetFile; - try { - targetFile = PlatformMethodWrapper.worldDir.relativize(file); - if (targetFile.toFile().getName().compareTo("session.lock") == 0) { - return FileVisitResult.CONTINUE; - } - zipOutputStream.putNextEntry(new ZipEntry(targetFile.toString())); - byte[] bytes = Files.readAllBytes(file); - zipOutputStream.write(bytes, 0, bytes.length); - zipOutputStream.closeEntry(); - - } catch (IOException e) { - // TODO : Scream at user - e.printStackTrace(); - PlatformMethodWrapper.errorLogger.accept(file.toString()); - } - - return FileVisitResult.CONTINUE; - } - }); - zipOutputStream.flush(); - zipOutputStream.close(); - - } catch (IOException e){ - // TODO : Scream at user - e.printStackTrace(); - } - - } - - - private static void makeDifferentialOrIncrementalBackup(File location, boolean differential) { - try { - PlatformMethodWrapper.infoLogger.accept("Preparing " + (differential ? "differential" : "incremental") + " backup name: " + backupName); - long time = 0; - File manifestFile = differential ? new File(location.toString() + "/differential/manifest.json") : new File(location.toString() + "/incremental/manifest.json"); - DifferentialManifest manifest; - if (manifestFile.exists()) { - manifest = gson.fromJson(new String(Files.readAllBytes(manifestFile.toPath())), DifferentialManifest.class); - } - else { - manifest = DifferentialManifest.defaultValues(); - } - - long comp = differential ? manifest.getLastFull() : manifest.getLastPartial(); - ArrayList toBackup = new ArrayList<>(); - ArrayList completeBackup = new ArrayList<>(); - - - boolean completeTemp = manifest.getComplete().size() == 0 || manifest.getChain() >= AVConfig.config.getMaxDepth() ? true : false; - - Files.walkFileTree(PlatformMethodWrapper.worldDir, new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { - Path targetFile; - targetFile = PlatformMethodWrapper.worldDir.relativize(file); - if (targetFile.toFile().getName().compareTo("session.lock") == 0) { - return FileVisitResult.CONTINUE; - } - count++; - completeSize += attributes.size(); - completeBackup.add(targetFile); - if (completeTemp || attributes.lastModifiedTime().toMillis() >= comp) { - toBackup.add(targetFile); - partialSize += attributes.size(); - } - return FileVisitResult.CONTINUE; - } - }); - boolean complete = completeTemp; - if (toBackup.size() >= count) { - complete = true; - } - if ((partialSize / completeSize) * 100F > AVConfig.config.getMaxSizePercent()) { - complete = true; - toBackup.clear(); - toBackup.addAll(completeBackup); - } - - backupName += complete? "-full":"-partial"; - - - - if (AVConfig.config.getCompressChains()) { - File zip = differential ? new File(location.toString() + "/differential/", backupName +".zip") : new File(location.toString() + "/incremental/", backupName +".zip"); - FileOutputStream outputStream = new FileOutputStream(zip); - ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream); - zipOutputStream.setLevel(AVConfig.config.getCompressionLevel()); - - for (Path path : toBackup) { - zipOutputStream.putNextEntry(new ZipEntry(path.toString())); - byte[] bytes = Files.readAllBytes(new File(PlatformMethodWrapper.worldDir.toString(), path.toString()).toPath()); - zipOutputStream.write(bytes, 0, bytes.length); - zipOutputStream.closeEntry(); - } - zipOutputStream.flush(); - zipOutputStream.close(); - - time = zip.lastModified(); - } - else { - File dest = differential ? new File(location.toString() + "/differential/", backupName + "/") :new File(location.toString() + "/incremental/", backupName + "/"); - dest.mkdirs(); - for (Path path : toBackup) { - File out = new File(dest, path.toString()); - if (!out.getParentFile().exists()) { - out.getParentFile().mkdirs(); - } - Files.copy(new File(PlatformMethodWrapper.worldDir.toString(), path.toString()).toPath(), out.toPath()); - } - time = dest.lastModified(); - } - - //Finally, update + write the manifest - if (complete || toBackup.size() >= count) { - manifest.setChain(0); - manifest.getComplete().add(time); - manifest.setLastFull(time); - } - else { - manifest.setChain(manifest.getChain() + 1); - manifest.getPartial().add(new Date().getTime()); - manifest.setLastPartial(new Date().getTime()); - } - - FileWriter writer = new FileWriter(manifestFile); - writer.write(gson.toJson(manifest)); - writer.flush(); - writer.close(); - - } catch (IOException e) { - // TODO Scream at user - e.printStackTrace(); - } - - - } - - - public static String serialiseBackupName(String in) { - Date date = new Date(); - String pattern = "yyyy-MM-dd_hh-mm-ss"; - - return in + "_" + new SimpleDateFormat(pattern).format(date); - } -} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/gson/DifferentialManifest.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/gson/DifferentialManifest.java deleted file mode 100644 index ca1385cc..00000000 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/gson/DifferentialManifest.java +++ /dev/null @@ -1,73 +0,0 @@ -package co.uk.mommyheather.advancedbackups.core.backups.gson; - -import java.util.ArrayList; -import java.util.List; - -public class DifferentialManifest { - private List complete; - private List partial; - private int chain; - private long lastFull; - private long lastPartial; - - - public List getComplete() { - return complete; - } - - - public void setComplete(List complete) { - this.complete = complete; - } - - - public List getPartial() { - return partial; - } - - - public void setPartial(List partial) { - this.partial = partial; - } - - - public int getChain() { - return chain; - } - - - public void setChain(int chain) { - this.chain = chain; - } - - - public long getLastFull() { - return lastFull; - } - - - public void setLastFull(long lastFull) { - this.lastFull = lastFull; - } - - - public long getLastPartial() { - return Math.max(lastFull, lastPartial); - } - - - public void setLastPartial(long lastPartial) { - this.lastPartial = lastPartial; - } - - - public static DifferentialManifest defaultValues() { - DifferentialManifest manifest = new DifferentialManifest(); - manifest.complete = new ArrayList<>(); - manifest.partial = new ArrayList<>(); - manifest.chain = 0; - manifest.lastFull = 0; - manifest.lastPartial = 0; - return manifest; - } -} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java deleted file mode 100644 index b56eed0c..00000000 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java +++ /dev/null @@ -1,165 +0,0 @@ -package co.uk.mommyheather.advancedbackups.core.config; - -import java.io.File; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Properties; - -import co.uk.mommyheather.advancedbackups.PlatformMethodWrapper; -import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; - -public class AVConfig { - - private static final String[] supportedProps = { - "config.advancedbackups.enabled", - "config.advancedbackups.save", - "config.advancedbackups.activity", - "config.advancedbackups.type", - "config.advancedbackups.path", - "config.advancedbackups.size", - "config.advancedbackups.frequency.min", - "config.advancedbackups.frequency.max", - "config.advancedbackups.frequency.uptime", - "config.advancedbackups.frequency.schedule", - "config.advancedbackups.frequency.shutdown", - "config.advancedbackups.frequency.startup", - "config.advancedbackups.frequency.delay", - "config.advancedbackups.logging.silent", - - "config.advancedbackups.zips.compression", - - "config.advancedbackups.chains.length", - "config.advancedbackups.chains.compress", - "config.advancedbackups.chains.smart", - "config.advancedbackups.chains.maxpercent", - - "config.advancedbackups.purge.incrementals" - - }; - - public static ConfigData config; - - public static void loadOrCreateConfig() { - // Called when the config needs to be loaded, but one may not exist. - // Creates a new config it one doesn't exist, then loads it. - File file = new File("./AdvancedBackups.properties"); - if (!file.exists()) { - initConfig(); - } - loadConfig(); - } - - public static void initConfig() { - // Called when no config file is present. - // Create a complete properties file in the cwd - File file = new File("./AdvancedBackups.properties"); - try { - if (!file.exists()) { - file.createNewFile(); - file.setWritable(true); - } - FileWriter writer = new FileWriter(file); - writer.write(ConfigData.defaults()); - writer.close(); - } catch (IOException e) { - // TODO : Scream to user - e.printStackTrace(); - } - - - } - - public static void loadConfig() { - // Called when the config needs to be loaded. - // Populates all values of ConfigData.class - - Properties props = new Properties(); - File file = new File("./AdvancedBackups.properties"); - FileReader reader; - try { - reader = new FileReader(file); - props.load(reader); - } catch (IOException e) { - // TODO : Scream to user - e.printStackTrace(); - } - - config = new ConfigData(); - - config.setEnabled(props.getProperty("config.advancedbackups.enabled", "true")); - config.setSave(props.getProperty("config.advancedbackups.save", "false")); - config.setRequireActivity(props.getProperty("config.advancedbackups.activity", "false")); - config.setBackupType(props.getProperty("config.advancedbackups.type", "differential")); - config.setPath(props.getProperty("config.advancedbackups.path", "./backups")); - config.setMaxSize(props.getProperty("config.advancedbackups.size", "50")); - config.setMinTimer(props.getProperty("config.advancedbackups.frequency.min", "0.5")); - config.setMaxTimer(props.getProperty("config.advancedbackups.frequency.max", "24")); - config.setUptimeSchedule(props.getProperty("config.advancedbackups.frequency.uptime", "true")); - config.setSchedule(props.getProperty("config.advancedbackups.frequency.schedule", "12:00")); - config.setForceOnShutdown(props.getProperty("config.advancedbackups.frequency.shutdown", "false")); - config.setForceOnStartup(props.getProperty("config.advancedbackups.frequency.startup", "false")); - config.setStartupDelay(props.getProperty("config.advancedbackups.frequency.delay", "5")); - config.setSilent(props.getProperty("config.advancedbackups.logging.silent", "false")); - - config.setCompressionLevel(props.getProperty("config.advancedbackups.zips.compression", "5")); - - config.setMaxDepth(props.getProperty("config.advancedbackups.chains.length", "50")); - config.setCompressChains(props.getProperty("config.advancedbackups.chains.compress", "true")); - config.setSmartChains(props.getProperty("config.advancedbackups.chains.smart", "true")); - config.setMaxSizePercent(props.getProperty("config.advancedbackups.chains.maxpercent", "75")); - - config.setPurgeIncrementals(props.getProperty("config.advancedbackups.purge.incrementals", "false")); - - - - String timingsString = config.getSchedule(); - if (timingsString.length() != 0) { - BackupWrapper.configuredPlaytime = new ArrayList<>(); - for (String time : timingsString.split(",")) { - String[] hm = time.split(":"); - long hours = Long.parseLong(hm[0]) * 3600000L; - long mins = Long.parseLong(hm[1]) * 60000; - BackupWrapper.configuredPlaytime.add(hours + mins); - } - } - - boolean flag = false; - - for (String prop : supportedProps) { - if (!props.containsKey(prop)) { - flag = true; - break; - } - } - - if (flag) { - PlatformMethodWrapper.warningLogger.accept("Broken, incomplete or misising config found! Generating new file whilst preserving any existing config values..."); - - File newPropsFile = new File("./AdvancedBackups.properties"); - try { - if (!newPropsFile.exists()) { - newPropsFile.createNewFile(); - } - FileWriter writer = new FileWriter(newPropsFile); - writer.write(ConfigData.config(config.getEnabled(), config.getSave(), - config.getRequireActivity(), config.getBackupType(), config.getPath(), - config.getMaxSize(), config.getMinTimer(), config.getMaxTimer(), - config.getUptimeSchedule(), config.getSchedule(), config.getForceOnShutdown(), - config.getForceOnStartup(), config.getStartupDelay(), config.getSilent(), - config.getCompressionLevel(), config.getMaxDepth(), config.getCompressChains(), - config.getSmartChains(), config.getMaxSizePercent(), config.getPurgeIncrementals() - )); - writer.close(); - } catch (IOException e) { - // TODO : Scream to user - e.printStackTrace(); - - } - loadConfig(); - } - - } - -} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java deleted file mode 100644 index ecf162c9..00000000 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java +++ /dev/null @@ -1,378 +0,0 @@ -package co.uk.mommyheather.advancedbackups.core.config; - -public class ConfigData { - - private Boolean enabled; - //Allows outright disabling of backups. - //OPTIONS = "TRUE", "FALSE" - - private Boolean save; - //Whether to save before a backup. - //OPTIONS = "TRUE", "FALSE" - - private Boolean requireActivity; - //Whether to require player activity between backups. - //OPTIONS = "TRUE", "FALSE" - - private String backupType; - //The type of backup to make. Each has a separate file structure, but only the currently selected backup type is scanned for. - //OPTIONS = "ZIP", "DIFFERENTIAL", "INCREMENTAL" - - private long maxSize; - //Maximum size of backups. With zips, deletes the absolute oldest file if size is exceeded after making a backup, and repeats until below max size. - //RANGE = 5GB - 9999GB - - private float minTimer; - //Ensure this amount of time is waited between backups, in hours. - //RANGE = 0.5 - 500 - - private float maxTimer; - //Triggers a backup if none has already happened within this time. Can be combined with an uptime-based schedule. - //RANGE = 0.5 - 500 - - private boolean uptimeSchedule; - //Whether the schedule is based off of server uptime (true) or world-time (false). - - private String schedule; - //A comma seperated schedule. About it. - - private String path; - //The path for backups. Defaults to ./backups. Can be absolute or relative. - //ANY STRING IS TESTED, WILL CREATE DIRECTORIES IF MISSING - - private Boolean silent; - //Whether to supress all information. Does not affect debug.log. - // TRUE OR FALSE - - private Boolean forceOnShutdown; - //Whether to build a backup when the server shuts down. - // TRUE OR FALSE - - private Boolean forceOnStartup; - //Whether to build a backup when the server starts up. - // TRUE OR FALSE - - //Startup backup delay, in seconds. - private long startupDelay; - - - //BELOW ONLY APPLIES TO ZIP FILES! (affects export command) - private int compressionLevel; - //The compression level to be passed to zip streams. - // RANGE = 1 - 9 - - - //BELOW ONLY APPLIES TO INCREMENTAL AND DIFFERENTIAL BACKUPS! - private int maxDepth; - //The maximum "depth" of partial backups to create before creating a full backup. Higher numbers are reccomended if using incremental. Lower numbers increase storage usage but reduce restoration times. - // RANGE = 5 - 500 - - private boolean compressChains; - //Whether to compress chains. Useful for size reduction and manual restoration. - // TRUE OR FALSE - - private boolean smartChains; - // Smart chain resetting. - // TRUE OR FALSE - - private int maxSizePercent; - // Resets chain length if what gets backed up is over the defined % size. - // 1-100 range. - - private boolean purgeIncrementals; - // Whether to purge incremental backups if over the limit. - // TRUE OR FALSE - - public Boolean getEnabled() { - return enabled; - } - - public void setEnabled(String enabled) { - this.enabled = Boolean.parseBoolean(enabled); - } - - public Boolean getSave() { - return save; - } - - public void setSave(String save) { - this.save = Boolean.parseBoolean(save); - } - - public Boolean getRequireActivity() { - return requireActivity; - } - - public void setRequireActivity(String requireActivity) { - this.requireActivity = Boolean.parseBoolean(requireActivity); - } - - public String getBackupType() { - return backupType; - } - - public void setBackupType(String backupType) { - this.backupType = backupType; - } - - public long getMaxSize() { - return maxSize; - } - - public void setMaxSize(String maxSize) { - this.maxSize = Long.parseLong(maxSize); - } - - public float getMinTimer() { - return minTimer; - } - - public void setMinTimer(String minTimer) { - this.minTimer = Float.parseFloat(minTimer); - } - - - public float getMaxTimer() { - return maxTimer; - } - - public void setUptimeSchedule(String uptimeSchedule) { - this.uptimeSchedule = Boolean.parseBoolean(uptimeSchedule); - } - - public boolean getUptimeSchedule() { - return uptimeSchedule; - } - - public void setSchedule(String schedule) { - this.schedule = schedule; - } - - public String getSchedule() { - return schedule; - } - - public void setMaxTimer(String maxTimer) { - this.maxTimer = Float.parseFloat(maxTimer); - } - - public String getPath() { - return path; - } - - public void setPath(String path) { - this.path = path; - } - - public Boolean getSilent() { - return silent; - } - - public void setSilent(String silent) { - this.silent = Boolean.parseBoolean(silent); - } - - public Boolean getForceOnShutdown() { - return forceOnShutdown; - } - - public void setForceOnShutdown(String forceOnShutdown) { - this.forceOnShutdown = Boolean.parseBoolean(forceOnShutdown); - } - - public Boolean getForceOnStartup() { - return forceOnStartup; - } - - public void setForceOnStartup(String forceOnStartup) { - this.forceOnStartup = Boolean.parseBoolean(forceOnStartup); - } - - public void setStartupDelay(String delay) { - this.startupDelay = Long.parseLong(delay); - } - - public long getStartupDelay() { - return startupDelay; - } - - public int getCompressionLevel() { - return compressionLevel; - } - - public void setCompressionLevel(String compressionLevel) { - this.compressionLevel = Integer.parseInt(compressionLevel); - } - - public int getMaxDepth() { - return maxDepth; - } - - public void setMaxDepth(String maxDepth) { - this.maxDepth = Integer.parseInt(maxDepth); - } - - public boolean getCompressChains() { - return compressChains; - } - - public void setCompressChains(String compressChains) { - this.compressChains = Boolean.parseBoolean(compressChains); - } - - public boolean getSmartChains() { - return smartChains; - } - - public void setSmartChains(String smartChains) { - this.smartChains = Boolean.parseBoolean(smartChains); - } - - - public boolean getPurgeIncrementals() { - return purgeIncrementals; - } - - public void setPurgeIncrementals(String purgeIncrementals) { - this.purgeIncrementals = Boolean.parseBoolean(purgeIncrementals); - } - - public int getMaxSizePercent() { - return maxSizePercent; - } - - public void setMaxSizePercent(String maxSizePercent) { - this.maxSizePercent = Integer.parseInt(maxSizePercent); - } - - - - - //default config output - can be ignored - public static String config(Object enabled, Object save, - Object activity, Object type, Object location, - Object size, Object min, Object max, - Object uptime, Object schedule, Object shutdown, - Object startup, Object delay, Object silent, - Object compression, Object chainLength, Object compressChains, - Object smartChains, Object maxPercent, Object purgeIncrementals) { - return String.join("\n", - -"#Enable or disable automatic backups.", -"#Options : true, false #Default : true,", -"config.advancedbackups.enabled=" + enabled, -"", -"#Whether to save before making a backup.", -"#Options : true, false #Default : false", -"config.advancedbackups.save=" + save, -"", -"#Whether to require player activity between backups.", -"#Options : true, false #Default : false", -"config.advancedbackups.activity=" + activity, -"", -"#The type of backups to use.", -"#Options : zip, differential, incremental #Default : differential", -"config.advancedbackups.type=" + type, -"", -"#The absolute or relative path to the backup location.", -"#Options : any file path. Default : ./backups", -"config.advancedbackups.path=" + location, -"", -"#The maximum size to keep, in GB. Keep relatively high for zips, tighter space requirements should instead use differential or incremental backups.", -"#Range : 5 - 9999 #Default : 50", -"config.advancedbackups.size=" + size, -"", -"#Minimum time between backups, in hours. This can prevent a shutdown backup from triggering immediately after a scheduled backup or similar situations.", -"#Range : 0.5 - 500 #Default : 0.5", -"config.advancedbackups.frequency.min=" + min, -"", -"#Triggers a backup if none has already happened within this time. Can be combined with an uptime-based schedule.", -"#Range : 0.5 - 500 #Default : 24", -"config.advancedbackups.frequency.max=" + max, -"", -"#Whether the schedule below uses uptime (true) or real-world time (false).", -"#Default : true", -"config.advancedbackups.frequency.uptime=" + uptime, -"", -"#When using server uptime:", -" #A looping comma-separated backup schedule, based off of server uptime, hours:minutes. Examples:", -" #4:00 - Makes a backup every four hours.", -" #4:00,7:00 - Makes a backup after four hours, then three, then four, and so on.", -" #1:00 - Makes a backup every hour.", -" #4:00,8:00,12:00,16:00,17:00,18:00,19:00,20:00,21:00,24:00 - Makes a backup following a strict schedule.", -"", -"#When using real-world time:", -" #A strict schedule, using hours:minutes to follow real-world time. Examples:", -" #4:00 - Makes a backup at 4am each day.", -" #4:00,8:00,12:00,16:00,17:00,18:00,19:00,20:00,21:00,24:00 - Makes a backup at specific times of day.", -"", -"#Default : 12:00", -"config.advancedbackups.frequency.schedule=" + schedule, -"", -"#Whether to force a backup on server shutdown. Respects min frequency.", -"#Options : true, false #Default : false", -"config.advancedbackups.frequency.shutdown=" + shutdown, -"", -"#Whether to force a backup on server startup. Respects min frequency.", -"#Options : true, false #Default : false", -"config.advancedbackups.frequency.startup=" + startup, -"", -"#Delay to use after startup, in seconds. Is always at least 5 seconds.", -"#Range : 5-9999999999", -"config.advancedbackups.frequency.delay=" + delay, -"", -"#Whether to disable console and chat logging. Does not affect debug.log, does not affect error messages.", -"#Options : true, false #Default : false", -"config.advancedbackups.logging.silent=" + silent, -"", -"", -"", -"#--------------------------------------------------------------------------------------------------------------------", -"##The following options only affect zip files, whether that's for zip backups, export commands or some other option.", -"#--------------------------------------------------------------------------------------------------------------------", -"", -"#The compression level to use for zip files. Higher numbers space usage, but decrease performance.", -"#Range : 1-9 #Default : 4", -"config.advancedbackups.zips.compression=" + compression, -"", -"", -"", -"#--------------------------------------------------------------------------------------------------------------------", -"##The following options only affect differential and incremental backups.", -"#--------------------------------------------------------------------------------------------------------------------", -"", -"#The maximum 'chain' length to keep.", -"#Range : 5-500 #Default : 50", -"config.advancedbackups.chains.length=" + chainLength, -"", -"#Whether to compress 'chains'. This compresses the base backup and all sequential backups. Reduces space usage, but decreases performance.", -"#Options : true, false #Default : true", -"config.advancedbackups.chains.compress=" + compressChains, -"", -"#Whether to enable \"smart\" reset for chains - if every file is being backed up, mark the backup as complete and reset chain length regardless of intended backup type.", -"#Options : true, false #Default : true", -"config.advancedbackups.chains.smart=" + smartChains, -"", -"#What % of a full backup is allowed to be contained in a partial before forcing it into a full backup. Useful for reducing partial backup size.", -"config.advancedbackups.chains.maxpercent=" + maxPercent, -"", -"#Whether to delete incremental backup chains if max size is exceeded. If not, incremental backups do not respect the max size config and never delete.", -"#Options : true, false #Default : false", -"config.advancedbackups.purge.incrementals=" + purgeIncrementals - - - ); - } - - public static String defaults() { - return config( - "true", "false", "false", - "differential", "./backups", "50", - "0.5", "24", "true", - "12:00", "false", "false", - "5", "false", "4", - "50", "true", "true", - "75","false"); - - } -} From d622ecd919df5dc09491e778f8d0b281f60fd4c5 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Sat, 2 Sep 2023 02:29:33 +0100 Subject: [PATCH 226/580] 1.7.10 edit to support the core changes --- build.gradle.kts | 8 +- .../advancedbackups/AdvancedBackups.java | 100 +- .../AdvancedBackupsCommand.java | 3 - .../PlatformMethodWrapper.java | 60 -- .../cli/AdvancedBackupsCLI.java | 954 ------------------ .../core/CoreCommandSystem.java | 77 -- .../core/backups/BackupCheckEnum.java | 38 - .../core/backups/BackupTimingThread.java | 74 -- .../core/backups/BackupWrapper.java | 273 ----- .../core/backups/ThreadedBackup.java | 240 ----- .../backups/gson/DifferentialManifest.java | 73 -- .../advancedbackups/core/config/AVConfig.java | 165 --- .../core/config/ConfigData.java | 378 ------- 13 files changed, 80 insertions(+), 2363 deletions(-) delete mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/PlatformMethodWrapper.java delete mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java delete mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java delete mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupCheckEnum.java delete mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java delete mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java delete mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java delete mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/core/backups/gson/DifferentialManifest.java delete mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java delete mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java diff --git a/build.gradle.kts b/build.gradle.kts index 86aef4ff..bf940671 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -10,7 +10,7 @@ plugins { -version = "1.0" +version = "2.0" group = "co.uk.mommyheather.advancedbackups" // http://maven.apache.org/guides/mini/guide-naming-conventions.html //archivesBaseName = "AdvancedBackups-forge-1.7.10" @@ -106,8 +106,8 @@ dependencies { // Adds NotEnoughItems and its dependencies (CCL&CCC) to runClient/runServer runtimeOnlyNonPublishable("com.github.GTNewHorizons:NotEnoughItems:2.3.39-GTNH:dev") - implementation (files("/dependencies/jansi-2.4.0.jar")) - extraLibs (files("/dependencies/jansi-2.4.0.jar")) + implementation (files("../advancedbackups-corelib.jar")) + extraLibs (files("../advancedbackups-corelib.jar")) // Example: grab the ic2 jar from curse maven and deobfuscate // api(rfg.deobf("curse.maven:ic2-242638:2353971")) // Example: grab the ic2 jar from libs/ in the workspace and deobfuscate @@ -135,7 +135,7 @@ publishing { } tasks.withType { - from(zipTree("dependencies/jansi-2.4.0.jar")) + from(zipTree("../advancedbackups-corelib.jar")) into("/") duplicatesStrategy = DuplicatesStrategy.EXCLUDE //from(zipTree("dependencies/jna-platform-5.13.0.jar")) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 0f514d4c..c209df4c 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -1,27 +1,28 @@ package co.uk.mommyheather.advancedbackups; -import cpw.mods.fml.common.FMLCommonHandler; +import net.minecraft.init.Blocks; +import net.minecraft.server.MinecraftServer; +import net.minecraft.world.WorldServer; + +import org.apache.logging.log4j.Logger; + +import co.uk.mommyheather.advancedbackups.core.ABCore; +import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; +import co.uk.mommyheather.advancedbackups.core.config.ABConfig; import cpw.mods.fml.common.Mod; import cpw.mods.fml.common.Mod.EventHandler; -import cpw.mods.fml.common.event.FMLInitializationEvent; +import cpw.mods.fml.common.event.FMLPreInitializationEvent; import cpw.mods.fml.common.event.FMLServerStartedEvent; import cpw.mods.fml.common.event.FMLServerStartingEvent; import cpw.mods.fml.common.event.FMLServerStoppingEvent; import cpw.mods.fml.common.eventhandler.SubscribeEvent; import cpw.mods.fml.common.gameevent.PlayerEvent; import cpw.mods.fml.relauncher.Side; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import net.minecraft.server.MinecraftServer; - - -import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; -import co.uk.mommyheather.advancedbackups.core.config.AVConfig; import net.minecraftforge.common.MinecraftForge; import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.util.function.Consumer; @@ -30,23 +31,22 @@ public class AdvancedBackups { public static final String MODID = "advancedbackups"; public static final String NAME = "Advanced Backups"; - public static final String VERSION = "0.3"; + public static final String VERSION = "2.0"; - private static Logger LOGGER = LogManager.getLogger("AdvancedBackups"); + private static Logger LOGGER; public static Consumer infoLogger; public static Consumer warningLogger; public static Consumer errorLogger; public static MinecraftServer server; - @EventHandler - @SuppressWarnings("unused") - public void init(FMLInitializationEvent ev) { + public void preInit(FMLPreInitializationEvent event) + { + LOGGER = event.getModLog(); infoLogger = LOGGER::info; warningLogger = LOGGER::warn; - errorLogger = LOGGER::error; - AVConfig.loadOrCreateConfig(); //doing this in init is better + errorLogger = LOGGER::error; } @@ -55,29 +55,40 @@ public AdvancedBackups() { // Register ourselves for server and other game events we are interested in MinecraftForge.EVENT_BUS.register(this); - FMLCommonHandler.instance().bus().register(this); } @EventHandler public void onServerStarting(FMLServerStartingEvent event) { // Do something when the server starts - AVConfig.loadConfig(); //and a reload upon server start + ABConfig.loadOrCreateConfig(); LOGGER.info("Config loaded!!"); - PlatformMethodWrapper.worldName = event.getServer().worldServers[0].getWorldInfo().getWorldName(); + ABCore.worldName = event.getServer().worldServers[0].getWorldInfo().getWorldName(); + + //Yes, this works. Yes, it feels FUCKING ILLEGAL if (event.getSide() == Side.SERVER) { - PlatformMethodWrapper.worldDir = new File(event.getServer().getFolderName()).toPath(); + ABCore.worldDir = new File(event.getServer().getFolderName(), "./").toPath(); } else { - PlatformMethodWrapper.worldDir = new File("saves/" + event.getServer().getFolderName()).toPath(); + ABCore.worldDir = new File("saves/" + event.getServer().getFolderName(), "./").toPath(); } + // the extra ./ is because some of the code in core calls a getParent as it was required when devving in my forge 1.18 instance, but versions earlier than 1.16 do not have this requirement server = event.getServer(); + ABCore.disableSaving = AdvancedBackups::disableSaving; + ABCore.enableSaving = AdvancedBackups::enableSaving; + ABCore.saveOnce = AdvancedBackups::saveOnce; + + ABCore.infoLogger = infoLogger; + ABCore.warningLogger = warningLogger; + ABCore.errorLogger = errorLogger; + event.registerServerCommand(new AdvancedBackupsCommand()); } + @EventHandler public void onServerStarted(FMLServerStartedEvent event) { BackupWrapper.checkStartupBackups(); @@ -90,7 +101,48 @@ public void onServerStopping(FMLServerStoppingEvent event) { @SubscribeEvent public void onPlayerConnected(PlayerEvent.PlayerLoggedInEvent event) { - PlatformMethodWrapper.activity = true; + ABCore.activity = true; + } + + + public static final String savesDisabledMessage = "\n\n\n***************************************\nSAVING DISABLED - PREPARING FOR BACKUP!\n***************************************"; + public static final String savesEnabledMessage = "\n\n\n*********************************\nSAVING ENABLED - BACKUP COMPLETE!\n*********************************"; + public static final String saveCompleteMessage = "\n\n\n*************************************\nSAVE COMPLETE - PREPARING FOR BACKUP!\n*************************************"; + + + + public static void disableSaving() { + MinecraftServer server = AdvancedBackups.server; + for (WorldServer level : server.worldServers) { + if (level != null && !level.levelSaving) { + level.levelSaving = true; + } + } + warningLogger.accept(savesDisabledMessage); + } + + public static void enableSaving() { + MinecraftServer server = AdvancedBackups.server; + for (WorldServer level : server.worldServers) { + if (level != null && !level.levelSaving) { + level.levelSaving = false; + } + } + warningLogger.accept(savesEnabledMessage); + } + + public static void saveOnce() { + try { + MinecraftServer server = AdvancedBackups.server; + Class[] classes = {Boolean.class}; + Method saveMethod = MinecraftServer.class.getMethod("saveAllWorlds", classes); + saveMethod.invoke(server, false); + warningLogger.accept(saveCompleteMessage); + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException e) { + // TODO Scream at user + errorLogger.accept("FAILED TO SAVE WORLD!"); + e.printStackTrace(); + } } } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index fe5de121..705a3b4e 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -3,13 +3,10 @@ import co.uk.mommyheather.advancedbackups.core.CoreCommandSystem; import net.minecraft.command.CommandBase; import net.minecraft.command.CommandException; -import net.minecraft.command.ICommand; import net.minecraft.command.ICommandSender; import net.minecraft.command.WrongUsageException; -import net.minecraft.server.MinecraftServer; import net.minecraft.util.ChatComponentText; -import scala.collection.script.Reset; public class AdvancedBackupsCommand extends CommandBase { diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/PlatformMethodWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/PlatformMethodWrapper.java deleted file mode 100644 index 191bf443..00000000 --- a/src/main/java/co/uk/mommyheather/advancedbackups/PlatformMethodWrapper.java +++ /dev/null @@ -1,60 +0,0 @@ -package co.uk.mommyheather.advancedbackups; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.nio.file.Path; -import java.util.function.Consumer; - -import net.minecraft.command.server.CommandSaveOff; -import net.minecraft.server.MinecraftServer; -import net.minecraft.world.World; -import net.minecraft.world.WorldServer; - -public class PlatformMethodWrapper { - - public static String worldName = ""; - public static Path worldDir = null; - public static Boolean activity = false; - public static final Consumer infoLogger = AdvancedBackups.infoLogger; - public static final Consumer warningLogger = AdvancedBackups.warningLogger; - public static final Consumer errorLogger = AdvancedBackups.errorLogger; - - public static final String savesDisabledMessage = "\n\n\n***************************************\nSAVING DISABLED - PREPARING FOR BACKUP!\n***************************************"; - public static final String savesEnabledMessage = "\n\n\n*********************************\nSAVING ENABLED - BACKUP COMPLETE!\n*********************************"; - public static final String saveCompleteMessage = "\n\n\n*************************************\nSAVE COMPLETE - PREPARING FOR BACKUP!\n*************************************"; - - - public static void disableSaving() { - MinecraftServer server = AdvancedBackups.server; - for (WorldServer level : server.worldServers) { - if (level != null && !level.levelSaving) { - level.levelSaving = true; - } - } - warningLogger.accept(savesDisabledMessage); - } - - public static void enableSaving() { - MinecraftServer server = AdvancedBackups.server; - for (WorldServer level : server.worldServers) { - if (level != null && !level.levelSaving) { - level.levelSaving = false; - } - } - warningLogger.accept(savesEnabledMessage); - } - - public static void saveOnce() { - try { - MinecraftServer server = AdvancedBackups.server; - Class[] classes = {Boolean.class}; - Method saveMethod = MinecraftServer.class.getMethod("saveAllWorlds", classes); - saveMethod.invoke(server, false); - warningLogger.accept(saveCompleteMessage); - } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException e) { - // TODO Scream at user - errorLogger.accept("FAILED TO SAVE WORLD!"); - e.printStackTrace(); - } - } -} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java b/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java deleted file mode 100644 index 5787b961..00000000 --- a/src/main/java/co/uk/mommyheather/advancedbackups/cli/AdvancedBackupsCLI.java +++ /dev/null @@ -1,954 +0,0 @@ -package co.uk.mommyheather.advancedbackups.cli; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.FileReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.nio.file.FileSystem; -import java.nio.file.FileSystems; -import java.nio.file.FileVisitResult; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.SimpleFileVisitor; -import java.nio.file.StandardCopyOption; -import java.nio.file.attribute.BasicFileAttributes; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.InputMismatchException; -import java.util.Properties; -import java.util.Scanner; -import java.util.regex.Pattern; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; -import java.util.zip.ZipInputStream; -import java.util.zip.ZipOutputStream; - -import org.fusesource.jansi.AnsiConsole; - -import co.uk.mommyheather.advancedbackups.core.backups.ThreadedBackup; - -public class AdvancedBackupsCLI { - - private static String backupLocation; - private static File serverDir = new File(new File("").toPath().toAbsolutePath().getParent().toString()); - private static String type; - private static Scanner input = new Scanner(System.in); - private static ArrayList fileNames = new ArrayList<>(); - private static File worldFile; - private static String worldPath; - public static void main(String args[]){ - - - System.out.print("\033[H\033[2J"); - System.out.flush(); - - if (System.console() != null) { - AnsiConsole.systemInstall(); //this gets ansi escape codes working on windows. this was a FUCKING PAIN IN MY ASS - } - - - info("Advanced Backups - Version " + AdvancedBackupsCLI.class.getPackage().getImplementationVersion()); - info("Searching for properties...", false); - - Properties props = new Properties(); - File file = new File(serverDir, "AdvancedBackups.properties"); - FileReader reader; - try { - reader = new FileReader(file); - props.load(reader); - - backupLocation = props.getProperty("config.advancedbackups.path"); - type = props.getProperty("config.advancedbackups.type"); - } catch (Exception e) { - error("ERROR LOADING PROPERTIES!"); - error(getStackTrace(e)); - error(""); - error(""); - error("Ensure you're running this from within the mods directory, and the config file is in the parent directory!"); - // Fatal, cannot proceed - return; - } - - if (backupLocation == null || type == null) { - error("ERROR LOADING PROPERTIES!"); - error("Backup location : " + backupLocation); - error("Type : " + type); - // Fatal, cannot proceed - return; - } - - info("Config loaded!"); - - type = getBackupType(); - - worldFile = getWorldFile(); - - if (!worldFile.exists()) { - error("Unable to find world folder!"); - error(worldFile.getAbsolutePath()); - error("Check if the location exists and the name is correct and try again."); - return; - - } - - - File backupDir; - - if (backupLocation.startsWith(Pattern.quote(File.separator))) { - backupDir = new File(backupLocation, File.separator + type + File.separator); - } - else { - backupDir = new File(serverDir, backupLocation.replaceAll(Pattern.quote("." + File.separator), "") + File.separator + type + File.separator); - } - - if (!backupDir.exists()) { - error("Could not find backup directory!"); - error(backupDir.getAbsolutePath()); - error("Have you made any backups before?"); - //Fatal, cannot continue - return; - } - - int backupDateIndex; - try { - backupDateIndex = getBackupDate(backupDir); - } catch (IOException e) { - error("ERROR VIEWING BACKUPS!"); - e.printStackTrace(); - return; - } - - - String restore = restoreWorldOrFile(); - - if (!confirmWarningMessage()) { - error("ABORTED - WILL NOT PROCEED."); - return; - } - - info("Preparing..."); - - - - switch(restore) { - case "world" : { - //No going back now! - //TODO : make a backup of current world state. - deleteEntireWorld(worldFile); - switch(type) { - case "zips" : { - restoreFullZip(backupDateIndex, worldFile); - return; - } - case "differential" : { - restoreFullDifferential(backupDateIndex, worldFile); - return; - } - case "incremental" : { - restoreFullIncremental(backupDateIndex, worldFile); - return; - } - } - } - case "file" : { - switch(type) { - case "zips" : { - restorePartialZip(backupDateIndex, worldFile); - return; - } - case "differential" : { - restorePartialDifferential(backupDateIndex, worldFile); - return; - } - case "incremental" : { - restorePartialIncremental(backupDateIndex, worldFile); - return; - } - } - } - } - - - } - - - - - - - - - - - - - - - - - - - //HELPER METHODS! - private static void info(String out, boolean line) { - if (line) System.out.println(out); - else System.out.print(out); - - } - - private static void warn(String out, boolean line) { - if (line) System.out.println("\u001B[33m" + out + "\u001B[0m"); - else System.out.print("\u001B[33m" + out + "\u001B[0m"); - - } - - private static void error(String out, boolean line) { - if (line) System.out.println("\u001B[31m" + out + "\u001B[0m"); - else System.out.print("\u001B[31m" + out + "\u001B[0m"); - - } - - private static void info(String out) { - info(out, true); - } - - private static void warn(String out) { - warn(out, true); - } - - private static void error(String out) { - error(out, true); - } - - - private static String getStackTrace(final Throwable throwable) { - final StringWriter sw = new StringWriter(); - final PrintWriter pw = new PrintWriter(sw, true); - throwable.printStackTrace(pw); - return sw.getBuffer().toString(); - } - - private static String getBackupType() { - // Select a type of backup to restore - info("Select a backup type to restore. Your server is currently set to use " + type + " backups."); - info("1: zip\n2: differential\n3: incremental"); - info("Enter a number or leave blank for " + type + "."); - int inputType; - try { - String line = input.nextLine(); - if (line == "") { - return type; - } - inputType = Integer.parseInt(line); - } catch (InputMismatchException | NumberFormatException e) { - warn("That was not a number. Please enter a number."); - return getBackupType(); - } - switch (inputType) { - case 1 : return "zips"; - case 2 : return "differential"; - case 3 : return "incremental"; - default : { - warn("Please pick an option between 1 and 3 inclusive."); - return getBackupType(); - } - } - } - - - private static File getWorldFile() { - info("Are you on a client or server?"); - info("1: Client\n2: Server"); - info("Enter a number."); - - int inputType; - File ret = new File(serverDir.getAbsolutePath()); - - try { - String line = input.nextLine(); - if (line == "") { - warn("Please enter a number."); - return getWorldFile(); - } - inputType = Integer.parseInt(line); - } catch (InputMismatchException | NumberFormatException e) { - warn("That was not a number. Please enter a number."); - return getWorldFile(); - } - - if (inputType < 1 || inputType > 2) { - warn("Please enter 1 or 2."); - return getWorldFile(); - } - - if (inputType == 1) { - ret = new File(ret, "/saves/"); - } - - ret = new File(ret, getWorldName(ret)); - return ret; - - } - - private static String getWorldName(File dir) { - ArrayList worlds = new ArrayList<>(); - int worldIndex; - for (File file : dir.listFiles()) { - boolean flag = false; - if (!file.isDirectory()) continue; - for (File file2 : file.listFiles()) { - if (file2.getName().contains("level.dat")) { - flag = true; - } - } - if (flag) { - worlds.add(file.getName()); - } - } - info("Please select your world. Default for servers is \"world\"."); - int index = 1; - for (String world : worlds) { - info (index + ". " + world); - index++; - } - try { - String line = input.nextLine(); - if (line == "") { - warn("Please enter a number."); - return getWorldName(dir); - } - worldIndex = Integer.parseInt(line); - } catch (InputMismatchException | NumberFormatException e) { - warn("That was not a number. Please enter a number."); - return getWorldName(dir); - } - if (worldIndex < 1 || worldIndex > worlds.size()) { - warn("Please enter a number between " + worlds.size() + "."); - return getWorldName(dir); - } - - worldPath = worlds.get(worldIndex -1).replaceAll(" ", "_"); - return worlds.get(worldIndex - 1); - - } - - - private static int getBackupDate(File backupDir) throws IOException { - fileNames.clear(); - int inputType; - - info("Select a backup to restore."); - - for (File file : backupDir.listFiles()) { - if (!file.getName().contains(worldPath)) continue; - fileNames.add(file.getAbsolutePath()); - String out = file.getName(); - out = out.replaceAll(".zip", ""); - out = out.replaceAll(worldPath + "_", ": "); - out = out.replaceAll("-partial", "\u001B[33m partial\u001B[0m"); - out = out.replaceAll("-full", "\u001B[32m full\u001B[0m"); - info(fileNames.size() + out); - } - - try { - String line = input.nextLine(); - if (line == "") { - warn("Please enter a number."); - return getBackupDate(backupDir); - } - inputType = Integer.parseInt(line); - } catch (InputMismatchException | NumberFormatException e) { - warn("That was not a number. Please enter a number."); - return getBackupDate(backupDir); - } - - if (inputType < 1 || inputType > fileNames.size()) { - warn("Please enter a number between " + fileNames.size() + "."); - return getBackupDate(backupDir); - } - - return inputType - 1; - } - - private static String restoreWorldOrFile() { - info("Do you want to restore the entire world state at this point, or a singular file?"); - info("1: Entire world\n2: Single file"); - info("Enter a number."); - int inputType; - try { - String line = input.nextLine(); - if (line == "") { - return type; - } - inputType = Integer.parseInt(line); - } catch (InputMismatchException | NumberFormatException e) { - warn("That was not a number. Please enter a number."); - return restoreWorldOrFile(); - } - switch (inputType) { - case 1 : return "world"; - case 2 : return "file"; - default : { - warn("Please pick 1 or 2."); - return restoreWorldOrFile(); - } - } - - } - - - - private static boolean confirmWarningMessage() { - warn(""); - warn(""); - warn("WARNING! DOING THIS WHILST THE SERVER IS RUNNING CAN CAUSE SEVERE CORRUPTION, PARTIAL RESTORATION, AND OTHER ISSUES."); - warn("TYPE \"continue\" IF YOU WISH TO CONTINUE...", false); - - - String line = input.nextLine(); - if (line.equals("")) { - return confirmWarningMessage(); - } - return line.equals("continue"); - } - - - private static void restoreFullZip(int index, File worldFile) { - byte[] buffer = new byte[1024]; - //The most basic of the bunch. - ZipEntry entry; - try { - FileInputStream fileInputStream = new FileInputStream(fileNames.get(index)); - ZipInputStream zip = new ZipInputStream(fileInputStream); - while ((entry = zip.getNextEntry()) != null) { - File outputFile; - - //FTB Backups and some other mods need special handling. - if (entry.getName().startsWith(worldFile.getName())) { - outputFile = new File(worldFile.getParentFile(), entry.getName()); - } - else { - outputFile = new File(worldFile, entry.getName()); - } - - if (!outputFile.getParentFile().exists()) { - outputFile.getParentFile().mkdirs(); - } - - FileOutputStream outputStream = new FileOutputStream(outputFile); - int length = 0; - while ((length = zip.read(buffer)) > 0) { - outputStream.write(buffer, 0, length); - } - outputStream.close(); - } - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - - private static void restoreFullDifferential(int index, File worldFile) { - //Do we need to check for past backups? if selected is a full backup, we do not. - File backup = new File(fileNames.get(index)); - if (backup.getName().contains("-full")) { - if (backup.isFile()) { - restoreFullZip(index, worldFile); - return; - } - restoreFolder(index, worldFile); - return; - } - //find last FULL backup - for (int i = index;i>0;i--) { - String name = fileNames.get(i); - if (name.contains("-full")) { - info("Restoring last full backup..."); - File file = new File(name); - if (file.isFile()) { - restoreFullZip(i, worldFile); - } - else { - restoreFolder(i, worldFile); - } - break; - } - } - info("\n\nRestoring selected backup..."); - if (backup.isFile()) { - restoreFullZip(index, worldFile); - } - else { - restoreFolder(index, worldFile); - } - } - - private static void restoreFullIncremental(int index, File worldFile) { - //Do we need to check for past backups? if selected is a full backup, we do not. - File backup = new File(fileNames.get(index)); - if (backup.getName().contains("-full")) { - if (backup.isFile()) { - restoreFullZip(index, worldFile); - return; - } - restoreFolder(index, worldFile); - return; - } - //find last FULL backup - int i = index; - while(i >= 0) { - String name = fileNames.get(i); - if (name.contains("-full")) { - info("Restoring last full backup..."); - File file = new File(name); - if (file.isFile()) { - restoreFullZip(i, worldFile); - } - else { - restoreFolder(i, worldFile); - } - break; - } - i--; - } - //restore backups up until the selected one - while(i < index) { - String name = fileNames.get(i); - info("Restoring chained backup..."); - File file = new File(name); - if (file.isFile()) { - restoreFullZip(i, worldFile); - } - else { - restoreFolder(i, worldFile); - } - i++; - } - - - info("\n\nRestoring selected backup..."); - if (backup.isFile()) { - restoreFullZip(index, worldFile); - } - else { - restoreFolder(index, worldFile); - } - } - - private static void restorePartialZip(int index, File worldFile) { - Path file; - HashMap entries = new HashMap<>(); - - try { - FileSystem zipFs = FileSystems.newFileSystem(new File(fileNames.get(index)).toPath(), AdvancedBackupsCLI.class.getClassLoader()); - Path root = zipFs.getPath(""); - Files.walkFileTree(root, new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) throws IOException { - entries.put(file.toString(), file); - return FileVisitResult.CONTINUE; - } - }); - - file = getFileToRestore(entries, ""); - info("Restoring " + file.toString() + "..."); - Path outputFile = new File(worldFile, file.toString()).toPath(); - Files.copy(file, outputFile, StandardCopyOption.REPLACE_EXISTING); - info("Done."); - - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - return; - } - - } - - private static void restorePartialDifferential(int index, File worldFile) { - //Do we need to check for past backups? if selected is a full backup, we do not. - HashMap filePaths = new HashMap<>(); - HashMap dates = new HashMap<>(); - HashMap entryOwners = new HashMap<>(); - try { - File backup = new File(fileNames.get(index)); - if (!backup.getName().contains("-full")) { - //find last FULL backup - for (int i = index;i>=0;i--) { - String name = fileNames.get(i); - if (name.contains("-full")) { - addBackupNamesToLists(new File(name), entryOwners, filePaths, dates, "\u001b[31m"); - break; - } - } - } - - File file = new File(fileNames.get(index)); - addBackupNamesToLists(file, entryOwners, filePaths, dates, "\u001B[32m"); - - HashMap properMapping = new HashMap<>(); - for (String date : dates.keySet()) { - properMapping.put( - date + " " + dates.get(date), - filePaths.get(date) - ); - } - - Object select = getFileToRestore(properMapping, ""); - if (select instanceof Path) { - Path input = (Path) select; - - - if (select.toString().replace("\\", "/").contains("-full/")) { - select = new File( - select.toString().replace("\\", "/") - .split("-full/")[1] - ).toPath(); - } - if (select.toString().replace("\\", "/").contains("-partial/")) { - select = new File( - select.toString().replace("\\", "/") - .split("-partial/")[1] - ).toPath(); - } - - File outputFile = new File(worldFile, select.toString()); - if (!outputFile.getParentFile().exists()) { - outputFile.getParentFile().mkdirs(); - } - info("\n\nRestoring file : " + select); - Files.copy(input, outputFile.toPath(), StandardCopyOption.REPLACE_EXISTING); - } - else if (select instanceof ZipEntry) { - ZipEntry entry = (ZipEntry) select; - - File outputFile = new File(worldFile, entry.toString()); - FileOutputStream outputStream = new FileOutputStream(outputFile); - - info("Restoring " + entry.toString() + "..."); - - byte[] buffer = new byte[1028]; - InputStream inputSteam = entryOwners.get(entry.toString()).getInputStream(entry); - int length; - while ((length = inputSteam.read(buffer, 0, buffer.length)) > 0) { - outputStream.write(buffer, 0, length); - } - outputStream.flush(); - outputStream.close(); - } - - - } - catch (IOException e){ - //TODO : Scream at user - e.printStackTrace(); - } - } - - private static void restorePartialIncremental(int index, File worldFile) { - //Do we need to check for past backups? if selected is a full backup, we do not. - HashMap filePaths = new HashMap<>(); - HashMap dates = new HashMap<>(); - HashMap entryOwners = new HashMap<>(); - try { - File backup = new File(fileNames.get(index)); - if (!backup.getName().contains("-full")) { - int i; - //find last FULL backup - for (i = index;i>=0;i--) { - String name = fileNames.get(i); - if (name.contains("-full")) { - addBackupNamesToLists(new File(name), entryOwners, filePaths, dates, "\u001b[31m"); - break; - } - } - while (i < index) { - String name = fileNames.get(i); - addBackupNamesToLists(new File(name), entryOwners, filePaths, dates, "\u001b[31m"); - i++; - } - - } - - File file = new File(fileNames.get(index)); - addBackupNamesToLists(file, entryOwners, filePaths, dates, "\u001B[32m"); - - HashMap properMapping = new HashMap<>(); - for (String date : dates.keySet()) { - properMapping.put( - date + " " + dates.get(date), - filePaths.get(date) - ); - } - - Object select = getFileToRestore(properMapping, ""); - if (select instanceof Path) { - Path input = (Path) select; - - - if (select.toString().replace("\\", "/").contains("-full/")) { - select = new File( - select.toString().replace("\\", "/") - .split("-full/")[1] - ).toPath(); - } - if (select.toString().replace("\\", "/").contains("-partial/")) { - select = new File( - select.toString().replace("\\", "/") - .split("-partial/")[1] - ).toPath(); - } - - File outputFile = new File(worldFile, select.toString()); - if (!outputFile.getParentFile().exists()) { - outputFile.getParentFile().mkdirs(); - } - info("\n\nRestoring file : " + select); - Files.copy(input, outputFile.toPath(), StandardCopyOption.REPLACE_EXISTING); - } - else if (select instanceof ZipEntry) { - ZipEntry entry = (ZipEntry) select; - - File outputFile = new File(worldFile, entry.toString()); - FileOutputStream outputStream = new FileOutputStream(outputFile); - - info("Restoring " + entry.toString() + "..."); - - byte[] buffer = new byte[1028]; - InputStream inputSteam = entryOwners.get(entry.toString()).getInputStream(entry); - int length; - while ((length = inputSteam.read(buffer, 0, buffer.length)) > 0) { - outputStream.write(buffer, 0, length); - } - outputStream.flush(); - outputStream.close(); - } - - - } - catch (IOException e){ - //TODO : Scream at user - e.printStackTrace(); - } - } - - - private static void restoreFolder(int index, File worldFile) { - File backup = new File(fileNames.get(index)); - - try { - Files.walkFileTree(backup.toPath(), new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) throws IOException { - File source = backup.toPath().relativize(file).toFile(); - File outputFile = new File(worldFile, source.getPath()); - - if (!outputFile.getParentFile().exists()) { - outputFile.getParentFile().mkdirs(); - } - Files.copy(file, outputFile.toPath()); - return FileVisitResult.CONTINUE; - } - }); - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - - - private static void deleteEntireWorld(File worldDir) { - backupExistingWorld(worldDir); - try { - Files.walkFileTree(worldDir.toPath(), new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { - file.toFile().delete(); - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult postVisitDirectory(Path file, java.io.IOException arg1) { - if (file.toFile().listFiles().length == 0) { - file.toFile().delete(); - } - return FileVisitResult.CONTINUE; - } - }); - } catch (IOException e) { - warn("Failed to delete file :"); - e.printStackTrace(); - } - } - - private static void backupExistingWorld(File worldDir) { - try { - File out = new File(worldDir, "../cli" + ThreadedBackup.serialiseBackupName("backup") + ".zip"); - FileOutputStream outputStream = new FileOutputStream(out); - ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream); - zipOutputStream.setLevel(4); - Files.walkFileTree(worldDir.toPath(), new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { - Path targetFile; - try { - targetFile = worldDir.toPath().relativize(file); - if (targetFile.toFile().getName().compareTo("session.lock") == 0) { - return FileVisitResult.CONTINUE; - } - zipOutputStream.putNextEntry(new ZipEntry(targetFile.toString())); - byte[] bytes = Files.readAllBytes(file); - zipOutputStream.write(bytes, 0, bytes.length); - zipOutputStream.closeEntry(); - - } catch (IOException e) { - // TODO : Scream at user - e.printStackTrace(); - } - - return FileVisitResult.CONTINUE; - } - }); - zipOutputStream.flush(); - zipOutputStream.close(); - } catch (Exception e) { - - } - } - - - private static T getFileToRestore(HashMap files, String directory) { - ArrayList toDisplay = new ArrayList<>(); - HashMap keyMap = new HashMap<>(); - int index = 1; - for (String name : files.keySet()) { - String name2 = name.replace("\\", "/"); // this replacement can fix some problems with wsl, and helps keep code neat. - if (name2.contains(directory)) { - name2 = name2.replace(directory, ""); - if (name2.startsWith(worldFile.getName())) { - name2 = name2.replace(worldFile.getName() + "/", ""); - } - if (name2.contains("/")) { - name2 = "\u001B[33mdirectory\u001B[0m " + name2.split("/")[0]; - } - if (!toDisplay.contains(name2)) { - toDisplay.add(name2); - keyMap.put(name2, name); - } - } - } - toDisplay = sortStringsAlphabeticallyWithDirectoryPriority(toDisplay); - info("Choose a file to restore.\n"); - for (String name : toDisplay) { - if (index < 10) { - info(index + ": " + name); - } - else { - info(index + ": " + name); - } - index++; - } - if (!directory.equals("")) { - info(index + ": ../"); - } - - - int userInput; - try { - String line = input.nextLine(); - if (line == "") { - warn("Please enter a number!"); - return getFileToRestore(files, directory); - } - userInput = Integer.parseInt(line); - } catch (InputMismatchException | NumberFormatException e) { - warn("That was not a number. Please enter a number."); - return getFileToRestore(files, directory); - } - - if (userInput <= 0 || userInput > (directory.equals("") ? toDisplay.size() : toDisplay.size() + 1)) { - warn("Please enter a number in the specified range!"); - return getFileToRestore(files, directory); - } - else if (userInput > toDisplay.size()) { - return null; - } - else if (!toDisplay.get(userInput - 1).contains("\u001B[33mdirectory\u001B[0m ")) { - return files.get(keyMap.get(toDisplay.get(userInput -1))); - } - - T result = getFileToRestore(files, directory + toDisplay.get(userInput -1).replace("\u001B[33mdirectory\u001B[0m ", "") + "/"); - if (result != null) { - return result; - } - else { - return getFileToRestore(files, directory); - } - } - - - private static ArrayList sortStringsAlphabeticallyWithDirectoryPriority(ArrayList in) { - ArrayList out = new ArrayList<>(); - Collections.sort(in); - for (String string : in) { - if (string.contains("\u001B[33mdirectory\u001B[0m")) { - out.add(string); - } - } - for (String string : in) { - if (!string.contains("\u001B[33mdirectory\u001B[0m")) { - out.add(string); - } - } - return out; - } - - - private static void addBackupNamesToLists(File file, HashMap entryOwners, HashMap filePaths, - HashMap dates, String colour) throws IOException { - - if (file.isFile()) { - - ZipFile zipFile = new ZipFile(file); - Enumeration entryEnum = zipFile.entries(); - - while (entryEnum.hasMoreElements()) { - ZipEntry entry = entryEnum.nextElement(); - - String backupName = file.toString().replace("\\", "/"); - filePaths.put(entry.toString().replace("\\", "/"), entry); - dates.put(entry.toString().replace("\\", "/"), "\u001b[31m" - + backupName - .substring(backupName.toString().lastIndexOf("/") + 1) - .replace(worldPath + "_", "") - .replace("-full.zip", "") - .replace("-partial.zip", "") - + "\u001B[0m"); - entryOwners.put(entry.toString(), zipFile); - } - } - - else { - Files.walkFileTree(file.toPath(), new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path path, BasicFileAttributes attributes) throws IOException { - String backupName = file.toString().replace("\\", "/"); - filePaths.put(file.toPath().relativize(path).toString().replace("\\", "/"), path); - dates.put(file.toPath().relativize(path).toString().replace("\\", "/"), "\u001b[31m" - + backupName - .substring(backupName.toString().lastIndexOf("/") + 1) - .replace(worldPath + "_", "") - .replace("-full", "") - .replace("-partial", "") - + "\u001B[0m"); - return FileVisitResult.CONTINUE; - } - }); - } - } - -} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java deleted file mode 100644 index 76e59aef..00000000 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/CoreCommandSystem.java +++ /dev/null @@ -1,77 +0,0 @@ -package co.uk.mommyheather.advancedbackups.core; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileWriter; -import java.nio.file.Files; -import java.util.function.Consumer; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; - -import co.uk.mommyheather.advancedbackups.core.backups.BackupCheckEnum; -import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; -import co.uk.mommyheather.advancedbackups.core.backups.gson.DifferentialManifest; -import co.uk.mommyheather.advancedbackups.core.config.AVConfig; - -public class CoreCommandSystem { - private static GsonBuilder builder = new GsonBuilder(); - private static Gson gson; - static { - builder.setPrettyPrinting(); - gson = builder.create(); - } - - - //These methods are all called by relevant command classes in version specific code - public static void checkBackups(Consumer chat) { - BackupCheckEnum check = BackupWrapper.checkBackups(); - chat.accept(check.getCheckMessage()); - } - - public static void startBackup(Consumer chat) { - BackupCheckEnum check = BackupWrapper.checkBackups(); - chat.accept(check.getCheckMessage()); - if (check.success()) { - chat.accept("Starting backup..."); - BackupWrapper.makeSingleBackup(0); - } - } - - public static void forceBackup(Consumer chat) { - chat.accept("Forcing a backup..."); - BackupWrapper.makeSingleBackup(0); - } - - public static void reloadConfig(Consumer chat) { - chat.accept("Reloading config..."); - AVConfig.loadConfig(); - chat.accept("Done!"); - } - - public static void resetChainLength(Consumer chat) { - chat.accept("Resetting chain length... The next backup will be a complete backup."); - boolean differential = AVConfig.config.getBackupType().equals("differential") ? true : false; - File manifestFile = differential ? new File(AVConfig.config.getPath() + "/differential/manifest.json") : new File(AVConfig.config.getPath() + "/incremental/manifest.json"); - DifferentialManifest manifest; - try { - if (manifestFile.exists()) { - manifest = gson.fromJson(new String(Files.readAllBytes(manifestFile.toPath())), DifferentialManifest.class); - manifest.setChain(manifest.getChain() + AVConfig.config.getMaxDepth()); - FileWriter writer = new FileWriter(manifestFile); - writer.write(gson.toJson(manifest)); - writer.flush(); - writer.close(); - chat.accept("Done!"); - return; - } - else { - chat.accept("No manifest file exists!"); - return; - } - } catch (Exception e) { - chat.accept("Error resetting chain length. - check logs for more info."); - e.printStackTrace(); - } - } -} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupCheckEnum.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupCheckEnum.java deleted file mode 100644 index 06e00e14..00000000 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupCheckEnum.java +++ /dev/null @@ -1,38 +0,0 @@ -package co.uk.mommyheather.advancedbackups.core.backups; - -public enum BackupCheckEnum { - SUCCESS, - DISABLED, - NOACTIVITY, - TOORECENT; - - public boolean success() { - switch (this) { - case SUCCESS: { - return true; - } - default : return false; - } - } - - - public String getCheckMessage() { - switch(this) { - case SUCCESS : { - return "Checks successful!"; - } - case DISABLED : { - return "Backups are disabled!"; - } - case NOACTIVITY : { - return "Player activity is required, but none have been active!"; - } - case TOORECENT : { - return "The time since the last backup is less than the minimum time specified in config!"; - } - default : { - return "You should not see this message, report a bug!"; - } - } - } -} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java deleted file mode 100644 index b346e89c..00000000 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupTimingThread.java +++ /dev/null @@ -1,74 +0,0 @@ -package co.uk.mommyheather.advancedbackups.core.backups; - -import java.time.LocalDateTime; -import java.util.ArrayList; - -import co.uk.mommyheather.advancedbackups.core.config.AVConfig; - -public class BackupTimingThread extends Thread { - private int loops = 0; - private int index = 0; - private long prev = 0; - - public BackupTimingThread() { - setName("AB Backup Timing Daemon"); - setDaemon(true); - } - - @Override - public void run() { - while (true) { - try { - long time = calculateNextBackupTime(); - sleep(time); - BackupWrapper.checkAndMakeBackups(); - } catch (InterruptedException e) { - // TODO Scream at user - e.printStackTrace(); - break; - } - } - } - - - private long calculateNextBackupTime() { - long forcedMillis = BackupWrapper.mostRecentBackupTime() + (long) (AVConfig.config.getMaxTimer() * 3600000L); - if (forcedMillis == AVConfig.config.getMaxTimer() * 3600000L || forcedMillis <= System.currentTimeMillis()) forcedMillis = 300000; //sets it to 5m if no backup exists or the timer is already execeeded to get the chain going - else forcedMillis -= System.currentTimeMillis(); - long ret = Long.MAX_VALUE; - if (AVConfig.config.getUptimeSchedule() && !BackupWrapper.configuredPlaytime.isEmpty()) { - ArrayList timings = new ArrayList(BackupWrapper.configuredPlaytime); - if (index >= timings.size()) { - index = 0; - loops++; - } - ret = (timings.get(index) + (timings.get(timings.size() - 1) * loops)); - ret -= prev; - prev += ret; - index++; - } - - else if (!BackupWrapper.configuredPlaytime.isEmpty()) { - long nextTime = 0; - long currentTime = System.currentTimeMillis(); - ArrayList timings = new ArrayList(BackupWrapper.configuredPlaytime); - for (long time : timings) { - if (time >= currentTime) { - nextTime = time; - break; - } - } - ret = nextTime >= currentTime ? nextTime - currentTime : 86640000 - currentTime; - } - - return Math.min(forcedMillis, ret); - - - - - - - } - - -} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java deleted file mode 100644 index f5960e0d..00000000 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/BackupWrapper.java +++ /dev/null @@ -1,273 +0,0 @@ -package co.uk.mommyheather.advancedbackups.core.backups; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.FileWriter; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.StringReader; -import java.util.ArrayList; -import java.util.Date; - - -import co.uk.mommyheather.advancedbackups.PlatformMethodWrapper; -import co.uk.mommyheather.advancedbackups.core.config.AVConfig; - -public class BackupWrapper { - - public static ArrayList configuredPlaytime = new ArrayList<>(); - - - public static void checkStartupBackups () { - if (AVConfig.config.getForceOnStartup()) { - checkAndMakeBackups(Math.max(5000, AVConfig.config.getStartupDelay() * 1000)); - } - - new BackupTimingThread().start(); - } - - public static void checkShutdownBackups() { - if (AVConfig.config.getForceOnShutdown()) { - checkAndMakeBackups(); - } - } - - public static void checkAndMakeBackups(long delay) { - BackupCheckEnum e = checkBackups(); - if (e.success()) { - makeSingleBackup(delay); - } - } - - public static void checkAndMakeBackups() { - checkAndMakeBackups(0); - } - - - public static BackupCheckEnum checkBackups() { - prepareBackupDestination(); - if (!AVConfig.config.getEnabled()) return BackupCheckEnum.DISABLED; - if (AVConfig.config.getRequireActivity() && !PlatformMethodWrapper.activity) return BackupCheckEnum.NOACTIVITY; - if (checkMostRecentBackup()) return BackupCheckEnum.TOORECENT; - - return BackupCheckEnum.SUCCESS; - - } - - private static void prepareBackupDestination() { - File file = new File(AVConfig.config.getPath()); - - if (!file.exists()) { - file.mkdirs(); - } - prepareReadMe(file); - - File zipFile = new File(file, "/zips/"); - if (!zipFile.exists()) { - zipFile.mkdirs(); - } - File differential = new File(file, "/differential/"); - if (!differential.exists()) { - differential.mkdirs(); - } - File incremental = new File(file, "/incremental/"); - if (!incremental.exists()) { - incremental.mkdirs(); - } - } - - private static void prepareReadMe(File path) { - File readme = new File(path, "README-BEFORE-RESTORING.txt"); - if (!readme.exists()) { - try { - InputStream is = BackupWrapper.class.getClassLoader().getResourceAsStream("advancedbackups-readme.txt"); - readme.createNewFile(); - FileOutputStream outputStream = new FileOutputStream(readme); - byte[] buf = new byte[1028]; - int n; - while ((n = is.read(buf)) > 0) { - outputStream.write(buf, 0, n); - } - outputStream.flush(); - outputStream.close(); - - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - - } - } - - - public static boolean checkMostRecentBackup() { - // Return true if the time difference between the most recent backup and the backup-to-be - // is less than specified in the config. - - Date date = new Date(); - long configVal = (long) (3600000F * AVConfig.config.getMinTimer()); - return (date.getTime() - mostRecentBackupTime()) < configVal; - } - - - public static long mostRecentBackupTime() { - - File directory = new File(AVConfig.config.getPath()); - - switch(AVConfig.config.getBackupType()) { - case "zip" : { - directory = new File(directory, "/zips/"); - break; - } - case "differential" : { - directory = new File(directory, "/differential/"); - break; - } - case "incremental" : { - directory = new File(directory, "/incremental/"); - break; - } - - } - - File[] files = directory.listFiles(); - long lastModifiedTime = Long.MIN_VALUE; - if (files == null || files.length == 0) return 0L; - for (File file : files) { - if (file.lastModified() > lastModifiedTime && !file.getName().contains("manifest")) { - lastModifiedTime = file.lastModified(); - } - } - return lastModifiedTime; - } - - - public static void makeSingleBackup(long delay) { - - PlatformMethodWrapper.disableSaving(); - if (AVConfig.config.getSave()) { - PlatformMethodWrapper.saveOnce(); - } - - // Make new thread, run backup utility. - ThreadedBackup threadedBackup = new ThreadedBackup(delay); - threadedBackup.start(); - // Don't re-enable saving - leave that down to the backup thread. - - } - - public static void finishBackup() { - File directory = new File(AVConfig.config.getPath()); - ThreadedBackup.running = false; - PlatformMethodWrapper.enableSaving(); - - switch(AVConfig.config.getBackupType()) { - case "zip" : { - directory = new File(directory, "/zips/"); - long date = Long.MIN_VALUE; - while (true) { - if (calculateDirectorySize(directory) < AVConfig.config.getMaxSize() * 1000000000L) return; - File file = getFirstBackupAfterDate(directory, date); - date = file.lastModified(); - file.delete(); - } - } - case "differential" : { - directory = new File(directory, "/differential/"); - long date = Long.MIN_VALUE; - while (true) { - if (calculateDirectorySize(directory) < AVConfig.config.getMaxSize() * 1000000000L) return; - File file = getFirstBackupAfterDate(directory, date); - date = file.lastModified(); - if (file.getName().contains("full")) { - File nextFile = getFirstBackupAfterDate(directory, date); - if (nextFile.getName().contains("partial")) { - nextFile.delete(); - } - else { - file.delete(); - } - } - else { - file.delete(); - } - - } - } - case "incremental" : { - directory = new File(directory, "/incremental/"); - if (!AVConfig.config.getPurgeIncrementals()) return; - long date = Long.MIN_VALUE; - while (true) { - if (calculateDirectorySize(directory) < AVConfig.config.getMaxSize() * 1000000000L) return; - if (calculateChainCount(directory) < 2) return; - PlatformMethodWrapper.errorLogger.accept("Purging incremental backup chain - too much space taken up!"); - File file = getFirstBackupAfterDate(directory, date); - date = file.lastModified(); - if (file.getName().contains("full")) { - file.delete(); - while (true) { - file = getFirstBackupAfterDate(directory, date); - date = file.lastModified(); - if (file.getName().contains("full")) { - file.delete(); - } - else { - break; - } - } - } - else { - file.delete(); - } - - } - } - - } - } - - - public static long calculateDirectorySize(File directory) { - long size = 0; - File[] files = directory.listFiles(); - if (files == null || files.length == 0) return size; - for (File file : files) { - if (file.isFile()) { - size += file.length(); - } - else { - size += calculateDirectorySize(file); - } - } - return size; - } - - public static File getFirstBackupAfterDate(File directory, long date) { - File[] files = directory.listFiles(); - File oldestFile = null; - long currentDate = Long.MAX_VALUE; - if (files == null || files.length == 0) return null; - for (File file : files) { - if (file.lastModified() < currentDate && file.lastModified() > date) { - currentDate = file.lastModified(); - oldestFile = file; - } - } - - return oldestFile; - } - - public static int calculateChainCount(File directory) { - int count = 0; - File[] files = directory.listFiles(); - if (files == null || files.length == 0) return 0; - for (File file : files) { - if (file.getName().contains("full")) { - count++; - } - } - return count; - } -} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java deleted file mode 100644 index b331c31b..00000000 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/ThreadedBackup.java +++ /dev/null @@ -1,240 +0,0 @@ -package co.uk.mommyheather.advancedbackups.core.backups; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.FileWriter; -import java.io.IOException; -import java.nio.file.FileVisitResult; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.SimpleFileVisitor; -import java.nio.file.attribute.BasicFileAttributes; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Date; -import java.util.zip.ZipEntry; -import java.util.zip.ZipOutputStream; - - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; - -import co.uk.mommyheather.advancedbackups.PlatformMethodWrapper; -import co.uk.mommyheather.advancedbackups.core.backups.gson.DifferentialManifest; -import co.uk.mommyheather.advancedbackups.core.config.AVConfig; - -public class ThreadedBackup extends Thread { - private static GsonBuilder builder = new GsonBuilder(); - private static Gson gson; - private long delay; - private static int count; - private static float partialSize; - private static float completeSize; - public static boolean running = false; - private static String backupName; - - static { - builder.setPrettyPrinting(); - gson = builder.create(); - } - - public ThreadedBackup(long delay) { - setName("AB Active Backup Thread"); - this.delay = delay; - count = 0; - partialSize = 0F; - completeSize = 0F; - } - - @Override - public void run() { - try { - sleep(delay); - } catch (InterruptedException e) { - return; - } - if (running) { - return; - } - running = true; - - File file = new File(AVConfig.config.getPath()); - backupName = serialiseBackupName(PlatformMethodWrapper.worldDir.getParent().toFile().getName().replaceAll(" ", "_")); - - switch(AVConfig.config.getBackupType()) { - case "zip" : { - makeZipBackup(file); - break; - } - case "differential" : { - makeDifferentialOrIncrementalBackup(file, true); - break; - } - case "incremental" : { - makeDifferentialOrIncrementalBackup(file, false); - break; - } - } - - BackupWrapper.finishBackup(); - } - - - private static void makeZipBackup(File file) { - try { - - File zip = new File(file.toString() + "/zips/", backupName + ".zip"); - PlatformMethodWrapper.infoLogger.accept("Preparing zip backup name: " + zip.getName()); - FileOutputStream outputStream = new FileOutputStream(zip); - ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream); - zipOutputStream.setLevel(AVConfig.config.getCompressionLevel()); - - Files.walkFileTree(PlatformMethodWrapper.worldDir, new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { - Path targetFile; - try { - targetFile = PlatformMethodWrapper.worldDir.relativize(file); - if (targetFile.toFile().getName().compareTo("session.lock") == 0) { - return FileVisitResult.CONTINUE; - } - zipOutputStream.putNextEntry(new ZipEntry(targetFile.toString())); - byte[] bytes = Files.readAllBytes(file); - zipOutputStream.write(bytes, 0, bytes.length); - zipOutputStream.closeEntry(); - - } catch (IOException e) { - // TODO : Scream at user - e.printStackTrace(); - PlatformMethodWrapper.errorLogger.accept(file.toString()); - } - - return FileVisitResult.CONTINUE; - } - }); - zipOutputStream.flush(); - zipOutputStream.close(); - - } catch (IOException e){ - // TODO : Scream at user - e.printStackTrace(); - } - - } - - - private static void makeDifferentialOrIncrementalBackup(File location, boolean differential) { - try { - PlatformMethodWrapper.infoLogger.accept("Preparing " + (differential ? "differential" : "incremental") + " backup name: " + backupName); - long time = 0; - File manifestFile = differential ? new File(location.toString() + "/differential/manifest.json") : new File(location.toString() + "/incremental/manifest.json"); - DifferentialManifest manifest; - if (manifestFile.exists()) { - manifest = gson.fromJson(new String(Files.readAllBytes(manifestFile.toPath())), DifferentialManifest.class); - } - else { - manifest = DifferentialManifest.defaultValues(); - } - - long comp = differential ? manifest.getLastFull() : manifest.getLastPartial(); - ArrayList toBackup = new ArrayList<>(); - ArrayList completeBackup = new ArrayList<>(); - - - boolean completeTemp = manifest.getComplete().size() == 0 || manifest.getChain() >= AVConfig.config.getMaxDepth() ? true : false; - - Files.walkFileTree(PlatformMethodWrapper.worldDir, new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { - Path targetFile; - targetFile = PlatformMethodWrapper.worldDir.relativize(file); - if (targetFile.toFile().getName().compareTo("session.lock") == 0) { - return FileVisitResult.CONTINUE; - } - count++; - completeSize += attributes.size(); - completeBackup.add(targetFile); - if (completeTemp || attributes.lastModifiedTime().toMillis() >= comp) { - toBackup.add(targetFile); - partialSize += attributes.size(); - } - return FileVisitResult.CONTINUE; - } - }); - boolean complete = completeTemp; - if (toBackup.size() >= count) { - complete = true; - } - if ((partialSize / completeSize) * 100F > AVConfig.config.getMaxSizePercent()) { - complete = true; - toBackup.clear(); - toBackup.addAll(completeBackup); - } - - backupName += complete? "-full":"-partial"; - - - - if (AVConfig.config.getCompressChains()) { - File zip = differential ? new File(location.toString() + "/differential/", backupName +".zip") : new File(location.toString() + "/incremental/", backupName +".zip"); - FileOutputStream outputStream = new FileOutputStream(zip); - ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream); - zipOutputStream.setLevel(AVConfig.config.getCompressionLevel()); - - for (Path path : toBackup) { - zipOutputStream.putNextEntry(new ZipEntry(path.toString())); - byte[] bytes = Files.readAllBytes(new File(PlatformMethodWrapper.worldDir.toString(), path.toString()).toPath()); - zipOutputStream.write(bytes, 0, bytes.length); - zipOutputStream.closeEntry(); - } - zipOutputStream.flush(); - zipOutputStream.close(); - - time = zip.lastModified(); - } - else { - File dest = differential ? new File(location.toString() + "/differential/", backupName + "/") :new File(location.toString() + "/incremental/", backupName + "/"); - dest.mkdirs(); - for (Path path : toBackup) { - File out = new File(dest, path.toString()); - if (!out.getParentFile().exists()) { - out.getParentFile().mkdirs(); - } - Files.copy(new File(PlatformMethodWrapper.worldDir.toString(), path.toString()).toPath(), out.toPath()); - } - time = dest.lastModified(); - } - - //Finally, update + write the manifest - if (complete || toBackup.size() >= count) { - manifest.setChain(0); - manifest.getComplete().add(time); - manifest.setLastFull(time); - } - else { - manifest.setChain(manifest.getChain() + 1); - manifest.getPartial().add(new Date().getTime()); - manifest.setLastPartial(new Date().getTime()); - } - - FileWriter writer = new FileWriter(manifestFile); - writer.write(gson.toJson(manifest)); - writer.flush(); - writer.close(); - - } catch (IOException e) { - // TODO Scream at user - e.printStackTrace(); - } - - - } - - - public static String serialiseBackupName(String in) { - Date date = new Date(); - String pattern = "yyyy-MM-dd_hh-mm-ss"; - - return in + "_" + new SimpleDateFormat(pattern).format(date); - } -} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/gson/DifferentialManifest.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/gson/DifferentialManifest.java deleted file mode 100644 index ca1385cc..00000000 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/backups/gson/DifferentialManifest.java +++ /dev/null @@ -1,73 +0,0 @@ -package co.uk.mommyheather.advancedbackups.core.backups.gson; - -import java.util.ArrayList; -import java.util.List; - -public class DifferentialManifest { - private List complete; - private List partial; - private int chain; - private long lastFull; - private long lastPartial; - - - public List getComplete() { - return complete; - } - - - public void setComplete(List complete) { - this.complete = complete; - } - - - public List getPartial() { - return partial; - } - - - public void setPartial(List partial) { - this.partial = partial; - } - - - public int getChain() { - return chain; - } - - - public void setChain(int chain) { - this.chain = chain; - } - - - public long getLastFull() { - return lastFull; - } - - - public void setLastFull(long lastFull) { - this.lastFull = lastFull; - } - - - public long getLastPartial() { - return Math.max(lastFull, lastPartial); - } - - - public void setLastPartial(long lastPartial) { - this.lastPartial = lastPartial; - } - - - public static DifferentialManifest defaultValues() { - DifferentialManifest manifest = new DifferentialManifest(); - manifest.complete = new ArrayList<>(); - manifest.partial = new ArrayList<>(); - manifest.chain = 0; - manifest.lastFull = 0; - manifest.lastPartial = 0; - return manifest; - } -} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java deleted file mode 100644 index b56eed0c..00000000 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/AVConfig.java +++ /dev/null @@ -1,165 +0,0 @@ -package co.uk.mommyheather.advancedbackups.core.config; - -import java.io.File; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Properties; - -import co.uk.mommyheather.advancedbackups.PlatformMethodWrapper; -import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; - -public class AVConfig { - - private static final String[] supportedProps = { - "config.advancedbackups.enabled", - "config.advancedbackups.save", - "config.advancedbackups.activity", - "config.advancedbackups.type", - "config.advancedbackups.path", - "config.advancedbackups.size", - "config.advancedbackups.frequency.min", - "config.advancedbackups.frequency.max", - "config.advancedbackups.frequency.uptime", - "config.advancedbackups.frequency.schedule", - "config.advancedbackups.frequency.shutdown", - "config.advancedbackups.frequency.startup", - "config.advancedbackups.frequency.delay", - "config.advancedbackups.logging.silent", - - "config.advancedbackups.zips.compression", - - "config.advancedbackups.chains.length", - "config.advancedbackups.chains.compress", - "config.advancedbackups.chains.smart", - "config.advancedbackups.chains.maxpercent", - - "config.advancedbackups.purge.incrementals" - - }; - - public static ConfigData config; - - public static void loadOrCreateConfig() { - // Called when the config needs to be loaded, but one may not exist. - // Creates a new config it one doesn't exist, then loads it. - File file = new File("./AdvancedBackups.properties"); - if (!file.exists()) { - initConfig(); - } - loadConfig(); - } - - public static void initConfig() { - // Called when no config file is present. - // Create a complete properties file in the cwd - File file = new File("./AdvancedBackups.properties"); - try { - if (!file.exists()) { - file.createNewFile(); - file.setWritable(true); - } - FileWriter writer = new FileWriter(file); - writer.write(ConfigData.defaults()); - writer.close(); - } catch (IOException e) { - // TODO : Scream to user - e.printStackTrace(); - } - - - } - - public static void loadConfig() { - // Called when the config needs to be loaded. - // Populates all values of ConfigData.class - - Properties props = new Properties(); - File file = new File("./AdvancedBackups.properties"); - FileReader reader; - try { - reader = new FileReader(file); - props.load(reader); - } catch (IOException e) { - // TODO : Scream to user - e.printStackTrace(); - } - - config = new ConfigData(); - - config.setEnabled(props.getProperty("config.advancedbackups.enabled", "true")); - config.setSave(props.getProperty("config.advancedbackups.save", "false")); - config.setRequireActivity(props.getProperty("config.advancedbackups.activity", "false")); - config.setBackupType(props.getProperty("config.advancedbackups.type", "differential")); - config.setPath(props.getProperty("config.advancedbackups.path", "./backups")); - config.setMaxSize(props.getProperty("config.advancedbackups.size", "50")); - config.setMinTimer(props.getProperty("config.advancedbackups.frequency.min", "0.5")); - config.setMaxTimer(props.getProperty("config.advancedbackups.frequency.max", "24")); - config.setUptimeSchedule(props.getProperty("config.advancedbackups.frequency.uptime", "true")); - config.setSchedule(props.getProperty("config.advancedbackups.frequency.schedule", "12:00")); - config.setForceOnShutdown(props.getProperty("config.advancedbackups.frequency.shutdown", "false")); - config.setForceOnStartup(props.getProperty("config.advancedbackups.frequency.startup", "false")); - config.setStartupDelay(props.getProperty("config.advancedbackups.frequency.delay", "5")); - config.setSilent(props.getProperty("config.advancedbackups.logging.silent", "false")); - - config.setCompressionLevel(props.getProperty("config.advancedbackups.zips.compression", "5")); - - config.setMaxDepth(props.getProperty("config.advancedbackups.chains.length", "50")); - config.setCompressChains(props.getProperty("config.advancedbackups.chains.compress", "true")); - config.setSmartChains(props.getProperty("config.advancedbackups.chains.smart", "true")); - config.setMaxSizePercent(props.getProperty("config.advancedbackups.chains.maxpercent", "75")); - - config.setPurgeIncrementals(props.getProperty("config.advancedbackups.purge.incrementals", "false")); - - - - String timingsString = config.getSchedule(); - if (timingsString.length() != 0) { - BackupWrapper.configuredPlaytime = new ArrayList<>(); - for (String time : timingsString.split(",")) { - String[] hm = time.split(":"); - long hours = Long.parseLong(hm[0]) * 3600000L; - long mins = Long.parseLong(hm[1]) * 60000; - BackupWrapper.configuredPlaytime.add(hours + mins); - } - } - - boolean flag = false; - - for (String prop : supportedProps) { - if (!props.containsKey(prop)) { - flag = true; - break; - } - } - - if (flag) { - PlatformMethodWrapper.warningLogger.accept("Broken, incomplete or misising config found! Generating new file whilst preserving any existing config values..."); - - File newPropsFile = new File("./AdvancedBackups.properties"); - try { - if (!newPropsFile.exists()) { - newPropsFile.createNewFile(); - } - FileWriter writer = new FileWriter(newPropsFile); - writer.write(ConfigData.config(config.getEnabled(), config.getSave(), - config.getRequireActivity(), config.getBackupType(), config.getPath(), - config.getMaxSize(), config.getMinTimer(), config.getMaxTimer(), - config.getUptimeSchedule(), config.getSchedule(), config.getForceOnShutdown(), - config.getForceOnStartup(), config.getStartupDelay(), config.getSilent(), - config.getCompressionLevel(), config.getMaxDepth(), config.getCompressChains(), - config.getSmartChains(), config.getMaxSizePercent(), config.getPurgeIncrementals() - )); - writer.close(); - } catch (IOException e) { - // TODO : Scream to user - e.printStackTrace(); - - } - loadConfig(); - } - - } - -} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java b/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java deleted file mode 100644 index ecf162c9..00000000 --- a/src/main/java/co/uk/mommyheather/advancedbackups/core/config/ConfigData.java +++ /dev/null @@ -1,378 +0,0 @@ -package co.uk.mommyheather.advancedbackups.core.config; - -public class ConfigData { - - private Boolean enabled; - //Allows outright disabling of backups. - //OPTIONS = "TRUE", "FALSE" - - private Boolean save; - //Whether to save before a backup. - //OPTIONS = "TRUE", "FALSE" - - private Boolean requireActivity; - //Whether to require player activity between backups. - //OPTIONS = "TRUE", "FALSE" - - private String backupType; - //The type of backup to make. Each has a separate file structure, but only the currently selected backup type is scanned for. - //OPTIONS = "ZIP", "DIFFERENTIAL", "INCREMENTAL" - - private long maxSize; - //Maximum size of backups. With zips, deletes the absolute oldest file if size is exceeded after making a backup, and repeats until below max size. - //RANGE = 5GB - 9999GB - - private float minTimer; - //Ensure this amount of time is waited between backups, in hours. - //RANGE = 0.5 - 500 - - private float maxTimer; - //Triggers a backup if none has already happened within this time. Can be combined with an uptime-based schedule. - //RANGE = 0.5 - 500 - - private boolean uptimeSchedule; - //Whether the schedule is based off of server uptime (true) or world-time (false). - - private String schedule; - //A comma seperated schedule. About it. - - private String path; - //The path for backups. Defaults to ./backups. Can be absolute or relative. - //ANY STRING IS TESTED, WILL CREATE DIRECTORIES IF MISSING - - private Boolean silent; - //Whether to supress all information. Does not affect debug.log. - // TRUE OR FALSE - - private Boolean forceOnShutdown; - //Whether to build a backup when the server shuts down. - // TRUE OR FALSE - - private Boolean forceOnStartup; - //Whether to build a backup when the server starts up. - // TRUE OR FALSE - - //Startup backup delay, in seconds. - private long startupDelay; - - - //BELOW ONLY APPLIES TO ZIP FILES! (affects export command) - private int compressionLevel; - //The compression level to be passed to zip streams. - // RANGE = 1 - 9 - - - //BELOW ONLY APPLIES TO INCREMENTAL AND DIFFERENTIAL BACKUPS! - private int maxDepth; - //The maximum "depth" of partial backups to create before creating a full backup. Higher numbers are reccomended if using incremental. Lower numbers increase storage usage but reduce restoration times. - // RANGE = 5 - 500 - - private boolean compressChains; - //Whether to compress chains. Useful for size reduction and manual restoration. - // TRUE OR FALSE - - private boolean smartChains; - // Smart chain resetting. - // TRUE OR FALSE - - private int maxSizePercent; - // Resets chain length if what gets backed up is over the defined % size. - // 1-100 range. - - private boolean purgeIncrementals; - // Whether to purge incremental backups if over the limit. - // TRUE OR FALSE - - public Boolean getEnabled() { - return enabled; - } - - public void setEnabled(String enabled) { - this.enabled = Boolean.parseBoolean(enabled); - } - - public Boolean getSave() { - return save; - } - - public void setSave(String save) { - this.save = Boolean.parseBoolean(save); - } - - public Boolean getRequireActivity() { - return requireActivity; - } - - public void setRequireActivity(String requireActivity) { - this.requireActivity = Boolean.parseBoolean(requireActivity); - } - - public String getBackupType() { - return backupType; - } - - public void setBackupType(String backupType) { - this.backupType = backupType; - } - - public long getMaxSize() { - return maxSize; - } - - public void setMaxSize(String maxSize) { - this.maxSize = Long.parseLong(maxSize); - } - - public float getMinTimer() { - return minTimer; - } - - public void setMinTimer(String minTimer) { - this.minTimer = Float.parseFloat(minTimer); - } - - - public float getMaxTimer() { - return maxTimer; - } - - public void setUptimeSchedule(String uptimeSchedule) { - this.uptimeSchedule = Boolean.parseBoolean(uptimeSchedule); - } - - public boolean getUptimeSchedule() { - return uptimeSchedule; - } - - public void setSchedule(String schedule) { - this.schedule = schedule; - } - - public String getSchedule() { - return schedule; - } - - public void setMaxTimer(String maxTimer) { - this.maxTimer = Float.parseFloat(maxTimer); - } - - public String getPath() { - return path; - } - - public void setPath(String path) { - this.path = path; - } - - public Boolean getSilent() { - return silent; - } - - public void setSilent(String silent) { - this.silent = Boolean.parseBoolean(silent); - } - - public Boolean getForceOnShutdown() { - return forceOnShutdown; - } - - public void setForceOnShutdown(String forceOnShutdown) { - this.forceOnShutdown = Boolean.parseBoolean(forceOnShutdown); - } - - public Boolean getForceOnStartup() { - return forceOnStartup; - } - - public void setForceOnStartup(String forceOnStartup) { - this.forceOnStartup = Boolean.parseBoolean(forceOnStartup); - } - - public void setStartupDelay(String delay) { - this.startupDelay = Long.parseLong(delay); - } - - public long getStartupDelay() { - return startupDelay; - } - - public int getCompressionLevel() { - return compressionLevel; - } - - public void setCompressionLevel(String compressionLevel) { - this.compressionLevel = Integer.parseInt(compressionLevel); - } - - public int getMaxDepth() { - return maxDepth; - } - - public void setMaxDepth(String maxDepth) { - this.maxDepth = Integer.parseInt(maxDepth); - } - - public boolean getCompressChains() { - return compressChains; - } - - public void setCompressChains(String compressChains) { - this.compressChains = Boolean.parseBoolean(compressChains); - } - - public boolean getSmartChains() { - return smartChains; - } - - public void setSmartChains(String smartChains) { - this.smartChains = Boolean.parseBoolean(smartChains); - } - - - public boolean getPurgeIncrementals() { - return purgeIncrementals; - } - - public void setPurgeIncrementals(String purgeIncrementals) { - this.purgeIncrementals = Boolean.parseBoolean(purgeIncrementals); - } - - public int getMaxSizePercent() { - return maxSizePercent; - } - - public void setMaxSizePercent(String maxSizePercent) { - this.maxSizePercent = Integer.parseInt(maxSizePercent); - } - - - - - //default config output - can be ignored - public static String config(Object enabled, Object save, - Object activity, Object type, Object location, - Object size, Object min, Object max, - Object uptime, Object schedule, Object shutdown, - Object startup, Object delay, Object silent, - Object compression, Object chainLength, Object compressChains, - Object smartChains, Object maxPercent, Object purgeIncrementals) { - return String.join("\n", - -"#Enable or disable automatic backups.", -"#Options : true, false #Default : true,", -"config.advancedbackups.enabled=" + enabled, -"", -"#Whether to save before making a backup.", -"#Options : true, false #Default : false", -"config.advancedbackups.save=" + save, -"", -"#Whether to require player activity between backups.", -"#Options : true, false #Default : false", -"config.advancedbackups.activity=" + activity, -"", -"#The type of backups to use.", -"#Options : zip, differential, incremental #Default : differential", -"config.advancedbackups.type=" + type, -"", -"#The absolute or relative path to the backup location.", -"#Options : any file path. Default : ./backups", -"config.advancedbackups.path=" + location, -"", -"#The maximum size to keep, in GB. Keep relatively high for zips, tighter space requirements should instead use differential or incremental backups.", -"#Range : 5 - 9999 #Default : 50", -"config.advancedbackups.size=" + size, -"", -"#Minimum time between backups, in hours. This can prevent a shutdown backup from triggering immediately after a scheduled backup or similar situations.", -"#Range : 0.5 - 500 #Default : 0.5", -"config.advancedbackups.frequency.min=" + min, -"", -"#Triggers a backup if none has already happened within this time. Can be combined with an uptime-based schedule.", -"#Range : 0.5 - 500 #Default : 24", -"config.advancedbackups.frequency.max=" + max, -"", -"#Whether the schedule below uses uptime (true) or real-world time (false).", -"#Default : true", -"config.advancedbackups.frequency.uptime=" + uptime, -"", -"#When using server uptime:", -" #A looping comma-separated backup schedule, based off of server uptime, hours:minutes. Examples:", -" #4:00 - Makes a backup every four hours.", -" #4:00,7:00 - Makes a backup after four hours, then three, then four, and so on.", -" #1:00 - Makes a backup every hour.", -" #4:00,8:00,12:00,16:00,17:00,18:00,19:00,20:00,21:00,24:00 - Makes a backup following a strict schedule.", -"", -"#When using real-world time:", -" #A strict schedule, using hours:minutes to follow real-world time. Examples:", -" #4:00 - Makes a backup at 4am each day.", -" #4:00,8:00,12:00,16:00,17:00,18:00,19:00,20:00,21:00,24:00 - Makes a backup at specific times of day.", -"", -"#Default : 12:00", -"config.advancedbackups.frequency.schedule=" + schedule, -"", -"#Whether to force a backup on server shutdown. Respects min frequency.", -"#Options : true, false #Default : false", -"config.advancedbackups.frequency.shutdown=" + shutdown, -"", -"#Whether to force a backup on server startup. Respects min frequency.", -"#Options : true, false #Default : false", -"config.advancedbackups.frequency.startup=" + startup, -"", -"#Delay to use after startup, in seconds. Is always at least 5 seconds.", -"#Range : 5-9999999999", -"config.advancedbackups.frequency.delay=" + delay, -"", -"#Whether to disable console and chat logging. Does not affect debug.log, does not affect error messages.", -"#Options : true, false #Default : false", -"config.advancedbackups.logging.silent=" + silent, -"", -"", -"", -"#--------------------------------------------------------------------------------------------------------------------", -"##The following options only affect zip files, whether that's for zip backups, export commands or some other option.", -"#--------------------------------------------------------------------------------------------------------------------", -"", -"#The compression level to use for zip files. Higher numbers space usage, but decrease performance.", -"#Range : 1-9 #Default : 4", -"config.advancedbackups.zips.compression=" + compression, -"", -"", -"", -"#--------------------------------------------------------------------------------------------------------------------", -"##The following options only affect differential and incremental backups.", -"#--------------------------------------------------------------------------------------------------------------------", -"", -"#The maximum 'chain' length to keep.", -"#Range : 5-500 #Default : 50", -"config.advancedbackups.chains.length=" + chainLength, -"", -"#Whether to compress 'chains'. This compresses the base backup and all sequential backups. Reduces space usage, but decreases performance.", -"#Options : true, false #Default : true", -"config.advancedbackups.chains.compress=" + compressChains, -"", -"#Whether to enable \"smart\" reset for chains - if every file is being backed up, mark the backup as complete and reset chain length regardless of intended backup type.", -"#Options : true, false #Default : true", -"config.advancedbackups.chains.smart=" + smartChains, -"", -"#What % of a full backup is allowed to be contained in a partial before forcing it into a full backup. Useful for reducing partial backup size.", -"config.advancedbackups.chains.maxpercent=" + maxPercent, -"", -"#Whether to delete incremental backup chains if max size is exceeded. If not, incremental backups do not respect the max size config and never delete.", -"#Options : true, false #Default : false", -"config.advancedbackups.purge.incrementals=" + purgeIncrementals - - - ); - } - - public static String defaults() { - return config( - "true", "false", "false", - "differential", "./backups", "50", - "0.5", "24", "true", - "12:00", "false", "false", - "5", "false", "4", - "50", "true", "true", - "75","false"); - - } -} From 363771a1937412dc55dc5bceb0c36e0b15a16ef7 Mon Sep 17 00:00:00 2001 From: Heather <66441550+MommyHeather@users.noreply.github.com> Date: Sat, 2 Sep 2023 02:31:55 +0100 Subject: [PATCH 227/580] Update README.md --- README.md | 180 +----------------------------------------------------- 1 file changed, 3 insertions(+), 177 deletions(-) diff --git a/README.md b/README.md index 08708d53..7063825c 100644 --- a/README.md +++ b/README.md @@ -1,178 +1,4 @@ -# Advanced Backups +# Forge - 1.18 - -A powerful backup mod for Minecraft, supporting Forge and Fabric. -Many Minecraft versions are supported - request more if the one you want isn't yet supported. - -[Supported Versions](#current-versions) - -[Features](#features) - -[Ingame Usage](#ingame) - -[Command Line Usage](#commandline) - -[Future Plans](#future-plans) - -## Current Versions: -- Forge 1.19 -- Forge 1.18 -- Fabric 1.18 -- Forge 1.16 -- Forge 1.12 -- Forge 1.7.10 - -## Features: -- Choose between zip, differential or incremental backups. -- Set a schedule to backup as and when you want. -- Optionally force a minimum time between backups to avoid doing so too frequently. -- Backup on server startup and / or shutdown, or neither. -- Set a cap to max backup sizes. -- Save anywhere on disk, including network locations. -- Customisable compression level. -- Commandline restoration tool built into the jar. - - -## Usage: - -### Ingame: -\- Upon first boot, an `AdvancedBackups.properties` file will be created in your server or client root directory. - -\- Adjust this to suit your needs, then restart the server or use `/advancedbackups reload` to reload the config. A small description of each config entry is below. - -| Config | Description | Default Value | Supported From | -| ----------- | ----------- | ------------- | -------------- | -| config.advancedbackups.enabled | Enable or disable backups entirely. | true | 0.3 | -| config.advancedbackups.activity | Enable or disable player activity requirements. | false | 1.0 | -| config.advancedbackups.save | Whether to save before making a backup. | false | 0.3 | -| config.advancedbackups.type | Whether to use zip, differential or incremental backups. | differential | 0.3 | -| config.advancedbackups.path | The relative or absolute location where backups are stored. | ./backups | 0.3 | -| config.advancedbackups.size | The maximum backup size to keep, in GB. Oldest backups are deleted if this is exceeded. | 50 | 0.3 | -| config.advancedbackups.frequency.min | The minimum time between backups. Command backups bypass this. | 0.5 | 0.3 | -| config.advancedbackups.frequency.max | If this time has passed since a backup was last made, one **will** be made. | 24 | 0.3 | -| config.advancedbackups.frequency.uptime| Whether the schedule is based on uptime. If not. it uses real-time instead. | true | 0.3 | -| config.advancedbackups.frequency.schedule | Uptime based : a looping uptime-based schedule. Real-time based : A strict schedule, following real-world time. | 12:00 | 0.3 | -| config.advancedbackups.frequency.shutdown | Whether to make a backup on server shutdown. | false | 0.3 | -| config.advancedbackups.frequency.startup | Whether to make a backup on server startup. | false | 0.3 | -| config.advancedbackups.frequency.delay | The delay in seconds before making a startup backup. Always at least 5 seconds. | 5 | 0.3 | -| config.advancedbackups.logging.silent | Whether to disable chat and console logging. Does not affect debug.log or error messages. | false | N/A | -| config.advancedbackups.zips.compression | The attempted compression level for all zip files. | 4 | 0.3 | -| config.advancedbackups.chains.length | The maximum chain length for incremental and differential backups. | 50 | 0.3 | -| config.advancedbackups.chains.compress | Whether to compress incremental and differential backups into zip files. | true | 0.3 | -| config.advancedbackups.chains.smart | For differential and incremental backups. Resets the chain length if every file is being backed up. | true | 0.3 | -| config.advancedbackups.purge.incremental | For incremental backups only. Enable to allow purging incremental backup chains if the defined storage usage is limit exceeded. | false | 1.0 | - -#### Commands: - -\- All entries in the table below must be prefixed with `/advancedbackups`. - -- Example : `/advancedbackups force-backup` - - -| Command | Description | Supported From | -| ----------- | ----------- | -------------- | -| check | Checks if a backup would be made at this point in time, and tells you the result. Does not make a backup.| 1.0 | -| start | Starts a backup if all checks pass. Tells you check results.| 1.0 | -| reload | Reloads the config.| 1.0 | -| force-backup | Forces a backup without running any checks.| 1.0 | -| reset-chain | Resets any current chain length.| 1.0 | - - -### Commandline: -TODO - export option for backups. - -\- Run the jar directly from the mods folder. `java -jar AdvancedBackups-modloader-mcversion-modversion` for example, replacing the filename with the correct one for your installation. - -\- It will read your config. Then, it will ask you which backup type to restore. - -\- Afterwards, it will ask you if you are on a client or server. If you run the forge/fabric server software, choose server, otherwise it's a client. - -\- Then it will ask for your world name. It will verify this, and will not proceed if it can't find the name. - -\- Then it will prompt you to choose a backup to restore. The most recent are listed last. With differential and incremental upgrades, the backups will be labelled as partial or fill. - -- This is only for your information, and will not affect the restoration process. - -\- The below image shows this for a differential backup. - - -![image](https://github.com/MommyHeather/AdvancedBackups/assets/66441550/ba73af5f-1bca-4ec7-9a3e-a21f6b7350ab) - -\- Next you choose whether you're restoring the entire backup, or a singular file. - -- This restores the **ENTIRE WORLD STATE** at the time of the backups. Partial backups will have the relevant previous backups also restored to make this happen. - - -Finally, you can accept the warning prompt it gives you. - -If you chose to restore the entire backup, the program will exit when it is complete. -If you chose to restore a singular file, you'll be presented with a rudimentary file browser. The below example is for differential backups: - -![image](https://github.com/MommyHeather/AdvancedBackups/assets/66441550/d5f771f5-32d4-435f-aa82-a1da52e3996c) - -Directories are marked, and `../` will traverse up a directory. - -If your selected backup type is differential or incremental, files will be marked with the date they're from. This is purely for your information, the file's state will match that of when the selected backup was made. - -Once you select a file, it will be restored. The program will then exit. - -![image](https://github.com/MommyHeather/AdvancedBackups/assets/66441550/7a2c5d4c-e8db-48c3-8353-46486b9f86b3) - - - -# Future Plans: -- Note : these are in no particular order. -- [Profiles](#profiles) -- [More Commands](#more-commands) -- [Client Feedback](#client-feedback) -- [Commandline Improvements](#commandline-improvements) - -## Profiles - -- Profiles plan to allow one server to have several backup configs active at once. -- Say, take an incremental backup every day, but make sure a zip backup is made at least once a week. -- Or maybe, you want to save a differential backup every hour on a remote drive, but keep a full-world zip backup ready locally every 24 hours. - -### Profiles can do this! - -Essentially, profiles will be an optional set of additional configs. - -These are completely separate - meaning they will not interfere with one another, at all. -- Certain values, such as min and max, may have problems if two profiles use the same location and backup type. I am not sure if I will fix this yet. - -The profile system will not be compatible with versions that predate its release. -- Backups themselves will be unaffected, and any version will be able to restore them. -- The backup location detection however may not work if your restoration cli predates the profile release. - -Upon first load with a version updated to use profiles, a default profile will be made. -- If you have a config present from an older version, the changes you made will be automatically applied to the default profile for you. -- *This means that a user who does not wish to use profiles will not be affected whatsoever. They can edit the default profile as they would with a standard config.* - - -## More commands - -Shortly after release, I wish to add more commands. - -- Config editing on the fly -- One-off backup types - - Currently, the `start` and `force-backup` commands only allow you to make a backup of the type specified in config. This will change. - - -## Client feedback - -Having some client feedback would allow connected clients that have the mod view backup progress. -- This should be toggleable in config. -- A config option to only show progress to ops should exist. - -This might be in the form of either a progress bar, or a simple percentage. - -Clients with the mod should have a way to opt out of this. - - -## Commandline improvements - -Export feature : -- When asked whether restoring a singular file or the whole world, a third option will be present : export. -- This will package the backup into a singular zip file (...so yeah, just copy over the backup in the case of zip backups). -- It will leave the actual world intact. - +This is the branch specifically for forge 1.18. +Any differences will be listed below. For full documentation, see the `core` branch. From e7a22ae086f150f0ea92aeefb204bca8c23b3d5e Mon Sep 17 00:00:00 2001 From: Heather <66441550+MommyHeather@users.noreply.github.com> Date: Sat, 2 Sep 2023 02:33:53 +0100 Subject: [PATCH 228/580] Update README.md --- README.md | 180 +----------------------------------------------------- 1 file changed, 3 insertions(+), 177 deletions(-) diff --git a/README.md b/README.md index 08708d53..77ad2bc7 100644 --- a/README.md +++ b/README.md @@ -1,178 +1,4 @@ -# Advanced Backups +# Forge - 1.16 - -A powerful backup mod for Minecraft, supporting Forge and Fabric. -Many Minecraft versions are supported - request more if the one you want isn't yet supported. - -[Supported Versions](#current-versions) - -[Features](#features) - -[Ingame Usage](#ingame) - -[Command Line Usage](#commandline) - -[Future Plans](#future-plans) - -## Current Versions: -- Forge 1.19 -- Forge 1.18 -- Fabric 1.18 -- Forge 1.16 -- Forge 1.12 -- Forge 1.7.10 - -## Features: -- Choose between zip, differential or incremental backups. -- Set a schedule to backup as and when you want. -- Optionally force a minimum time between backups to avoid doing so too frequently. -- Backup on server startup and / or shutdown, or neither. -- Set a cap to max backup sizes. -- Save anywhere on disk, including network locations. -- Customisable compression level. -- Commandline restoration tool built into the jar. - - -## Usage: - -### Ingame: -\- Upon first boot, an `AdvancedBackups.properties` file will be created in your server or client root directory. - -\- Adjust this to suit your needs, then restart the server or use `/advancedbackups reload` to reload the config. A small description of each config entry is below. - -| Config | Description | Default Value | Supported From | -| ----------- | ----------- | ------------- | -------------- | -| config.advancedbackups.enabled | Enable or disable backups entirely. | true | 0.3 | -| config.advancedbackups.activity | Enable or disable player activity requirements. | false | 1.0 | -| config.advancedbackups.save | Whether to save before making a backup. | false | 0.3 | -| config.advancedbackups.type | Whether to use zip, differential or incremental backups. | differential | 0.3 | -| config.advancedbackups.path | The relative or absolute location where backups are stored. | ./backups | 0.3 | -| config.advancedbackups.size | The maximum backup size to keep, in GB. Oldest backups are deleted if this is exceeded. | 50 | 0.3 | -| config.advancedbackups.frequency.min | The minimum time between backups. Command backups bypass this. | 0.5 | 0.3 | -| config.advancedbackups.frequency.max | If this time has passed since a backup was last made, one **will** be made. | 24 | 0.3 | -| config.advancedbackups.frequency.uptime| Whether the schedule is based on uptime. If not. it uses real-time instead. | true | 0.3 | -| config.advancedbackups.frequency.schedule | Uptime based : a looping uptime-based schedule. Real-time based : A strict schedule, following real-world time. | 12:00 | 0.3 | -| config.advancedbackups.frequency.shutdown | Whether to make a backup on server shutdown. | false | 0.3 | -| config.advancedbackups.frequency.startup | Whether to make a backup on server startup. | false | 0.3 | -| config.advancedbackups.frequency.delay | The delay in seconds before making a startup backup. Always at least 5 seconds. | 5 | 0.3 | -| config.advancedbackups.logging.silent | Whether to disable chat and console logging. Does not affect debug.log or error messages. | false | N/A | -| config.advancedbackups.zips.compression | The attempted compression level for all zip files. | 4 | 0.3 | -| config.advancedbackups.chains.length | The maximum chain length for incremental and differential backups. | 50 | 0.3 | -| config.advancedbackups.chains.compress | Whether to compress incremental and differential backups into zip files. | true | 0.3 | -| config.advancedbackups.chains.smart | For differential and incremental backups. Resets the chain length if every file is being backed up. | true | 0.3 | -| config.advancedbackups.purge.incremental | For incremental backups only. Enable to allow purging incremental backup chains if the defined storage usage is limit exceeded. | false | 1.0 | - -#### Commands: - -\- All entries in the table below must be prefixed with `/advancedbackups`. - -- Example : `/advancedbackups force-backup` - - -| Command | Description | Supported From | -| ----------- | ----------- | -------------- | -| check | Checks if a backup would be made at this point in time, and tells you the result. Does not make a backup.| 1.0 | -| start | Starts a backup if all checks pass. Tells you check results.| 1.0 | -| reload | Reloads the config.| 1.0 | -| force-backup | Forces a backup without running any checks.| 1.0 | -| reset-chain | Resets any current chain length.| 1.0 | - - -### Commandline: -TODO - export option for backups. - -\- Run the jar directly from the mods folder. `java -jar AdvancedBackups-modloader-mcversion-modversion` for example, replacing the filename with the correct one for your installation. - -\- It will read your config. Then, it will ask you which backup type to restore. - -\- Afterwards, it will ask you if you are on a client or server. If you run the forge/fabric server software, choose server, otherwise it's a client. - -\- Then it will ask for your world name. It will verify this, and will not proceed if it can't find the name. - -\- Then it will prompt you to choose a backup to restore. The most recent are listed last. With differential and incremental upgrades, the backups will be labelled as partial or fill. - -- This is only for your information, and will not affect the restoration process. - -\- The below image shows this for a differential backup. - - -![image](https://github.com/MommyHeather/AdvancedBackups/assets/66441550/ba73af5f-1bca-4ec7-9a3e-a21f6b7350ab) - -\- Next you choose whether you're restoring the entire backup, or a singular file. - -- This restores the **ENTIRE WORLD STATE** at the time of the backups. Partial backups will have the relevant previous backups also restored to make this happen. - - -Finally, you can accept the warning prompt it gives you. - -If you chose to restore the entire backup, the program will exit when it is complete. -If you chose to restore a singular file, you'll be presented with a rudimentary file browser. The below example is for differential backups: - -![image](https://github.com/MommyHeather/AdvancedBackups/assets/66441550/d5f771f5-32d4-435f-aa82-a1da52e3996c) - -Directories are marked, and `../` will traverse up a directory. - -If your selected backup type is differential or incremental, files will be marked with the date they're from. This is purely for your information, the file's state will match that of when the selected backup was made. - -Once you select a file, it will be restored. The program will then exit. - -![image](https://github.com/MommyHeather/AdvancedBackups/assets/66441550/7a2c5d4c-e8db-48c3-8353-46486b9f86b3) - - - -# Future Plans: -- Note : these are in no particular order. -- [Profiles](#profiles) -- [More Commands](#more-commands) -- [Client Feedback](#client-feedback) -- [Commandline Improvements](#commandline-improvements) - -## Profiles - -- Profiles plan to allow one server to have several backup configs active at once. -- Say, take an incremental backup every day, but make sure a zip backup is made at least once a week. -- Or maybe, you want to save a differential backup every hour on a remote drive, but keep a full-world zip backup ready locally every 24 hours. - -### Profiles can do this! - -Essentially, profiles will be an optional set of additional configs. - -These are completely separate - meaning they will not interfere with one another, at all. -- Certain values, such as min and max, may have problems if two profiles use the same location and backup type. I am not sure if I will fix this yet. - -The profile system will not be compatible with versions that predate its release. -- Backups themselves will be unaffected, and any version will be able to restore them. -- The backup location detection however may not work if your restoration cli predates the profile release. - -Upon first load with a version updated to use profiles, a default profile will be made. -- If you have a config present from an older version, the changes you made will be automatically applied to the default profile for you. -- *This means that a user who does not wish to use profiles will not be affected whatsoever. They can edit the default profile as they would with a standard config.* - - -## More commands - -Shortly after release, I wish to add more commands. - -- Config editing on the fly -- One-off backup types - - Currently, the `start` and `force-backup` commands only allow you to make a backup of the type specified in config. This will change. - - -## Client feedback - -Having some client feedback would allow connected clients that have the mod view backup progress. -- This should be toggleable in config. -- A config option to only show progress to ops should exist. - -This might be in the form of either a progress bar, or a simple percentage. - -Clients with the mod should have a way to opt out of this. - - -## Commandline improvements - -Export feature : -- When asked whether restoring a singular file or the whole world, a third option will be present : export. -- This will package the backup into a singular zip file (...so yeah, just copy over the backup in the case of zip backups). -- It will leave the actual world intact. - +This is the branch specifically for forge 1.16. +Any differences will be listed below. For full documentation, see the `core` branch. From 41f58c6ed192e03e40a73b1831ee7db33dd30f74 Mon Sep 17 00:00:00 2001 From: Heather <66441550+MommyHeather@users.noreply.github.com> Date: Sat, 2 Sep 2023 02:34:14 +0100 Subject: [PATCH 229/580] Update README.md --- README.md | 180 +----------------------------------------------------- 1 file changed, 3 insertions(+), 177 deletions(-) diff --git a/README.md b/README.md index 08708d53..911a7b09 100644 --- a/README.md +++ b/README.md @@ -1,178 +1,4 @@ -# Advanced Backups +# Forge - 1.12 - -A powerful backup mod for Minecraft, supporting Forge and Fabric. -Many Minecraft versions are supported - request more if the one you want isn't yet supported. - -[Supported Versions](#current-versions) - -[Features](#features) - -[Ingame Usage](#ingame) - -[Command Line Usage](#commandline) - -[Future Plans](#future-plans) - -## Current Versions: -- Forge 1.19 -- Forge 1.18 -- Fabric 1.18 -- Forge 1.16 -- Forge 1.12 -- Forge 1.7.10 - -## Features: -- Choose between zip, differential or incremental backups. -- Set a schedule to backup as and when you want. -- Optionally force a minimum time between backups to avoid doing so too frequently. -- Backup on server startup and / or shutdown, or neither. -- Set a cap to max backup sizes. -- Save anywhere on disk, including network locations. -- Customisable compression level. -- Commandline restoration tool built into the jar. - - -## Usage: - -### Ingame: -\- Upon first boot, an `AdvancedBackups.properties` file will be created in your server or client root directory. - -\- Adjust this to suit your needs, then restart the server or use `/advancedbackups reload` to reload the config. A small description of each config entry is below. - -| Config | Description | Default Value | Supported From | -| ----------- | ----------- | ------------- | -------------- | -| config.advancedbackups.enabled | Enable or disable backups entirely. | true | 0.3 | -| config.advancedbackups.activity | Enable or disable player activity requirements. | false | 1.0 | -| config.advancedbackups.save | Whether to save before making a backup. | false | 0.3 | -| config.advancedbackups.type | Whether to use zip, differential or incremental backups. | differential | 0.3 | -| config.advancedbackups.path | The relative or absolute location where backups are stored. | ./backups | 0.3 | -| config.advancedbackups.size | The maximum backup size to keep, in GB. Oldest backups are deleted if this is exceeded. | 50 | 0.3 | -| config.advancedbackups.frequency.min | The minimum time between backups. Command backups bypass this. | 0.5 | 0.3 | -| config.advancedbackups.frequency.max | If this time has passed since a backup was last made, one **will** be made. | 24 | 0.3 | -| config.advancedbackups.frequency.uptime| Whether the schedule is based on uptime. If not. it uses real-time instead. | true | 0.3 | -| config.advancedbackups.frequency.schedule | Uptime based : a looping uptime-based schedule. Real-time based : A strict schedule, following real-world time. | 12:00 | 0.3 | -| config.advancedbackups.frequency.shutdown | Whether to make a backup on server shutdown. | false | 0.3 | -| config.advancedbackups.frequency.startup | Whether to make a backup on server startup. | false | 0.3 | -| config.advancedbackups.frequency.delay | The delay in seconds before making a startup backup. Always at least 5 seconds. | 5 | 0.3 | -| config.advancedbackups.logging.silent | Whether to disable chat and console logging. Does not affect debug.log or error messages. | false | N/A | -| config.advancedbackups.zips.compression | The attempted compression level for all zip files. | 4 | 0.3 | -| config.advancedbackups.chains.length | The maximum chain length for incremental and differential backups. | 50 | 0.3 | -| config.advancedbackups.chains.compress | Whether to compress incremental and differential backups into zip files. | true | 0.3 | -| config.advancedbackups.chains.smart | For differential and incremental backups. Resets the chain length if every file is being backed up. | true | 0.3 | -| config.advancedbackups.purge.incremental | For incremental backups only. Enable to allow purging incremental backup chains if the defined storage usage is limit exceeded. | false | 1.0 | - -#### Commands: - -\- All entries in the table below must be prefixed with `/advancedbackups`. - -- Example : `/advancedbackups force-backup` - - -| Command | Description | Supported From | -| ----------- | ----------- | -------------- | -| check | Checks if a backup would be made at this point in time, and tells you the result. Does not make a backup.| 1.0 | -| start | Starts a backup if all checks pass. Tells you check results.| 1.0 | -| reload | Reloads the config.| 1.0 | -| force-backup | Forces a backup without running any checks.| 1.0 | -| reset-chain | Resets any current chain length.| 1.0 | - - -### Commandline: -TODO - export option for backups. - -\- Run the jar directly from the mods folder. `java -jar AdvancedBackups-modloader-mcversion-modversion` for example, replacing the filename with the correct one for your installation. - -\- It will read your config. Then, it will ask you which backup type to restore. - -\- Afterwards, it will ask you if you are on a client or server. If you run the forge/fabric server software, choose server, otherwise it's a client. - -\- Then it will ask for your world name. It will verify this, and will not proceed if it can't find the name. - -\- Then it will prompt you to choose a backup to restore. The most recent are listed last. With differential and incremental upgrades, the backups will be labelled as partial or fill. - -- This is only for your information, and will not affect the restoration process. - -\- The below image shows this for a differential backup. - - -![image](https://github.com/MommyHeather/AdvancedBackups/assets/66441550/ba73af5f-1bca-4ec7-9a3e-a21f6b7350ab) - -\- Next you choose whether you're restoring the entire backup, or a singular file. - -- This restores the **ENTIRE WORLD STATE** at the time of the backups. Partial backups will have the relevant previous backups also restored to make this happen. - - -Finally, you can accept the warning prompt it gives you. - -If you chose to restore the entire backup, the program will exit when it is complete. -If you chose to restore a singular file, you'll be presented with a rudimentary file browser. The below example is for differential backups: - -![image](https://github.com/MommyHeather/AdvancedBackups/assets/66441550/d5f771f5-32d4-435f-aa82-a1da52e3996c) - -Directories are marked, and `../` will traverse up a directory. - -If your selected backup type is differential or incremental, files will be marked with the date they're from. This is purely for your information, the file's state will match that of when the selected backup was made. - -Once you select a file, it will be restored. The program will then exit. - -![image](https://github.com/MommyHeather/AdvancedBackups/assets/66441550/7a2c5d4c-e8db-48c3-8353-46486b9f86b3) - - - -# Future Plans: -- Note : these are in no particular order. -- [Profiles](#profiles) -- [More Commands](#more-commands) -- [Client Feedback](#client-feedback) -- [Commandline Improvements](#commandline-improvements) - -## Profiles - -- Profiles plan to allow one server to have several backup configs active at once. -- Say, take an incremental backup every day, but make sure a zip backup is made at least once a week. -- Or maybe, you want to save a differential backup every hour on a remote drive, but keep a full-world zip backup ready locally every 24 hours. - -### Profiles can do this! - -Essentially, profiles will be an optional set of additional configs. - -These are completely separate - meaning they will not interfere with one another, at all. -- Certain values, such as min and max, may have problems if two profiles use the same location and backup type. I am not sure if I will fix this yet. - -The profile system will not be compatible with versions that predate its release. -- Backups themselves will be unaffected, and any version will be able to restore them. -- The backup location detection however may not work if your restoration cli predates the profile release. - -Upon first load with a version updated to use profiles, a default profile will be made. -- If you have a config present from an older version, the changes you made will be automatically applied to the default profile for you. -- *This means that a user who does not wish to use profiles will not be affected whatsoever. They can edit the default profile as they would with a standard config.* - - -## More commands - -Shortly after release, I wish to add more commands. - -- Config editing on the fly -- One-off backup types - - Currently, the `start` and `force-backup` commands only allow you to make a backup of the type specified in config. This will change. - - -## Client feedback - -Having some client feedback would allow connected clients that have the mod view backup progress. -- This should be toggleable in config. -- A config option to only show progress to ops should exist. - -This might be in the form of either a progress bar, or a simple percentage. - -Clients with the mod should have a way to opt out of this. - - -## Commandline improvements - -Export feature : -- When asked whether restoring a singular file or the whole world, a third option will be present : export. -- This will package the backup into a singular zip file (...so yeah, just copy over the backup in the case of zip backups). -- It will leave the actual world intact. - +This is the branch specifically for forge 1.12. +Any differences will be listed below. For full documentation, see the `core` branch. From 84e6a3bf0bfd1ad46e459f7f211a8411d35f0ebb Mon Sep 17 00:00:00 2001 From: Heather <66441550+MommyHeather@users.noreply.github.com> Date: Sat, 2 Sep 2023 02:34:40 +0100 Subject: [PATCH 230/580] Update README.md --- README.md | 180 +----------------------------------------------------- 1 file changed, 3 insertions(+), 177 deletions(-) diff --git a/README.md b/README.md index 08708d53..5e41c346 100644 --- a/README.md +++ b/README.md @@ -1,178 +1,4 @@ -# Advanced Backups +# Forge - 1.7.10 - -A powerful backup mod for Minecraft, supporting Forge and Fabric. -Many Minecraft versions are supported - request more if the one you want isn't yet supported. - -[Supported Versions](#current-versions) - -[Features](#features) - -[Ingame Usage](#ingame) - -[Command Line Usage](#commandline) - -[Future Plans](#future-plans) - -## Current Versions: -- Forge 1.19 -- Forge 1.18 -- Fabric 1.18 -- Forge 1.16 -- Forge 1.12 -- Forge 1.7.10 - -## Features: -- Choose between zip, differential or incremental backups. -- Set a schedule to backup as and when you want. -- Optionally force a minimum time between backups to avoid doing so too frequently. -- Backup on server startup and / or shutdown, or neither. -- Set a cap to max backup sizes. -- Save anywhere on disk, including network locations. -- Customisable compression level. -- Commandline restoration tool built into the jar. - - -## Usage: - -### Ingame: -\- Upon first boot, an `AdvancedBackups.properties` file will be created in your server or client root directory. - -\- Adjust this to suit your needs, then restart the server or use `/advancedbackups reload` to reload the config. A small description of each config entry is below. - -| Config | Description | Default Value | Supported From | -| ----------- | ----------- | ------------- | -------------- | -| config.advancedbackups.enabled | Enable or disable backups entirely. | true | 0.3 | -| config.advancedbackups.activity | Enable or disable player activity requirements. | false | 1.0 | -| config.advancedbackups.save | Whether to save before making a backup. | false | 0.3 | -| config.advancedbackups.type | Whether to use zip, differential or incremental backups. | differential | 0.3 | -| config.advancedbackups.path | The relative or absolute location where backups are stored. | ./backups | 0.3 | -| config.advancedbackups.size | The maximum backup size to keep, in GB. Oldest backups are deleted if this is exceeded. | 50 | 0.3 | -| config.advancedbackups.frequency.min | The minimum time between backups. Command backups bypass this. | 0.5 | 0.3 | -| config.advancedbackups.frequency.max | If this time has passed since a backup was last made, one **will** be made. | 24 | 0.3 | -| config.advancedbackups.frequency.uptime| Whether the schedule is based on uptime. If not. it uses real-time instead. | true | 0.3 | -| config.advancedbackups.frequency.schedule | Uptime based : a looping uptime-based schedule. Real-time based : A strict schedule, following real-world time. | 12:00 | 0.3 | -| config.advancedbackups.frequency.shutdown | Whether to make a backup on server shutdown. | false | 0.3 | -| config.advancedbackups.frequency.startup | Whether to make a backup on server startup. | false | 0.3 | -| config.advancedbackups.frequency.delay | The delay in seconds before making a startup backup. Always at least 5 seconds. | 5 | 0.3 | -| config.advancedbackups.logging.silent | Whether to disable chat and console logging. Does not affect debug.log or error messages. | false | N/A | -| config.advancedbackups.zips.compression | The attempted compression level for all zip files. | 4 | 0.3 | -| config.advancedbackups.chains.length | The maximum chain length for incremental and differential backups. | 50 | 0.3 | -| config.advancedbackups.chains.compress | Whether to compress incremental and differential backups into zip files. | true | 0.3 | -| config.advancedbackups.chains.smart | For differential and incremental backups. Resets the chain length if every file is being backed up. | true | 0.3 | -| config.advancedbackups.purge.incremental | For incremental backups only. Enable to allow purging incremental backup chains if the defined storage usage is limit exceeded. | false | 1.0 | - -#### Commands: - -\- All entries in the table below must be prefixed with `/advancedbackups`. - -- Example : `/advancedbackups force-backup` - - -| Command | Description | Supported From | -| ----------- | ----------- | -------------- | -| check | Checks if a backup would be made at this point in time, and tells you the result. Does not make a backup.| 1.0 | -| start | Starts a backup if all checks pass. Tells you check results.| 1.0 | -| reload | Reloads the config.| 1.0 | -| force-backup | Forces a backup without running any checks.| 1.0 | -| reset-chain | Resets any current chain length.| 1.0 | - - -### Commandline: -TODO - export option for backups. - -\- Run the jar directly from the mods folder. `java -jar AdvancedBackups-modloader-mcversion-modversion` for example, replacing the filename with the correct one for your installation. - -\- It will read your config. Then, it will ask you which backup type to restore. - -\- Afterwards, it will ask you if you are on a client or server. If you run the forge/fabric server software, choose server, otherwise it's a client. - -\- Then it will ask for your world name. It will verify this, and will not proceed if it can't find the name. - -\- Then it will prompt you to choose a backup to restore. The most recent are listed last. With differential and incremental upgrades, the backups will be labelled as partial or fill. - -- This is only for your information, and will not affect the restoration process. - -\- The below image shows this for a differential backup. - - -![image](https://github.com/MommyHeather/AdvancedBackups/assets/66441550/ba73af5f-1bca-4ec7-9a3e-a21f6b7350ab) - -\- Next you choose whether you're restoring the entire backup, or a singular file. - -- This restores the **ENTIRE WORLD STATE** at the time of the backups. Partial backups will have the relevant previous backups also restored to make this happen. - - -Finally, you can accept the warning prompt it gives you. - -If you chose to restore the entire backup, the program will exit when it is complete. -If you chose to restore a singular file, you'll be presented with a rudimentary file browser. The below example is for differential backups: - -![image](https://github.com/MommyHeather/AdvancedBackups/assets/66441550/d5f771f5-32d4-435f-aa82-a1da52e3996c) - -Directories are marked, and `../` will traverse up a directory. - -If your selected backup type is differential or incremental, files will be marked with the date they're from. This is purely for your information, the file's state will match that of when the selected backup was made. - -Once you select a file, it will be restored. The program will then exit. - -![image](https://github.com/MommyHeather/AdvancedBackups/assets/66441550/7a2c5d4c-e8db-48c3-8353-46486b9f86b3) - - - -# Future Plans: -- Note : these are in no particular order. -- [Profiles](#profiles) -- [More Commands](#more-commands) -- [Client Feedback](#client-feedback) -- [Commandline Improvements](#commandline-improvements) - -## Profiles - -- Profiles plan to allow one server to have several backup configs active at once. -- Say, take an incremental backup every day, but make sure a zip backup is made at least once a week. -- Or maybe, you want to save a differential backup every hour on a remote drive, but keep a full-world zip backup ready locally every 24 hours. - -### Profiles can do this! - -Essentially, profiles will be an optional set of additional configs. - -These are completely separate - meaning they will not interfere with one another, at all. -- Certain values, such as min and max, may have problems if two profiles use the same location and backup type. I am not sure if I will fix this yet. - -The profile system will not be compatible with versions that predate its release. -- Backups themselves will be unaffected, and any version will be able to restore them. -- The backup location detection however may not work if your restoration cli predates the profile release. - -Upon first load with a version updated to use profiles, a default profile will be made. -- If you have a config present from an older version, the changes you made will be automatically applied to the default profile for you. -- *This means that a user who does not wish to use profiles will not be affected whatsoever. They can edit the default profile as they would with a standard config.* - - -## More commands - -Shortly after release, I wish to add more commands. - -- Config editing on the fly -- One-off backup types - - Currently, the `start` and `force-backup` commands only allow you to make a backup of the type specified in config. This will change. - - -## Client feedback - -Having some client feedback would allow connected clients that have the mod view backup progress. -- This should be toggleable in config. -- A config option to only show progress to ops should exist. - -This might be in the form of either a progress bar, or a simple percentage. - -Clients with the mod should have a way to opt out of this. - - -## Commandline improvements - -Export feature : -- When asked whether restoring a singular file or the whole world, a third option will be present : export. -- This will package the backup into a singular zip file (...so yeah, just copy over the backup in the case of zip backups). -- It will leave the actual world intact. - +This is the branch specifically for forge 1.7.10. +Any differences will be listed below. For full documentation, see the `core` branch. From 4943b5057819212163440893ed18cc391016861e Mon Sep 17 00:00:00 2001 From: Heather <66441550+MommyHeather@users.noreply.github.com> Date: Sat, 2 Sep 2023 02:35:11 +0100 Subject: [PATCH 231/580] Update README.md --- README.md | 180 +----------------------------------------------------- 1 file changed, 3 insertions(+), 177 deletions(-) diff --git a/README.md b/README.md index 08708d53..a1bde000 100644 --- a/README.md +++ b/README.md @@ -1,178 +1,4 @@ -# Advanced Backups +# Fabric - 1.18 - -A powerful backup mod for Minecraft, supporting Forge and Fabric. -Many Minecraft versions are supported - request more if the one you want isn't yet supported. - -[Supported Versions](#current-versions) - -[Features](#features) - -[Ingame Usage](#ingame) - -[Command Line Usage](#commandline) - -[Future Plans](#future-plans) - -## Current Versions: -- Forge 1.19 -- Forge 1.18 -- Fabric 1.18 -- Forge 1.16 -- Forge 1.12 -- Forge 1.7.10 - -## Features: -- Choose between zip, differential or incremental backups. -- Set a schedule to backup as and when you want. -- Optionally force a minimum time between backups to avoid doing so too frequently. -- Backup on server startup and / or shutdown, or neither. -- Set a cap to max backup sizes. -- Save anywhere on disk, including network locations. -- Customisable compression level. -- Commandline restoration tool built into the jar. - - -## Usage: - -### Ingame: -\- Upon first boot, an `AdvancedBackups.properties` file will be created in your server or client root directory. - -\- Adjust this to suit your needs, then restart the server or use `/advancedbackups reload` to reload the config. A small description of each config entry is below. - -| Config | Description | Default Value | Supported From | -| ----------- | ----------- | ------------- | -------------- | -| config.advancedbackups.enabled | Enable or disable backups entirely. | true | 0.3 | -| config.advancedbackups.activity | Enable or disable player activity requirements. | false | 1.0 | -| config.advancedbackups.save | Whether to save before making a backup. | false | 0.3 | -| config.advancedbackups.type | Whether to use zip, differential or incremental backups. | differential | 0.3 | -| config.advancedbackups.path | The relative or absolute location where backups are stored. | ./backups | 0.3 | -| config.advancedbackups.size | The maximum backup size to keep, in GB. Oldest backups are deleted if this is exceeded. | 50 | 0.3 | -| config.advancedbackups.frequency.min | The minimum time between backups. Command backups bypass this. | 0.5 | 0.3 | -| config.advancedbackups.frequency.max | If this time has passed since a backup was last made, one **will** be made. | 24 | 0.3 | -| config.advancedbackups.frequency.uptime| Whether the schedule is based on uptime. If not. it uses real-time instead. | true | 0.3 | -| config.advancedbackups.frequency.schedule | Uptime based : a looping uptime-based schedule. Real-time based : A strict schedule, following real-world time. | 12:00 | 0.3 | -| config.advancedbackups.frequency.shutdown | Whether to make a backup on server shutdown. | false | 0.3 | -| config.advancedbackups.frequency.startup | Whether to make a backup on server startup. | false | 0.3 | -| config.advancedbackups.frequency.delay | The delay in seconds before making a startup backup. Always at least 5 seconds. | 5 | 0.3 | -| config.advancedbackups.logging.silent | Whether to disable chat and console logging. Does not affect debug.log or error messages. | false | N/A | -| config.advancedbackups.zips.compression | The attempted compression level for all zip files. | 4 | 0.3 | -| config.advancedbackups.chains.length | The maximum chain length for incremental and differential backups. | 50 | 0.3 | -| config.advancedbackups.chains.compress | Whether to compress incremental and differential backups into zip files. | true | 0.3 | -| config.advancedbackups.chains.smart | For differential and incremental backups. Resets the chain length if every file is being backed up. | true | 0.3 | -| config.advancedbackups.purge.incremental | For incremental backups only. Enable to allow purging incremental backup chains if the defined storage usage is limit exceeded. | false | 1.0 | - -#### Commands: - -\- All entries in the table below must be prefixed with `/advancedbackups`. - -- Example : `/advancedbackups force-backup` - - -| Command | Description | Supported From | -| ----------- | ----------- | -------------- | -| check | Checks if a backup would be made at this point in time, and tells you the result. Does not make a backup.| 1.0 | -| start | Starts a backup if all checks pass. Tells you check results.| 1.0 | -| reload | Reloads the config.| 1.0 | -| force-backup | Forces a backup without running any checks.| 1.0 | -| reset-chain | Resets any current chain length.| 1.0 | - - -### Commandline: -TODO - export option for backups. - -\- Run the jar directly from the mods folder. `java -jar AdvancedBackups-modloader-mcversion-modversion` for example, replacing the filename with the correct one for your installation. - -\- It will read your config. Then, it will ask you which backup type to restore. - -\- Afterwards, it will ask you if you are on a client or server. If you run the forge/fabric server software, choose server, otherwise it's a client. - -\- Then it will ask for your world name. It will verify this, and will not proceed if it can't find the name. - -\- Then it will prompt you to choose a backup to restore. The most recent are listed last. With differential and incremental upgrades, the backups will be labelled as partial or fill. - -- This is only for your information, and will not affect the restoration process. - -\- The below image shows this for a differential backup. - - -![image](https://github.com/MommyHeather/AdvancedBackups/assets/66441550/ba73af5f-1bca-4ec7-9a3e-a21f6b7350ab) - -\- Next you choose whether you're restoring the entire backup, or a singular file. - -- This restores the **ENTIRE WORLD STATE** at the time of the backups. Partial backups will have the relevant previous backups also restored to make this happen. - - -Finally, you can accept the warning prompt it gives you. - -If you chose to restore the entire backup, the program will exit when it is complete. -If you chose to restore a singular file, you'll be presented with a rudimentary file browser. The below example is for differential backups: - -![image](https://github.com/MommyHeather/AdvancedBackups/assets/66441550/d5f771f5-32d4-435f-aa82-a1da52e3996c) - -Directories are marked, and `../` will traverse up a directory. - -If your selected backup type is differential or incremental, files will be marked with the date they're from. This is purely for your information, the file's state will match that of when the selected backup was made. - -Once you select a file, it will be restored. The program will then exit. - -![image](https://github.com/MommyHeather/AdvancedBackups/assets/66441550/7a2c5d4c-e8db-48c3-8353-46486b9f86b3) - - - -# Future Plans: -- Note : these are in no particular order. -- [Profiles](#profiles) -- [More Commands](#more-commands) -- [Client Feedback](#client-feedback) -- [Commandline Improvements](#commandline-improvements) - -## Profiles - -- Profiles plan to allow one server to have several backup configs active at once. -- Say, take an incremental backup every day, but make sure a zip backup is made at least once a week. -- Or maybe, you want to save a differential backup every hour on a remote drive, but keep a full-world zip backup ready locally every 24 hours. - -### Profiles can do this! - -Essentially, profiles will be an optional set of additional configs. - -These are completely separate - meaning they will not interfere with one another, at all. -- Certain values, such as min and max, may have problems if two profiles use the same location and backup type. I am not sure if I will fix this yet. - -The profile system will not be compatible with versions that predate its release. -- Backups themselves will be unaffected, and any version will be able to restore them. -- The backup location detection however may not work if your restoration cli predates the profile release. - -Upon first load with a version updated to use profiles, a default profile will be made. -- If you have a config present from an older version, the changes you made will be automatically applied to the default profile for you. -- *This means that a user who does not wish to use profiles will not be affected whatsoever. They can edit the default profile as they would with a standard config.* - - -## More commands - -Shortly after release, I wish to add more commands. - -- Config editing on the fly -- One-off backup types - - Currently, the `start` and `force-backup` commands only allow you to make a backup of the type specified in config. This will change. - - -## Client feedback - -Having some client feedback would allow connected clients that have the mod view backup progress. -- This should be toggleable in config. -- A config option to only show progress to ops should exist. - -This might be in the form of either a progress bar, or a simple percentage. - -Clients with the mod should have a way to opt out of this. - - -## Commandline improvements - -Export feature : -- When asked whether restoring a singular file or the whole world, a third option will be present : export. -- This will package the backup into a singular zip file (...so yeah, just copy over the backup in the case of zip backups). -- It will leave the actual world intact. - +This is the branch specifically for fabric 1.18. +Any differences will be listed below. For full documentation, see the `core` branch. From 78562c87e064553ade237a0c4d3f86985f8523d2 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Sat, 2 Sep 2023 20:08:18 +0100 Subject: [PATCH 232/580] support #10 forge 1.18, and fix a crash (init config after logger) --- .../uk/mommyheather/advancedbackups/AdvancedBackups.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 30de3b24..c360cdbb 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -10,6 +10,7 @@ import net.minecraft.world.level.storage.LevelResource; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.ModList; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.server.ServerLifecycleHooks; import net.minecraftforge.event.RegisterCommandsEvent; @@ -43,8 +44,6 @@ public AdvancedBackups() public void onServerStarting(ServerStartingEvent event) { // Do something when the server starts - ABConfig.loadOrCreateConfig(); - LOGGER.info("Config loaded!!"); ABCore.worldName = event.getServer().getWorldData().getLevelName(); ABCore.worldDir = event.getServer().getWorldPath(LevelResource.ROOT); @@ -57,6 +56,12 @@ public void onServerStarting(ServerStartingEvent event) ABCore.warningLogger = warningLogger; ABCore.errorLogger = errorLogger; + ABCore.modJar = ModList.get().getModFileById("advancedbackups").getFile().getFilePath().toFile(); + + + ABConfig.loadOrCreateConfig(); + LOGGER.info("Config loaded!!"); + } From 1a19d8165e447e10864e736b42473a637933878f Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Sat, 2 Sep 2023 20:23:52 +0100 Subject: [PATCH 233/580] support #10 forge 1.19, and fix a crash (init config after logger) --- .../uk/mommyheather/advancedbackups/AdvancedBackups.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 17859990..8f391648 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -10,6 +10,7 @@ import net.minecraft.world.level.storage.LevelResource; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.ModList; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.server.ServerLifecycleHooks; import net.minecraftforge.event.RegisterCommandsEvent; @@ -43,8 +44,6 @@ public AdvancedBackups() public void onServerStarting(ServerStartingEvent event) { // Do something when the server starts - ABConfig.loadOrCreateConfig(); - LOGGER.info("Config loaded!!"); ABCore.worldName = event.getServer().getWorldData().getLevelName(); ABCore.worldDir = event.getServer().getWorldPath(LevelResource.ROOT); @@ -55,6 +54,12 @@ public void onServerStarting(ServerStartingEvent event) ABCore.infoLogger = infoLogger; ABCore.warningLogger = warningLogger; ABCore.errorLogger = errorLogger; + + ABCore.modJar = ModList.get().getModFileById("advancedbackups").getFile().getFilePath().toFile(); + + + ABConfig.loadOrCreateConfig(); + LOGGER.info("Config loaded!!"); } From 7cd79ba0b31fc4d0c5401db24b4d6c95744ab883 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Sat, 2 Sep 2023 20:31:14 +0100 Subject: [PATCH 234/580] Support #10 in forge 1.16 and fix crash --- .../uk/mommyheather/advancedbackups/AdvancedBackups.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index ad9f4945..52539daf 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -11,6 +11,7 @@ import net.minecraftforge.event.RegisterCommandsEvent; import net.minecraftforge.event.entity.player.PlayerEvent.PlayerLoggedInEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.ModList; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.event.server.FMLServerStartedEvent; import net.minecraftforge.fml.event.server.FMLServerStartingEvent; @@ -42,8 +43,6 @@ public AdvancedBackups() public void onServerStarting(FMLServerStartingEvent event) { // Do something when the server starts - ABConfig.loadOrCreateConfig(); - LOGGER.info("Config loaded!!"); ABCore.worldName = event.getServer().getWorldData().getLevelName(); ABCore.worldDir = event.getServer().getWorldPath(FolderName.ROOT); @@ -55,6 +54,12 @@ public void onServerStarting(FMLServerStartingEvent event) ABCore.infoLogger = infoLogger; ABCore.warningLogger = warningLogger; ABCore.errorLogger = errorLogger; + + ABCore.modJar = ModList.get().getModFileById("advancedbackups").getFile().getFilePath().toFile(); + + + ABConfig.loadOrCreateConfig(); + LOGGER.info("Config loaded!!"); } From 5f69c5b7730a3df7e58d6bb18410b1d468126fb5 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Sat, 2 Sep 2023 20:43:06 +0100 Subject: [PATCH 235/580] support #10 on forge 1.12 and fix a crash --- .../mommyheather/advancedbackups/AdvancedBackups.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index f0a33b15..b47d31b0 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -3,6 +3,7 @@ import net.minecraft.init.Blocks; import net.minecraft.server.MinecraftServer; import net.minecraft.world.WorldServer; +import net.minecraftforge.fml.common.Loader; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod.EventBusSubscriber; import net.minecraftforge.fml.common.Mod.EventHandler; @@ -62,8 +63,6 @@ public AdvancedBackups() public void onServerStarting(FMLServerStartingEvent event) { // Do something when the server starts - ABConfig.loadOrCreateConfig(); - LOGGER.info("Config loaded!!"); ABCore.worldName = event.getServer().worlds[0].getWorldInfo().getWorldName(); //Yes, this works. Yes, it feels FUCKING ILLEGAL @@ -85,6 +84,14 @@ public void onServerStarting(FMLServerStartingEvent event) ABCore.warningLogger = warningLogger; ABCore.errorLogger = errorLogger; + + ABCore.modJar = Loader.instance().getIndexedModList().get("advancedbackups").getSource(); + //ModList.get().getModFileById("advancedbackups").getFile().getFilePath().toFile(); + ABConfig.loadOrCreateConfig(); + LOGGER.info("Config loaded!!"); + + + event.registerServerCommand(new AdvancedBackupsCommand()); } From aeb692dbfde94e3d2ef12ef74a5fdc8a0ce3c0aa Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Sat, 2 Sep 2023 20:50:01 +0100 Subject: [PATCH 236/580] support #10 forge 1.7.10, fix crash --- .../uk/mommyheather/advancedbackups/AdvancedBackups.java | 8 ++++++-- src/main/resources/mcmod.info | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index c209df4c..5a909da5 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -9,6 +9,7 @@ import co.uk.mommyheather.advancedbackups.core.ABCore; import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; import co.uk.mommyheather.advancedbackups.core.config.ABConfig; +import cpw.mods.fml.common.Loader; import cpw.mods.fml.common.Mod; import cpw.mods.fml.common.Mod.EventHandler; import cpw.mods.fml.common.event.FMLPreInitializationEvent; @@ -61,8 +62,6 @@ public AdvancedBackups() public void onServerStarting(FMLServerStartingEvent event) { // Do something when the server starts - ABConfig.loadOrCreateConfig(); - LOGGER.info("Config loaded!!"); ABCore.worldName = event.getServer().worldServers[0].getWorldInfo().getWorldName(); //Yes, this works. Yes, it feels FUCKING ILLEGAL @@ -85,6 +84,11 @@ public void onServerStarting(FMLServerStartingEvent event) ABCore.errorLogger = errorLogger; event.registerServerCommand(new AdvancedBackupsCommand()); + + ABCore.modJar = Loader.instance().getIndexedModList().get("advancedbackups").getSource(); + + ABConfig.loadOrCreateConfig(); + LOGGER.info("Config loaded!!"); } diff --git a/src/main/resources/mcmod.info b/src/main/resources/mcmod.info index 0b8455ee..cad387cd 100644 --- a/src/main/resources/mcmod.info +++ b/src/main/resources/mcmod.info @@ -2,7 +2,7 @@ { "modid": "advancedbackups", "name": "Advanced Backups", - "version": "1.0", + "version": "2.0", "mcversion": "1.7.10", "description": "A highly advanced backup mod.", "url": "https://github.com/MommyHeather/AdvancedBackups", From 0d5489414e14c74c6db86cb84c7b82fea34850bc Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Sat, 2 Sep 2023 21:11:00 +0100 Subject: [PATCH 237/580] support #10 on fabric 1.18, fix crash --- .../advancedbackups/AdvancedBackups.java | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 8bba8190..448a7769 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -4,10 +4,12 @@ import net.fabricmc.fabric.api.command.v1.CommandRegistrationCallback; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; +import net.fabricmc.loader.impl.FabricLoaderImpl; import net.minecraft.server.MinecraftServer; import net.minecraft.server.world.ServerWorld; import net.minecraft.util.WorldSavePath; +import java.io.File; import java.util.function.Consumer; import org.slf4j.Logger; @@ -34,8 +36,6 @@ public class AdvancedBackups implements ModInitializer { public void onInitialize() { ServerLifecycleEvents.SERVER_STARTING.register((server) -> { AdvancedBackups.server = server; - ABConfig.loadOrCreateConfig(); - LOGGER.info("Config loaded!!"); ABCore.worldName = server.getSaveProperties().getLevelName(); ABCore.worldDir = server.getSavePath(WorldSavePath.ROOT); @@ -46,6 +46,13 @@ public void onInitialize() { ABCore.infoLogger = infoLogger; ABCore.warningLogger = warningLogger; ABCore.errorLogger = errorLogger; + + + ABCore.modJar = new File(FabricLoaderImpl.INSTANCE.getModContainer("advancedbackups").get().getOrigin().toString()); + + + ABConfig.loadOrCreateConfig(); + LOGGER.info("Config loaded!!"); }); ServerLifecycleEvents.SERVER_STARTED.register((server) -> { @@ -62,6 +69,8 @@ public void onInitialize() { CommandRegistrationCallback.EVENT.register((dispatcher, isDedicated) -> { AdvancedBackupsCommand.register(dispatcher); }); + + } From ad9f409848cbea8af17d901d29fec207a4afaf33 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Mon, 4 Sep 2023 01:21:14 +0100 Subject: [PATCH 238/580] Support config rewrite. --- .../co/uk/mommyheather/advancedbackups/AdvancedBackups.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 8f391648..2d67a636 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -4,7 +4,7 @@ import co.uk.mommyheather.advancedbackups.core.ABCore; import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; -import co.uk.mommyheather.advancedbackups.core.config.ABConfig; +import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.storage.LevelResource; @@ -58,7 +58,7 @@ public void onServerStarting(ServerStartingEvent event) ABCore.modJar = ModList.get().getModFileById("advancedbackups").getFile().getFilePath().toFile(); - ABConfig.loadOrCreateConfig(); + ConfigManager.loadOrCreateConfig(); LOGGER.info("Config loaded!!"); } From e5848eb36a24decc58bcb7e5d0fcb9f9c098c7e4 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Mon, 4 Sep 2023 03:00:47 +0100 Subject: [PATCH 239/580] change to new config --- .../co/uk/mommyheather/advancedbackups/AdvancedBackups.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index c360cdbb..f8ea0139 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -4,7 +4,7 @@ import co.uk.mommyheather.advancedbackups.core.ABCore; import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; -import co.uk.mommyheather.advancedbackups.core.config.ABConfig; +import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.storage.LevelResource; @@ -59,7 +59,7 @@ public void onServerStarting(ServerStartingEvent event) ABCore.modJar = ModList.get().getModFileById("advancedbackups").getFile().getFilePath().toFile(); - ABConfig.loadOrCreateConfig(); + ConfigManager.loadOrCreateConfig(); LOGGER.info("Config loaded!!"); From 275dd1006f7a8b74f08197dc96489490aba76e39 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Mon, 4 Sep 2023 20:19:36 +0100 Subject: [PATCH 240/580] support new config --- .../co/uk/mommyheather/advancedbackups/AdvancedBackups.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 52539daf..053e4f76 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -3,7 +3,7 @@ import co.uk.mommyheather.advancedbackups.core.ABCore; import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; -import co.uk.mommyheather.advancedbackups.core.config.ABConfig; +import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; import net.minecraft.server.MinecraftServer; import net.minecraft.world.server.ServerWorld; import net.minecraft.world.storage.FolderName; @@ -58,7 +58,7 @@ public void onServerStarting(FMLServerStartingEvent event) ABCore.modJar = ModList.get().getModFileById("advancedbackups").getFile().getFilePath().toFile(); - ABConfig.loadOrCreateConfig(); + ConfigManager.loadOrCreateConfig(); LOGGER.info("Config loaded!!"); } From 29d3ee573efcfa1a4289432e8a225b3a9e3d654c Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Mon, 4 Sep 2023 20:24:27 +0100 Subject: [PATCH 241/580] support new config --- .../co/uk/mommyheather/advancedbackups/AdvancedBackups.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index b47d31b0..6f16cd75 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -20,7 +20,7 @@ import co.uk.mommyheather.advancedbackups.core.ABCore; import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; -import co.uk.mommyheather.advancedbackups.core.config.ABConfig; +import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; import net.minecraftforge.common.MinecraftForge; import java.io.File; @@ -87,7 +87,7 @@ public void onServerStarting(FMLServerStartingEvent event) ABCore.modJar = Loader.instance().getIndexedModList().get("advancedbackups").getSource(); //ModList.get().getModFileById("advancedbackups").getFile().getFilePath().toFile(); - ABConfig.loadOrCreateConfig(); + ConfigManager.loadOrCreateConfig(); LOGGER.info("Config loaded!!"); From 7b4f612a36c570cc0f60bab35fcb84dcee5f37f8 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Mon, 4 Sep 2023 20:28:56 +0100 Subject: [PATCH 242/580] support new connfig --- .../co/uk/mommyheather/advancedbackups/AdvancedBackups.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 5a909da5..713c477d 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -8,7 +8,7 @@ import co.uk.mommyheather.advancedbackups.core.ABCore; import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; -import co.uk.mommyheather.advancedbackups.core.config.ABConfig; +import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; import cpw.mods.fml.common.Loader; import cpw.mods.fml.common.Mod; import cpw.mods.fml.common.Mod.EventHandler; @@ -87,7 +87,7 @@ public void onServerStarting(FMLServerStartingEvent event) ABCore.modJar = Loader.instance().getIndexedModList().get("advancedbackups").getSource(); - ABConfig.loadOrCreateConfig(); + ConfigManager.loadOrCreateConfig(); LOGGER.info("Config loaded!!"); } From ad0bbaba6db552632fd8659ee657cd1847ff0fcf Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Mon, 4 Sep 2023 20:32:22 +0100 Subject: [PATCH 243/580] support new config --- .../co/uk/mommyheather/advancedbackups/AdvancedBackups.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 448a7769..9d3bebbf 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -17,7 +17,7 @@ import co.uk.mommyheather.advancedbackups.core.ABCore; import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; -import co.uk.mommyheather.advancedbackups.core.config.ABConfig; +import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; public class AdvancedBackups implements ModInitializer { // This logger is used to write text to the console and the log file. @@ -51,7 +51,7 @@ public void onInitialize() { ABCore.modJar = new File(FabricLoaderImpl.INSTANCE.getModContainer("advancedbackups").get().getOrigin().toString()); - ABConfig.loadOrCreateConfig(); + ConfigManager.loadOrCreateConfig(); LOGGER.info("Config loaded!!"); }); From aed061b558772e3ca20cc2ee1d4476480fcd57d5 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Thu, 7 Sep 2023 13:52:05 +0100 Subject: [PATCH 244/580] silent support --- .../co/uk/mommyheather/advancedbackups/AdvancedBackups.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index f8ea0139..644c1b57 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -117,6 +117,7 @@ public static void disableSaving() { level.noSave = true; } } + if (ConfigManager.silent.get()) return; warningLogger.accept(savesDisabledMessage); } @@ -127,12 +128,14 @@ public static void enableSaving() { level.noSave = false; } } + if (ConfigManager.silent.get()) return; warningLogger.accept(savesEnabledMessage); } public static void saveOnce() { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); server.saveEverything(true, true, true); + if (ConfigManager.silent.get()) return; warningLogger.accept(saveCompleteMessage); } From a84592651fdbb3ceeba57f729a1aaaf66fe3db57 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Thu, 7 Sep 2023 14:17:40 +0100 Subject: [PATCH 245/580] silent --- .../co/uk/mommyheather/advancedbackups/AdvancedBackups.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 2d67a636..721d8e7f 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -115,6 +115,7 @@ public static void disableSaving() { level.noSave = true; } } + if (ConfigManager.silent.get()) return; warningLogger.accept(savesDisabledMessage); } @@ -125,12 +126,14 @@ public static void enableSaving() { level.noSave = false; } } + if (ConfigManager.silent.get()) return; warningLogger.accept(savesEnabledMessage); } public static void saveOnce() { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); server.saveEverything(true, true, true); + if (ConfigManager.silent.get()) return; warningLogger.accept(saveCompleteMessage); } From c52a23a58c502a65ef2e48c1d8dd95cb554bd8e6 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Thu, 7 Sep 2023 15:39:17 +0100 Subject: [PATCH 246/580] silent --- .../co/uk/mommyheather/advancedbackups/AdvancedBackups.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 9d3bebbf..e74a04bc 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -104,6 +104,7 @@ public static void disableSaving() { level.savingDisabled = true; } } + if (ConfigManager.silent.get()) return; warningLogger.accept(savesDisabledMessage); } @@ -114,12 +115,14 @@ public static void enableSaving() { level.savingDisabled = false; } } + if (ConfigManager.silent.get()) return; warningLogger.accept(savesEnabledMessage); } public static void saveOnce() { MinecraftServer server = AdvancedBackups.server; server.saveAll(true, true, true); + if (ConfigManager.silent.get()) return; warningLogger.accept(saveCompleteMessage); } } \ No newline at end of file From c8bbeea126b0f71fb215981d3f8e591f0f917c7a Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Thu, 7 Sep 2023 15:46:33 +0100 Subject: [PATCH 247/580] silent --- .../co/uk/mommyheather/advancedbackups/AdvancedBackups.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 053e4f76..6dfea64d 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -97,6 +97,7 @@ public static void disableSaving() { level.noSave = true; } } + if (ConfigManager.silent.get()) return; warningLogger.accept(savesDisabledMessage); } @@ -107,12 +108,14 @@ public static void enableSaving() { level.noSave = false; } } + if (ConfigManager.silent.get()) return; warningLogger.accept(savesEnabledMessage); } public static void saveOnce() { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); server.saveAllChunks(true, true, true); + if (ConfigManager.silent.get()) return; warningLogger.accept(saveCompleteMessage); } From 61015b021437374b92af2a166be7b9802981792c Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Thu, 7 Sep 2023 16:21:36 +0100 Subject: [PATCH 248/580] silent --- .../co/uk/mommyheather/advancedbackups/AdvancedBackups.java | 3 +++ src/main/resources/mcmod.info | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 6f16cd75..44296074 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -124,6 +124,7 @@ public static void disableSaving() { level.disableLevelSaving = true; } } + if (ConfigManager.silent.get()) return; warningLogger.accept(savesDisabledMessage); } @@ -133,11 +134,13 @@ public static void enableSaving() { level.disableLevelSaving = false; } } + if (ConfigManager.silent.get()) return; warningLogger.accept(savesEnabledMessage); } public static void saveOnce() { server.saveAllWorlds(false); + if (ConfigManager.silent.get()) return; warningLogger.accept(saveCompleteMessage); } diff --git a/src/main/resources/mcmod.info b/src/main/resources/mcmod.info index 38903d90..2c48de3f 100644 --- a/src/main/resources/mcmod.info +++ b/src/main/resources/mcmod.info @@ -3,7 +3,7 @@ "modid": "advancedbackups", "name": "Advanced Backups", "description": "Powerful backup mod.", - "version": "1.0 ", + "version": "2.0 ", "url": "https://github.com/MommyHeather/AdvancedBackups", "updateUrl": "", "authorList": ["MommyHeather"], From 6fc5348bb26cf85f6bd7ac51d9616cf9c71f5e25 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Thu, 7 Sep 2023 16:35:26 +0100 Subject: [PATCH 249/580] silent --- .../co/uk/mommyheather/advancedbackups/AdvancedBackups.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 713c477d..4023b5fd 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -122,6 +122,7 @@ public static void disableSaving() { level.levelSaving = true; } } + if (ConfigManager.silent.get()) return; warningLogger.accept(savesDisabledMessage); } @@ -132,6 +133,7 @@ public static void enableSaving() { level.levelSaving = false; } } + if (ConfigManager.silent.get()) return; warningLogger.accept(savesEnabledMessage); } @@ -141,6 +143,7 @@ public static void saveOnce() { Class[] classes = {Boolean.class}; Method saveMethod = MinecraftServer.class.getMethod("saveAllWorlds", classes); saveMethod.invoke(server, false); + if (ConfigManager.silent.get()) return; warningLogger.accept(saveCompleteMessage); } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException e) { // TODO Scream at user From 4d000381bcba73adb93f301b9ed14977cfbd07a7 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Wed, 20 Sep 2023 14:40:42 +0100 Subject: [PATCH 250/580] remove version from build.gradle, as it'll be passed in cli in future --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index bf940671..fd28876f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -10,7 +10,7 @@ plugins { -version = "2.0" +//version = "2.0" group = "co.uk.mommyheather.advancedbackups" // http://maven.apache.org/guides/mini/guide-naming-conventions.html //archivesBaseName = "AdvancedBackups-forge-1.7.10" From fed69a519bdd8c0838079362c6228cb392a981dd Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Wed, 20 Sep 2023 14:41:31 +0100 Subject: [PATCH 251/580] add gradle script and wrapper --- gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 61608 bytes gradle/wrapper/gradle-wrapper.properties | 6 + gradlew | 244 +++++++++++++++++++++++ 3 files changed, 250 insertions(+) create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100644 gradlew diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..ccebba7710deaf9f98673a68957ea02138b60d0a GIT binary patch literal 61608 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 literal 0 HcmV?d00001 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..bdc9a83b --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.2-bin.zip +networkTimeout=10000 +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100644 index 00000000..79a61d42 --- /dev/null +++ b/gradlew @@ -0,0 +1,244 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" From 0a2f8bdded0e280c081b7a0cf94c4d9de6a3a1ac Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Wed, 20 Sep 2023 14:43:28 +0100 Subject: [PATCH 252/580] make gradlew executable --- gradlew | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 gradlew diff --git a/gradlew b/gradlew old mode 100644 new mode 100755 From f55fd95495d9f740649b1b6a4ab405d4d9ed1185 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Wed, 20 Sep 2023 14:48:56 +0100 Subject: [PATCH 253/580] adjust corelib dependency --- build.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index fd28876f..c8acd55a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -106,8 +106,8 @@ dependencies { // Adds NotEnoughItems and its dependencies (CCL&CCC) to runClient/runServer runtimeOnlyNonPublishable("com.github.GTNewHorizons:NotEnoughItems:2.3.39-GTNH:dev") - implementation (files("../advancedbackups-corelib.jar")) - extraLibs (files("../advancedbackups-corelib.jar")) + implementation (files("advancedbackups-corelib.jar")) + extraLibs (files("advancedbackups-corelib.jar")) // Example: grab the ic2 jar from curse maven and deobfuscate // api(rfg.deobf("curse.maven:ic2-242638:2353971")) // Example: grab the ic2 jar from libs/ in the workspace and deobfuscate From fd486fff427fc005c7b189fa85e214dda57dc92e Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Wed, 20 Sep 2023 16:13:29 +0100 Subject: [PATCH 254/580] whoops --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index c8acd55a..d9b1685f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -135,7 +135,7 @@ publishing { } tasks.withType { - from(zipTree("../advancedbackups-corelib.jar")) + from(zipTree("advancedbackups-corelib.jar")) into("/") duplicatesStrategy = DuplicatesStrategy.EXCLUDE //from(zipTree("dependencies/jna-platform-5.13.0.jar")) From 2d23b8bbb2b444874401447f912dc08e76181d39 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Wed, 20 Sep 2023 16:32:18 +0100 Subject: [PATCH 255/580] Versioning stuff --- src/main/resources/META-INF/mods.toml | 62 --------------------------- src/main/resources/mcmod.info | 2 +- 2 files changed, 1 insertion(+), 63 deletions(-) delete mode 100644 src/main/resources/META-INF/mods.toml diff --git a/src/main/resources/META-INF/mods.toml b/src/main/resources/META-INF/mods.toml deleted file mode 100644 index ad0e6ca5..00000000 --- a/src/main/resources/META-INF/mods.toml +++ /dev/null @@ -1,62 +0,0 @@ -# This is an example mods.toml file. It contains the data relating to the loading mods. -# There are several mandatory fields (#mandatory), and many more that are optional (#optional). -# The overall format is standard TOML format, v0.5.0. -# Note that there are a couple of TOML lists in this file. -# Find more information on toml format here: https://github.com/toml-lang/toml -# The name of the mod loader type to load - for regular FML @Mod mods it should be javafml -modLoader="javafml" #mandatory -# A version range to match for said mod loader - for regular FML @Mod it will be the forge version -loaderVersion="[40,)" #mandatory This is typically bumped every Minecraft version by Forge. See our download page for lists of versions. -# The license for you mod. This is mandatory metadata and allows for easier comprehension of your redistributive properties. -# Review your options at https://choosealicense.com/. All rights reserved is the default copyright stance, and is thus the default here. -license="MIT" -# A URL to refer people to when problems occur with this mod -#issueTrackerURL="https://change.me.to.your.issue.tracker.example.invalid/" #optional -# A list of mods - how many allowed here is determined by the individual mod loader -[[mods]] #mandatory -# The modid of the mod -modId="advancedbackups" #mandatory -# The version number of the mod - there's a few well known ${} variables useable here or just hardcode it -# ${file.jarVersion} will substitute the value of the Implementation-Version as read from the mod's JAR file metadata -# see the associated build.gradle script for how to populate this completely automatically during a build -version="${file.jarVersion}" #mandatory - # A display name for the mod -displayName="Advanced Backups" #mandatory -# A URL to query for updates for this mod. See the JSON update specification https://mcforge.readthedocs.io/en/latest/gettingstarted/autoupdate/ -#updateJSONURL="https://change.me.example.invalid/updates.json" #optional -# A URL for the "homepage" for this mod, displayed in the mod UI -#displayURL="https://change.me.to.your.mods.homepage.example.invalid/" #optional -# A file name (in the root of the mod JAR) containing a logo for display -#logoFile="advancedbackups.png" #optional -# A text field displayed in the mod UI -#credits="Thanks for this example mod goes to Java" #optional -# A text field displayed in the mod UI -#authors="Love, Cheese and small house plants" #optional -# The description text for the mod (multi line!) (#mandatory) -description=''' -An extremely advanced backup mod. - -Supports many backup types. - -Config file and github contain documentation. -''' -# A dependency - use the . to indicate dependency for a specific modid. Dependencies are optional. -[[dependencies.advancedbackups]] #optional - # the modid of the dependency - modId="forge" #mandatory - # Does this dependency have to exist - if not, ordering below must be specified - mandatory=true #mandatory - # The version range of the dependency - versionRange="[40,)" #mandatory - # An ordering relationship for the dependency - BEFORE or AFTER required if the relationship is not mandatory - ordering="NONE" - # Side this dependency is applied on - BOTH, CLIENT or SERVER - side="BOTH" -# Here's another dependency -[[dependencies.advancedbackups]] - modId="minecraft" - mandatory=true -# This version range declares a minimum of the current minecraft version up to but not including the next major version - versionRange="[1.18.2,1.19)" - ordering="NONE" - side="BOTH" diff --git a/src/main/resources/mcmod.info b/src/main/resources/mcmod.info index cad387cd..3c25a4cd 100644 --- a/src/main/resources/mcmod.info +++ b/src/main/resources/mcmod.info @@ -2,7 +2,7 @@ { "modid": "advancedbackups", "name": "Advanced Backups", - "version": "2.0", + "version": "${version}", "mcversion": "1.7.10", "description": "A highly advanced backup mod.", "url": "https://github.com/MommyHeather/AdvancedBackups", From 7e4f0de0e798cf1cb9d23da488a10dabacc8af30 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Wed, 20 Sep 2023 16:34:03 +0100 Subject: [PATCH 256/580] Make gradle executable --- gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 54708 bytes gradle/wrapper/gradle-wrapper.properties | 5 + gradlew | 172 +++++++++++++++++++++++ settings.gradle | 8 ++ 4 files changed, 185 insertions(+) create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100644 gradlew create mode 100644 settings.gradle diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..7a3265ee94c0ab25cf079ac8ccdf87f41d455d42 GIT binary patch literal 54708 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

_x$+l{{cH8$W#CT literal 0 HcmV?d00001 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..0e9a6105 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip diff --git a/gradlew b/gradlew new file mode 100644 index 00000000..cccdd3d5 --- /dev/null +++ b/gradlew @@ -0,0 +1,172 @@ +#!/usr/bin/env sh + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 00000000..45230aa9 --- /dev/null +++ b/settings.gradle @@ -0,0 +1,8 @@ +pluginManagement { + repositories { + maven { + name 'MinecraftForge' + url 'https://maven.minecraftforge.net/' + } + } +} From 27dd6a06123a32f3507ab145ddb72cb4a84f8b11 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Wed, 20 Sep 2023 16:34:30 +0100 Subject: [PATCH 257/580] again --- gradlew | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 gradlew diff --git a/gradlew b/gradlew old mode 100644 new mode 100755 From 933b2d9ae858420e10f70d61a62b4eff89d700a0 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Wed, 20 Sep 2023 16:35:51 +0100 Subject: [PATCH 258/580] versioning stuff --- build.gradle | 11 +++-- src/main/resources/META-INF/mods.toml | 62 --------------------------- src/main/resources/mcmod.info | 2 +- 3 files changed, 6 insertions(+), 69 deletions(-) delete mode 100644 src/main/resources/META-INF/mods.toml diff --git a/build.gradle b/build.gradle index 6b81fc16..ad85255e 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,6 @@ plugins { } -version = '2.0' group = 'co.uk.mommyheather.advancedbackups' // http://maven.apache.org/guides/mini/guide-naming-conventions.html archivesBaseName = 'AdvancedBackups-' + modloaderName + "-" + minecraftVersion @@ -57,8 +56,8 @@ dependencies { // that the dep is a ForgeGradle 'patcher' dependency. And it's patches will be applied. // The userdev artifact is a special name and will get all sorts of transformations applied to it. minecraft 'net.minecraftforge:forge:1.12.2-14.23.5.2855' - implementation files ('../advancedbackups-corelib.jar') - extraLibs files ('../advancedbackups-corelib.jar') + implementation files ('advancedbackups-corelib.jar') + extraLibs files ('advancedbackups-corelib.jar') // You may put jars on which you depend on in ./libs or you may define them like so.. // compile "some.group:artifact:version:classifier" @@ -86,12 +85,12 @@ jar { attributes([ "Main-Class" : "co.uk.mommyheather.advancedbackups.cli.AdvancedBackupsCLI", "Specification-Title" : "advancedbackups", - "Specification-Vendor" : "raveninthedark", + "Specification-Vendor" : "mommyheather", "Specification-Version" : "1", // We are version 1 of ourselves "Implementation-Title" : project.name, "Implementation-Version": "${version}", - "Implementation-Vendor" :"raveninthedark", - "Implementation-Vendor" : "raveninthedark", + "Implementation-Vendor" :"mommyheather", + "Implementation-Vendor" : "mommyheather", "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ") ]) } diff --git a/src/main/resources/META-INF/mods.toml b/src/main/resources/META-INF/mods.toml deleted file mode 100644 index ad0e6ca5..00000000 --- a/src/main/resources/META-INF/mods.toml +++ /dev/null @@ -1,62 +0,0 @@ -# This is an example mods.toml file. It contains the data relating to the loading mods. -# There are several mandatory fields (#mandatory), and many more that are optional (#optional). -# The overall format is standard TOML format, v0.5.0. -# Note that there are a couple of TOML lists in this file. -# Find more information on toml format here: https://github.com/toml-lang/toml -# The name of the mod loader type to load - for regular FML @Mod mods it should be javafml -modLoader="javafml" #mandatory -# A version range to match for said mod loader - for regular FML @Mod it will be the forge version -loaderVersion="[40,)" #mandatory This is typically bumped every Minecraft version by Forge. See our download page for lists of versions. -# The license for you mod. This is mandatory metadata and allows for easier comprehension of your redistributive properties. -# Review your options at https://choosealicense.com/. All rights reserved is the default copyright stance, and is thus the default here. -license="MIT" -# A URL to refer people to when problems occur with this mod -#issueTrackerURL="https://change.me.to.your.issue.tracker.example.invalid/" #optional -# A list of mods - how many allowed here is determined by the individual mod loader -[[mods]] #mandatory -# The modid of the mod -modId="advancedbackups" #mandatory -# The version number of the mod - there's a few well known ${} variables useable here or just hardcode it -# ${file.jarVersion} will substitute the value of the Implementation-Version as read from the mod's JAR file metadata -# see the associated build.gradle script for how to populate this completely automatically during a build -version="${file.jarVersion}" #mandatory - # A display name for the mod -displayName="Advanced Backups" #mandatory -# A URL to query for updates for this mod. See the JSON update specification https://mcforge.readthedocs.io/en/latest/gettingstarted/autoupdate/ -#updateJSONURL="https://change.me.example.invalid/updates.json" #optional -# A URL for the "homepage" for this mod, displayed in the mod UI -#displayURL="https://change.me.to.your.mods.homepage.example.invalid/" #optional -# A file name (in the root of the mod JAR) containing a logo for display -#logoFile="advancedbackups.png" #optional -# A text field displayed in the mod UI -#credits="Thanks for this example mod goes to Java" #optional -# A text field displayed in the mod UI -#authors="Love, Cheese and small house plants" #optional -# The description text for the mod (multi line!) (#mandatory) -description=''' -An extremely advanced backup mod. - -Supports many backup types. - -Config file and github contain documentation. -''' -# A dependency - use the . to indicate dependency for a specific modid. Dependencies are optional. -[[dependencies.advancedbackups]] #optional - # the modid of the dependency - modId="forge" #mandatory - # Does this dependency have to exist - if not, ordering below must be specified - mandatory=true #mandatory - # The version range of the dependency - versionRange="[40,)" #mandatory - # An ordering relationship for the dependency - BEFORE or AFTER required if the relationship is not mandatory - ordering="NONE" - # Side this dependency is applied on - BOTH, CLIENT or SERVER - side="BOTH" -# Here's another dependency -[[dependencies.advancedbackups]] - modId="minecraft" - mandatory=true -# This version range declares a minimum of the current minecraft version up to but not including the next major version - versionRange="[1.18.2,1.19)" - ordering="NONE" - side="BOTH" diff --git a/src/main/resources/mcmod.info b/src/main/resources/mcmod.info index 2c48de3f..e576d9e0 100644 --- a/src/main/resources/mcmod.info +++ b/src/main/resources/mcmod.info @@ -3,7 +3,7 @@ "modid": "advancedbackups", "name": "Advanced Backups", "description": "Powerful backup mod.", - "version": "2.0 ", + "version": "${version}", "url": "https://github.com/MommyHeather/AdvancedBackups", "updateUrl": "", "authorList": ["MommyHeather"], From 8a184b591e8f4da49ebb26a526f0aad334ead32f Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Wed, 20 Sep 2023 16:38:46 +0100 Subject: [PATCH 259/580] files needed to run gradle --- build.gradle | 11 +- gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 54413 bytes gradle/wrapper/gradle-wrapper.properties | 5 + gradlew | 172 +++++++++++++++++++++++ 4 files changed, 182 insertions(+), 6 deletions(-) create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100644 gradlew diff --git a/build.gradle b/build.gradle index 80a789b8..739a9157 100644 --- a/build.gradle +++ b/build.gradle @@ -12,7 +12,6 @@ apply plugin: 'net.minecraftforge.gradle' apply plugin: 'eclipse' apply plugin: 'maven-publish' -version = '2.0' group = 'co.uk.mommyheather.advancedbackups' // http://maven.apache.org/guides/mini/guide-naming-conventions.html archivesBaseName = 'AdvancedBackups-' + modloaderName + "-" + minecraftVersion @@ -124,8 +123,8 @@ dependencies { // The userdev artifact is a special name and will get all sorts of transformations applied to it. minecraft 'net.minecraftforge:forge:1.16.5-36.1.0' - implementation files ('../advancedbackups-corelib.jar') - extraLibs files ('../advancedbackups-corelib.jar') + implementation files ('advancedbackups-corelib.jar') + extraLibs files ('advancedbackups-corelib.jar') // You may put jars on which you depend on in ./libs or you may define them like so.. // compile "some.group:artifact:version:classifier" // compile "some.group:artifact:version" @@ -152,12 +151,12 @@ jar { attributes([ "Main-Class" : "co.uk.mommyheather.advancedbackups.cli.AdvancedBackupsCLI", "Specification-Title" : "advancedbackups", - "Specification-Vendor" : "raveninthedark", + "Specification-Vendor" : "mommyheather", "Specification-Version" : "1", // We are version 1 of ourselves "Implementation-Title" : project.name, "Implementation-Version": "${version}", - "Implementation-Vendor" :"raveninthedark", - "Implementation-Vendor" : "raveninthedark", + "Implementation-Vendor" :"mommyheather", + "Implementation-Vendor" : "mommyheather", "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ") ]) } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..0d4a9516871afd710a9d84d89e31ba77745607bd GIT binary patch literal 54413 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 literal 0 HcmV?d00001 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..1c4bcc29 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.1-all.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100644 index 00000000..cccdd3d5 --- /dev/null +++ b/gradlew @@ -0,0 +1,172 @@ +#!/usr/bin/env sh + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" From 73b539b6c93cc1d985b1d7805d295138ca1c5c57 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Wed, 20 Sep 2023 16:39:09 +0100 Subject: [PATCH 260/580] make gradlew executable --- gradlew | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 gradlew diff --git a/gradlew b/gradlew old mode 100644 new mode 100755 From 9cb62d4f5343e3a3e4c94765959db102b6583671 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Wed, 20 Sep 2023 16:46:03 +0100 Subject: [PATCH 261/580] version stuff + things needed for gradle to run --- .gitignore | 1 - build.gradle | 9 +- gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 59536 bytes gradle/wrapper/gradle-wrapper.properties | 5 + gradlew | 234 +++++++++++++++++++++++ 5 files changed, 243 insertions(+), 6 deletions(-) create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100644 gradlew diff --git a/.gitignore b/.gitignore index 12ae3a47..12f86447 100644 --- a/.gitignore +++ b/.gitignore @@ -16,7 +16,6 @@ out # gradle build .gradle -gradle # other eclipse diff --git a/build.gradle b/build.gradle index 93932248..74f0a710 100644 --- a/build.gradle +++ b/build.gradle @@ -16,7 +16,6 @@ plugins { apply plugin: 'net.minecraftforge.gradle' -version = '2.0' group = 'co.uk.mommyheather.advancedbackups' // http://maven.apache.org/guides/mini/guide-naming-conventions.html archivesBaseName = 'AdvancedBackups-' + modloaderName + "-" + minecraftVersion @@ -159,8 +158,8 @@ dependencies { minecraft 'net.minecraftforge:forge:1.18.2-40.2.1' //extraLibs 'com.sun.jna.platform:5.13.0' - minecraftLibrary files ('../advancedbackups-corelib.jar') - extraLibs files ('../advancedbackups-corelib.jar') + minecraftLibrary files ('advancedbackups-corelib.jar') + extraLibs files ('advancedbackups-corelib.jar') // Real mod deobf dependency examples - these get remapped to your current mappings // compileOnly fg.deobf("mezz.jei:jei-${mc_version}:${jei_version}:api") // Adds JEI API as a compile dependency @@ -181,11 +180,11 @@ jar { attributes([ "Main-Class" : "co.uk.mommyheather.advancedbackups.cli.AdvancedBackupsCLI", "Specification-Title" : "advancedbackups", - "Specification-Vendor" : "raveninthedark", + "Specification-Vendor" : "mommyheather", "Specification-Version" : "1", // We are version 1 of ourselves "Implementation-Title" : project.name, "Implementation-Version" : project.jar.archiveVersion, - "Implementation-Vendor" : "raveninthedark", + "Implementation-Vendor" : "mommyheather", "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ") ]) } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..7454180f2ae8848c63b8b4dea2cb829da983f2fa GIT binary patch literal 59536 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 QuEJmfE|#`Dqx|px0L@K;Y5)KL literal 0 HcmV?d00001 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..ae04661e --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100644 index 00000000..c53aefaa --- /dev/null +++ b/gradlew @@ -0,0 +1,234 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit + +APP_NAME="Gradle" +APP_BASE_NAME=${0##*/} + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" From 8300a16f33fba47b1c0bc05baec6dd28cc6259a0 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Wed, 20 Sep 2023 16:46:29 +0100 Subject: [PATCH 262/580] make gradlew executable --- gradlew | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 gradlew diff --git a/gradlew b/gradlew old mode 100644 new mode 100755 From 25a5e18252ada4318b91c080df2bc5a00ba19698 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Wed, 20 Sep 2023 16:57:45 +0100 Subject: [PATCH 263/580] Versioning changes for nnew build workflow --- build.gradle | 10 ++--- gradle.properties | 2 +- src/main/resources/META-INF/mods.toml | 62 --------------------------- src/main/resources/fabric.mod.json | 2 +- 4 files changed, 6 insertions(+), 70 deletions(-) delete mode 100644 src/main/resources/META-INF/mods.toml diff --git a/build.gradle b/build.gradle index 5507b3ba..d51c2539 100644 --- a/build.gradle +++ b/build.gradle @@ -3,7 +3,6 @@ plugins { id 'maven-publish' } -version = project.mod_version group = project.maven_group archivesBaseName = 'AdvancedBackups-' + modloaderName + "-" + minecraftVersion @@ -36,9 +35,8 @@ dependencies { // modImplementation "net.fabricmc.fabric-api:fabric-api-deprecated:${project.fabric_version}" - implementation files ('../advancedbackups-corelib.jar') - extraLibs files ('../advancedbackups-corelib.jar') - + implementation files ('advancedbackups-corelib.jar') + extraLibs files ('advancedbackups-corelib.jar') } processResources { @@ -68,11 +66,11 @@ jar { attributes([ "Main-Class" : "co.uk.mommyheather.advancedbackups.cli.AdvancedBackupsCLI", "Specification-Title" : "advancedbackups", - "Specification-Vendor" : "raveninthedark", + "Specification-Vendor" : "mommyheather", "Specification-Version" : "1", // We are version 1 of ourselves "Implementation-Title" : project.name, "Implementation-Version" : project.jar.archiveVersion, - "Implementation-Vendor" : "raveninthedark", + "Implementation-Vendor" : "mommyheather", "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ") ]) } diff --git a/gradle.properties b/gradle.properties index 9e098e85..f0cad445 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,7 @@ yarn_mappings=1.18.2+build.4 loader_version=0.14.19 # Mod Properties -mod_version=2.0 +version=2.0 maven_group=co.uk.mommyheather.advancedbackups archives_base_name=advanced-backups modloaderName =fabric diff --git a/src/main/resources/META-INF/mods.toml b/src/main/resources/META-INF/mods.toml deleted file mode 100644 index ad0e6ca5..00000000 --- a/src/main/resources/META-INF/mods.toml +++ /dev/null @@ -1,62 +0,0 @@ -# This is an example mods.toml file. It contains the data relating to the loading mods. -# There are several mandatory fields (#mandatory), and many more that are optional (#optional). -# The overall format is standard TOML format, v0.5.0. -# Note that there are a couple of TOML lists in this file. -# Find more information on toml format here: https://github.com/toml-lang/toml -# The name of the mod loader type to load - for regular FML @Mod mods it should be javafml -modLoader="javafml" #mandatory -# A version range to match for said mod loader - for regular FML @Mod it will be the forge version -loaderVersion="[40,)" #mandatory This is typically bumped every Minecraft version by Forge. See our download page for lists of versions. -# The license for you mod. This is mandatory metadata and allows for easier comprehension of your redistributive properties. -# Review your options at https://choosealicense.com/. All rights reserved is the default copyright stance, and is thus the default here. -license="MIT" -# A URL to refer people to when problems occur with this mod -#issueTrackerURL="https://change.me.to.your.issue.tracker.example.invalid/" #optional -# A list of mods - how many allowed here is determined by the individual mod loader -[[mods]] #mandatory -# The modid of the mod -modId="advancedbackups" #mandatory -# The version number of the mod - there's a few well known ${} variables useable here or just hardcode it -# ${file.jarVersion} will substitute the value of the Implementation-Version as read from the mod's JAR file metadata -# see the associated build.gradle script for how to populate this completely automatically during a build -version="${file.jarVersion}" #mandatory - # A display name for the mod -displayName="Advanced Backups" #mandatory -# A URL to query for updates for this mod. See the JSON update specification https://mcforge.readthedocs.io/en/latest/gettingstarted/autoupdate/ -#updateJSONURL="https://change.me.example.invalid/updates.json" #optional -# A URL for the "homepage" for this mod, displayed in the mod UI -#displayURL="https://change.me.to.your.mods.homepage.example.invalid/" #optional -# A file name (in the root of the mod JAR) containing a logo for display -#logoFile="advancedbackups.png" #optional -# A text field displayed in the mod UI -#credits="Thanks for this example mod goes to Java" #optional -# A text field displayed in the mod UI -#authors="Love, Cheese and small house plants" #optional -# The description text for the mod (multi line!) (#mandatory) -description=''' -An extremely advanced backup mod. - -Supports many backup types. - -Config file and github contain documentation. -''' -# A dependency - use the . to indicate dependency for a specific modid. Dependencies are optional. -[[dependencies.advancedbackups]] #optional - # the modid of the dependency - modId="forge" #mandatory - # Does this dependency have to exist - if not, ordering below must be specified - mandatory=true #mandatory - # The version range of the dependency - versionRange="[40,)" #mandatory - # An ordering relationship for the dependency - BEFORE or AFTER required if the relationship is not mandatory - ordering="NONE" - # Side this dependency is applied on - BOTH, CLIENT or SERVER - side="BOTH" -# Here's another dependency -[[dependencies.advancedbackups]] - modId="minecraft" - mandatory=true -# This version range declares a minimum of the current minecraft version up to but not including the next major version - versionRange="[1.18.2,1.19)" - ordering="NONE" - side="BOTH" diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 91875b52..408a7798 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -10,7 +10,7 @@ "contact": { "homepage": "https://github.com/mommyheather/advancedbackups" }, - "license": "MIT", + "license": "BSD", "icon": "assets/advanced-backups/icon.png", "environment": "*", "entrypoints": { From 3d28c4c82e7080c5c3a61f0f3b4078f8e232ba7a Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Wed, 20 Sep 2023 16:58:15 +0100 Subject: [PATCH 264/580] make gradlew executable --- gradlew | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 gradlew diff --git a/gradlew b/gradlew old mode 100644 new mode 100755 From 89beb063b1683ce9af32c592312c97e9e1cb1c21 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Wed, 20 Sep 2023 17:01:20 +0100 Subject: [PATCH 265/580] Version stuff, files needed for workflow --- build.gradle | 9 +- gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 60756 bytes gradle/wrapper/gradle-wrapper.properties | 5 + gradlew | 240 +++++++++++++++++++++++ src/main/resources/META-INF/mods.toml | 2 +- 5 files changed, 250 insertions(+), 6 deletions(-) create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100644 gradlew diff --git a/build.gradle b/build.gradle index a6bb7622..acd8118d 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,6 @@ plugins { -version = '2.0' group = 'co.uk.mommyheather.advancedbackups' // http://maven.apache.org/guides/mini/guide-naming-conventions.html archivesBaseName = 'AdvancedBackups-' + modloaderName + "-" + minecraftVersion @@ -122,8 +121,8 @@ dependencies { //implementation files('dependencies/jansi-2.4.0.jar') //extraLibs files('dependencies/jansi-2.4.0.jar') - minecraftLibrary files ('../advancedbackups-corelib.jar') - extraLibs files ('../advancedbackups-corelib.jar') + minecraftLibrary files ('advancedbackups-corelib.jar') + extraLibs files ('advancedbackups-corelib.jar') // Real mod deobf dependency examples - these get remapped to your current mappings // compileOnly fg.deobf("mezz.jei:jei-${mc_version}:${jei_version}:api") // Adds JEI API as a compile dependency @@ -144,11 +143,11 @@ jar { attributes([ "Main-Class" : "co.uk.mommyheather.advancedbackups.cli.AdvancedBackupsCLI", "Specification-Title" : "advancedbackups", - "Specification-Vendor" : "raveninthedark", + "Specification-Vendor" : "mommyheather", "Specification-Version" : "1", // We are version 1 of ourselves "Implementation-Title" : project.name, "Implementation-Version" : project.jar.archiveVersion, - "Implementation-Vendor" : "raveninthedark", + "Implementation-Vendor" : "mommyheather", "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ") ]) } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..249e5832f090a2944b7473328c07c9755baa3196 GIT binary patch literal 60756 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 '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit + +APP_NAME="Gradle" +APP_BASE_NAME=${0##*/} + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/src/main/resources/META-INF/mods.toml b/src/main/resources/META-INF/mods.toml index 77d5bcd6..e7b49321 100644 --- a/src/main/resources/META-INF/mods.toml +++ b/src/main/resources/META-INF/mods.toml @@ -9,7 +9,7 @@ modLoader="javafml" #mandatory loaderVersion="[40,)" #mandatory This is typically bumped every Minecraft version by Forge. See our download page for lists of versions. # The license for you mod. This is mandatory metadata and allows for easier comprehension of your redistributive properties. # Review your options at https://choosealicense.com/. All rights reserved is the default copyright stance, and is thus the default here. -license="MIT" +license="BSD" # A URL to refer people to when problems occur with this mod #issueTrackerURL="https://change.me.to.your.issue.tracker.example.invalid/" #optional # A list of mods - how many allowed here is determined by the individual mod loader From 703d7851569ea35925f40000236bcdde225f6f76 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Wed, 20 Sep 2023 17:01:51 +0100 Subject: [PATCH 266/580] make gradlew executable --- gradlew | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 gradlew diff --git a/gradlew b/gradlew old mode 100644 new mode 100755 From 87fe93fa54947286828dfea5fefb5e83798d2714 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Wed, 20 Sep 2023 17:02:17 +0100 Subject: [PATCH 267/580] add settings.gradle --- settings.gradle | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 settings.gradle diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 00000000..3703f364 --- /dev/null +++ b/settings.gradle @@ -0,0 +1,6 @@ +pluginManagement { + repositories { + gradlePluginPortal() + maven { url = 'https://maven.minecraftforge.net/' } + } +} \ No newline at end of file From 13479b402af9c3ccf22fd803d43a2f406d5aaf83 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Wed, 20 Sep 2023 17:02:52 +0100 Subject: [PATCH 268/580] .gitignore --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index 12ae3a47..12f86447 100644 --- a/.gitignore +++ b/.gitignore @@ -16,7 +16,6 @@ out # gradle build .gradle -gradle # other eclipse From 06f10e078c530a5e56607bb947cb4aacab3592f8 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Wed, 20 Sep 2023 17:33:23 +0100 Subject: [PATCH 269/580] fix workflow issue --- src/main/resources/mcmod.info | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/mcmod.info b/src/main/resources/mcmod.info index 3c25a4cd..20d03144 100644 --- a/src/main/resources/mcmod.info +++ b/src/main/resources/mcmod.info @@ -2,7 +2,7 @@ { "modid": "advancedbackups", "name": "Advanced Backups", - "version": "${version}", + "version": "${modVersion}", "mcversion": "1.7.10", "description": "A highly advanced backup mod.", "url": "https://github.com/MommyHeather/AdvancedBackups", From 128c70f6da0a96df5e3e66dd689787f335c315dc Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Thu, 21 Sep 2023 00:18:00 +0100 Subject: [PATCH 270/580] fabric 1.19! --- README.md | 4 ++-- build.gradle | 2 +- gradle.properties | 10 +++++----- .../mommyheather/advancedbackups/AdvancedBackups.java | 4 ++-- src/main/resources/fabric.mod.json | 4 ++-- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index a1bde000..c6254984 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Fabric - 1.18 +# Fabric - 1.19 -This is the branch specifically for fabric 1.18. +This is the branch specifically for fabric 1.19. Any differences will be listed below. For full documentation, see the `core` branch. diff --git a/build.gradle b/build.gradle index d51c2539..922c32ce 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ plugins { - id 'fabric-loom' version '1.2-SNAPSHOT' + id 'fabric-loom' version '1.3-SNAPSHOT' id 'maven-publish' } diff --git a/gradle.properties b/gradle.properties index f0cad445..223c6f03 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,18 +4,18 @@ org.gradle.parallel=true # Fabric Properties # check these on https://fabricmc.net/develop -minecraft_version=1.18.2 -yarn_mappings=1.18.2+build.4 -loader_version=0.14.19 +minecraft_version=1.19.2 +yarn_mappings=1.19.2+build.28 +loader_version=0.14.22 # Mod Properties version=2.0 maven_group=co.uk.mommyheather.advancedbackups archives_base_name=advanced-backups modloaderName =fabric -minecraftVersion =1.18 +minecraftVersion =1.19 # Dependencies -fabric_version=0.76.0+1.18.2 +fabric_version=0.76.1+1.19.2 diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index e74a04bc..8a1200f2 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -1,7 +1,7 @@ package co.uk.mommyheather.advancedbackups; import net.fabricmc.api.ModInitializer; -import net.fabricmc.fabric.api.command.v1.CommandRegistrationCallback; +import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; import net.fabricmc.loader.impl.FabricLoaderImpl; @@ -66,7 +66,7 @@ public void onInitialize() { ABCore.setActivity(); }); - CommandRegistrationCallback.EVENT.register((dispatcher, isDedicated) -> { + CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> { AdvancedBackupsCommand.register(dispatcher); }); diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 408a7798..2f55f1f9 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -19,8 +19,8 @@ ] }, "depends": { - "fabricloader": ">=0.14.19", - "minecraft": "~1.18.2", + "fabricloader": ">=0.14.22", + "minecraft": "~1.19.2", "java": ">=17", "fabric-api": "*" } From 1991d124268d6929cd8194c652119e58bdb0d6b5 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Thu, 21 Sep 2023 19:21:03 +0100 Subject: [PATCH 271/580] Gradle stuff for neoforge 1.20 --- build.gradle | 165 ++++++++++++++--------- gradle.properties | 58 +++++++- gradle/wrapper/gradle-wrapper.jar | Bin 60756 -> 61574 bytes gradle/wrapper/gradle-wrapper.properties | 3 +- gradlew | 12 +- settings.gradle | 9 +- 6 files changed, 177 insertions(+), 70 deletions(-) diff --git a/build.gradle b/build.gradle index acd8118d..01a0f2a0 100644 --- a/build.gradle +++ b/build.gradle @@ -1,13 +1,16 @@ plugins { id 'eclipse' + id 'idea' id 'maven-publish' - id 'net.minecraftforge.gradle' version '5.1.+' + id 'net.neoforged.gradle' version '[6.0.18,6.2)' + id 'org.spongepowered.mixin' version '0.7.+' } +group = mod_group_id - -group = 'co.uk.mommyheather.advancedbackups' // http://maven.apache.org/guides/mini/guide-naming-conventions.html -archivesBaseName = 'AdvancedBackups-' + modloaderName + "-" + minecraftVersion +base { + archivesName = 'AdvancedBackups-' + modloaderName + "-" + minecraftVersion +} // Mojang ships Java 17 to end users in 1.18+, so your mod should target Java 17. java.toolchain.languageVersion = JavaLanguageVersion.of(17) @@ -20,22 +23,45 @@ minecraft { // parchment YYYY.MM.DD-MCVersion Open community-sourced parameter names and javadocs layered on top of official // // You must be aware of the Mojang license when using the 'official' or 'parchment' mappings. - // See more information here: https://github.com/MinecraftForge/MCPConfig/blob/master/Mojang.md + // See more information here: https://github.com/NeoForged/NeoForm/blob/main/Mojang.md // // Parchment is an unofficial project maintained by ParchmentMC, separate from MinecraftForge - // Additional setup is needed to use their mappings: https://github.com/ParchmentMC/Parchment/wiki/Getting-Started + // Additional setup is needed to use their mappings: https://parchmentmc.org/docs/getting-started // // Use non-default mappings at your own risk. They may not always work. // Simply re-run your setup task after changing the mappings to update your workspace. - mappings channel: 'official', version: '1.19.2' + mappings channel: mapping_channel, version: mapping_version + + // When true, this property will have all Eclipse/IntelliJ IDEA run configurations run the "prepareX" task for the given run configuration before launching the game. + // In most cases, it is not necessary to enable. + // enableEclipsePrepareRuns = true + // enableIdeaPrepareRuns = true + + // This property allows configuring Gradle's ProcessResources task(s) to run on IDE output locations before launching the game. + // It is REQUIRED to be set to true for this template to function. + // See https://docs.gradle.org/current/dsl/org.gradle.language.jvm.tasks.ProcessResources.html + copyIdeResources = true + + // When true, this property will add the folder name of all declared run configurations to generated IDE run configurations. + // The folder name can be set on a run configuration using the "folderName" property. + // By default, the folder name of a run configuration is the name of the Gradle project containing it. + // generateRunFolders = true + + // This property enables access transformers for use in development. + // They will be applied to the Minecraft artifact. + // The access transformer file can be anywhere in the project. + // However, it must be at "META-INF/accesstransformer.cfg" in the final mod jar to be loaded by Forge. + // This default location is a best practice to automatically put the file in the right place in the final jar. + // See https://docs.neoforged.net/docs/1.20.x/advanced/accesstransformers/ for more information. - // accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg') // Currently, this location cannot be changed from the default. + // accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg') // Default run configurations. // These can be tweaked, removed, or duplicated as needed. runs { - client { - workingDirectory project.file('run') + // applies to all the run configs below + configureEach { + workingDirectory project.file("run/${it.name}") // Recommended logging data for a userdev environment // The markers can be added/remove as needed separated by commas. @@ -49,48 +75,36 @@ minecraft { // Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels property 'forge.logging.console.level', 'debug' - // Comma-separated list of namespaces to load gametests from. Empty = all namespaces. - property 'forge.enabledGameTestNamespaces', 'advancedbackups' - mods { - advancedbackups { + "${mod_id}" { source sourceSets.main } } } - server { - workingDirectory project.file('run') - - property 'forge.logging.markers', 'REGISTRIES' - - property 'forge.logging.console.level', 'debug' - + client { // Comma-separated list of namespaces to load gametests from. Empty = all namespaces. - property 'forge.enabledGameTestNamespaces', 'advancedbackups' - - mods { - advancedbackups { - source sourceSets.main - } - } + property 'forge.enabledGameTestNamespaces', mod_id } - data { - workingDirectory project.file('run') + server { + property 'forge.enabledGameTestNamespaces', mod_id + args '--nogui' + } - property 'forge.logging.markers', 'REGISTRIES' + // This run config launches GameTestServer and runs all registered gametests, then exits. + // By default, the server will crash when no gametests are provided. + // The gametest system is also enabled by default for other run configs under the /test command. + gameTestServer { + property 'forge.enabledGameTestNamespaces', mod_id + } - property 'forge.logging.console.level', 'debug' + data { + // example of overriding the workingDirectory set in configureEach above, uncomment if you want to use it + // workingDirectory project.file('run-data') // Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources. - args '--mod', 'advancedbackups', '--all', '--output', file('src/generated/resources/'), '--existing', file('src/main/resources/') - - mods { - advancedbackups { - source sourceSets.main - } - } + args '--mod', mod_id, '--all', '--output', file('src/generated/resources/'), '--existing', file('src/main/resources/') } } } @@ -105,40 +119,63 @@ configurations { repositories { // Put repositories for dependencies here - // ForgeGradle automatically adds the Forge maven and Maven Central for you + // NeoGradle automatically adds the Forge maven and Maven Central for you - // If you have mod jar dependencies in ./libs, you can declare them as a repository like so: + // If you have mod jar dependencies in ./libs, you can declare them as a repository like so. + // See https://docs.gradle.org/current/userguide/declaring_repositories.html#sub:flat_dir_resolver // flatDir { // dir 'libs' // } } dependencies { - // Specify the version of Minecraft to use. If this is any group other than 'net.minecraft', it is assumed - // that the dep is a ForgeGradle 'patcher' dependency, and its patches will be applied. - // The userdev artifact is a special name and will get all sorts of transformations applied to it. - minecraft 'net.minecraftforge:forge:1.19.2-43.2.0' - //implementation files('dependencies/jansi-2.4.0.jar') - //extraLibs files('dependencies/jansi-2.4.0.jar') + // Specify the version of Minecraft to use. + // Any artifact can be supplied so long as it has a "userdev" classifier artifact and is a compatible patcher artifact. + // The "userdev" classifier will be requested and setup by NeoGradle. + // If the group id is "net.minecraft" and the artifact id is one of ["client", "server", "joined"], + // then special handling is done to allow a setup of a vanilla dependency without the use of an external repository. + minecraft "net.neoforged:forge:${minecraft_version}-${neo_version}" + + // Example mod dependency with JEI - using fg.deobf() ensures the dependency is remapped to your development mappings + // The JEI API is declared for compile time use, while the full JEI artifact is used at runtime + // compileOnly fg.deobf("mezz.jei:jei-${mc_version}-common-api:${jei_version}") + // compileOnly fg.deobf("mezz.jei:jei-${mc_version}-forge-api:${jei_version}") + // runtimeOnly fg.deobf("mezz.jei:jei-${mc_version}-forge:${jei_version}") + + // Example mod dependency using a mod jar from ./libs with a flat dir repository + // This maps to ./libs/coolmod-${mc_version}-${coolmod_version}.jar + // The group id is ignored when searching -- in this case, it is "blank" + // implementation fg.deobf("blank:coolmod-${mc_version}:${coolmod_version}") minecraftLibrary files ('advancedbackups-corelib.jar') extraLibs files ('advancedbackups-corelib.jar') - // Real mod deobf dependency examples - these get remapped to your current mappings - // compileOnly fg.deobf("mezz.jei:jei-${mc_version}:${jei_version}:api") // Adds JEI API as a compile dependency - // runtimeOnly fg.deobf("mezz.jei:jei-${mc_version}:${jei_version}") // Adds the full JEI mod as a runtime dependency - // implementation fg.deobf("com.tterrag.registrate:Registrate:MC${mc_version}-${registrate_version}") // Adds registrate as a dependency - - // Examples using mod jars from ./libs - // implementation fg.deobf("blank:coolmod-${mc_version}:${coolmod_version}") - - // For more info... + // For more info: // http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html // http://www.gradle.org/docs/current/userguide/dependency_management.html } +// This block of code expands all declared replace properties in the specified resource targets. +// A missing property will result in an error. Properties are expanded using ${} Groovy notation. +// When "copyIdeResources" is enabled, this will also run before the game launches in IDE environments. +// See https://docs.gradle.org/current/dsl/org.gradle.language.jvm.tasks.ProcessResources.html +tasks.withType(ProcessResources).configureEach { + var replaceProperties = [ + minecraft_version : minecraft_version, minecraft_version_range: minecraft_version_range, + neo_version : neo_version, neo_version_range: neo_version_range, + loader_version_range: loader_version_range, + mod_id : mod_id, mod_name: mod_name, mod_license: mod_license, mod_version: mod_version, + mod_authors : mod_authors, mod_description: mod_description, pack_format_number: pack_format_number, + ] + inputs.properties replaceProperties + + filesMatching(['META-INF/mods.toml', 'pack.mcmeta']) { + expand replaceProperties + [project: project] + } +} + // Example for how to get properties into the manifest for reading at runtime. -jar { +tasks.named('jar', Jar).configure { manifest { attributes([ "Main-Class" : "co.uk.mommyheather.advancedbackups.cli.AdvancedBackupsCLI", @@ -154,17 +191,19 @@ jar { from { configurations.extraLibs.collect { it.isDirectory() ? it : zipTree(it) } } + // This is the preferred method to reobfuscate your jar file + finalizedBy 'reobfJar' } -// Example configuration to allow publishing using the maven-publish plugin -// This is the preferred method to reobfuscate your jar file -jar.finalizedBy('reobfJar') -// However if you are in a multi-project build, dev time needs unobfed jar files, so you can delay the obfuscation until publishing by doing -// publish.dependsOn('reobfJar') +// However if you are in a multi-project build, dev time needs unobfed jar files, so you can delay the obfuscation until publishing by doing: +// tasks.named('publish').configure { +// dependsOn 'reobfJar' +// } +// Example configuration to allow publishing using the maven-publish plugin publishing { publications { - mavenJava(MavenPublication) { + register('mavenJava', MavenPublication) { artifact jar } } diff --git a/gradle.properties b/gradle.properties index 5b712214..cfffcd91 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,6 +4,62 @@ org.gradle.jvmargs=-Xmx3G org.gradle.daemon=false +## Environment Properties + +# The Minecraft version must agree with the Neo version to get a valid artifact +minecraft_version=1.20.1 +# The Minecraft version range can use any release version of Minecraft as bounds. +# Snapshots, pre-releases, and release candidates are not guaranteed to sort properly +# as they do not follow standard versioning conventions. +minecraft_version_range=[1.20,1.21) +# The Neo version must agree with the Minecraft version to get a valid artifact +neo_version=47.1.65 +# The Neo version range can use any version of Neo as bounds or match the loader version range +neo_version_range=[47.1,) +# The loader version range can only use the major version of Neo/FML as bounds +loader_version_range=[47,) +# The mapping channel to use for mappings. +# The default set of supported mapping channels are ["official", "snapshot", "snapshot_nodoc", "stable", "stable_nodoc"]. +# Additional mapping channels can be registered through the "channelProviders" extension in a Gradle plugin. +# +# | Channel | Version | | +# |-----------|----------------------|--------------------------------------------------------------------------------| +# | official | MCVersion | Official field/method names from Mojang mapping files | +# | parchment | YYYY.MM.DD-MCVersion | Open community-sourced parameter names and javadocs layered on top of official | +# +# You must be aware of the Mojang license when using the 'official' or 'parchment' mappings. +# See more information here: https://github.com/neoforged/NeoForm/blob/main/Mojang.md +# +# Parchment is an unofficial project maintained by ParchmentMC, separate from Minecraft Forge. +# Additional setup is needed to use their mappings, see https://parchmentmc.org/docs/getting-started +mapping_channel=official +# The mapping version to query from the mapping channel. +# This must match the format required by the mapping channel. +mapping_version=1.20.1 + + +## Mod Properties + +# The unique mod identifier for the mod. Must be lowercase in English locale. Must fit the regex [a-z][a-z0-9_]{1,63} +# Must match the String constant located in the main mod class annotated with @Mod. +mod_id=advancedbackups +# The human-readable display name for the mod. +mod_name=Advanced Backups +# The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default. +mod_license=BSD +# The mod version. See https://semver.org/ +mod_version=2.1.2 +# The group ID for the mod. It is only important when publishing as an artifact to a Maven repository. +# This should match the base package used for the mod sources. +# See https://maven.apache.org/guides/mini/guide-naming-conventions.html +mod_group_id=co.uk.mommyheather.advancedbackups +# The authors of the mod. This is a simple text string that is used for display purposes in the mod list. +mod_authors=Heather White +# The description of the mod. This is a simple multiline text string that is used for display purposes in the mod list. +mod_description=A highly advanced and configurable backup mod.\Github contains documentation. +# Pack version - this changes each minecraft release, in general. +pack_format_number=15 + modloaderName =forge -minecraftVersion =1.19 \ No newline at end of file +minecraftVersion =1.20 \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 249e5832f090a2944b7473328c07c9755baa3196..943f0cbfa754578e88a3dae77fce6e3dea56edbf 100644 GIT binary patch delta 36524 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%0DGK?7GHTj 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 VwlMN}`%er%aGR6olj~j${vQ;P=LY}) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index ae04661e..37aef8d3 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip +networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index a69d9cb6..65dcd68d 100755 --- a/gradlew +++ b/gradlew @@ -55,7 +55,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -80,10 +80,10 @@ do esac done -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit - -APP_NAME="Gradle" +# This is normally unused +# shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' @@ -143,12 +143,16 @@ fi if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac case $MAX_FD in #( '' | soft) :;; #( *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac diff --git a/settings.gradle b/settings.gradle index 3703f364..24584e97 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,6 +1,13 @@ pluginManagement { repositories { gradlePluginPortal() - maven { url = 'https://maven.minecraftforge.net/' } + maven { + name = 'NeoForged' + url = 'https://maven.neoforged.net/releases' + } } +} + +plugins { + id 'org.gradle.toolchains.foojay-resolver-convention' version '0.5.0' } \ No newline at end of file From 874dbd5d25294e7972f60502f2caae080a5a71d0 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Thu, 21 Sep 2023 19:21:21 +0100 Subject: [PATCH 272/580] add vscode gradle task to fix debugging --- build.gradle | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/build.gradle b/build.gradle index 01a0f2a0..cd978ce7 100644 --- a/build.gradle +++ b/build.gradle @@ -12,6 +12,11 @@ base { archivesName = 'AdvancedBackups-' + modloaderName + "-" + minecraftVersion } +task copyVSCodeResources (dependsOn: 'processResources', type: Copy) { + from 'build/resources' + into 'bin/' +} + // Mojang ships Java 17 to end users in 1.18+, so your mod should target Java 17. java.toolchain.languageVersion = JavaLanguageVersion.of(17) From 41c1f3f931c7c4fde4490b7bc866f580cd19f120 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Thu, 21 Sep 2023 19:21:58 +0100 Subject: [PATCH 273/580] More neoforge stuff - mods.toml and command fix --- .../AdvancedBackupsCommand.java | 20 ++++-- src/main/resources/META-INF/mods.toml | 64 +++++++++++-------- 2 files changed, 51 insertions(+), 33 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index 5e415c26..9b04a831 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -13,35 +13,45 @@ public static void register(CommandDispatcher stack) { return runner.hasPermission(3); }).then(Commands.literal("check").executes((runner) -> { CoreCommandSystem.checkBackups((response) -> { - runner.getSource().sendSuccess(Component.literal(response), true); + runner.getSource().sendSuccess(() -> { + return Component.literal(response) ; + }, true); }); return 1; })) .then(Commands.literal("start").executes((runner) -> { CoreCommandSystem.startBackup((response) -> { - runner.getSource().sendSuccess(Component.literal(response), true); + runner.getSource().sendSuccess(() -> { + return Component.literal(response) ; + }, true); }); return 1; })) .then(Commands.literal("force-backup").executes((runner) -> { CoreCommandSystem.forceBackup((response) -> { - runner.getSource().sendSuccess(Component.literal(response), true); + runner.getSource().sendSuccess(() -> { + return Component.literal(response) ; + }, true); }); return 1; })) .then(Commands.literal("reload").executes((runner) -> { CoreCommandSystem.reloadConfig((response) -> { - runner.getSource().sendSuccess(Component.literal(response), true); + runner.getSource().sendSuccess(() -> { + return Component.literal(response) ; + }, true); }); return 1; })) .then(Commands.literal("reset-chain").executes((runner) -> { CoreCommandSystem.resetChainLength((response) -> { - runner.getSource().sendSuccess(Component.literal(response), true); + runner.getSource().sendSuccess(() -> { + return Component.literal(response) ; + }, true); }); return 1; })) diff --git a/src/main/resources/META-INF/mods.toml b/src/main/resources/META-INF/mods.toml index e7b49321..c9e2c40c 100644 --- a/src/main/resources/META-INF/mods.toml +++ b/src/main/resources/META-INF/mods.toml @@ -5,58 +5,66 @@ # Find more information on toml format here: https://github.com/toml-lang/toml # The name of the mod loader type to load - for regular FML @Mod mods it should be javafml modLoader="javafml" #mandatory -# A version range to match for said mod loader - for regular FML @Mod it will be the forge version -loaderVersion="[40,)" #mandatory This is typically bumped every Minecraft version by Forge. See our download page for lists of versions. +# A version range to match for said mod loader - for regular FML @Mod it will be the the FML version. This is currently 47. +loaderVersion="${loader_version_range}" #mandatory # The license for you mod. This is mandatory metadata and allows for easier comprehension of your redistributive properties. # Review your options at https://choosealicense.com/. All rights reserved is the default copyright stance, and is thus the default here. -license="BSD" +license="${mod_license}" # A URL to refer people to when problems occur with this mod #issueTrackerURL="https://change.me.to.your.issue.tracker.example.invalid/" #optional # A list of mods - how many allowed here is determined by the individual mod loader [[mods]] #mandatory # The modid of the mod -modId="advancedbackups" #mandatory -# The version number of the mod - there's a few well known ${} variables useable here or just hardcode it -# ${file.jarVersion} will substitute the value of the Implementation-Version as read from the mod's JAR file metadata -# see the associated build.gradle script for how to populate this completely automatically during a build -version="${file.jarVersion}" #mandatory - # A display name for the mod -displayName="Advanced Backups" #mandatory -# A URL to query for updates for this mod. See the JSON update specification https://mcforge.readthedocs.io/en/latest/gettingstarted/autoupdate/ +modId="${mod_id}" #mandatory +# The version number of the mod +version="${mod_version}" #mandatory +# A display name for the mod +displayName="${mod_name}" #mandatory +# A URL to query for updates for this mod. See the JSON update specification https://docs.neoforged.net/docs/misc/updatechecker/ #updateJSONURL="https://change.me.example.invalid/updates.json" #optional # A URL for the "homepage" for this mod, displayed in the mod UI #displayURL="https://change.me.to.your.mods.homepage.example.invalid/" #optional # A file name (in the root of the mod JAR) containing a logo for display -#logoFile="advancedbackups.png" #optional +#logoFile="examplemod.png" #optional # A text field displayed in the mod UI -#credits="Thanks for this example mod goes to Java" #optional +#credits="" #optional # A text field displayed in the mod UI -#authors="Love, Cheese and small house plants" #optional -# The description text for the mod (multi line!) (#mandatory) -description=''' -An extremely advanced backup mod. - -Supports many backup types. +authors="${mod_authors}" #optional +# Display Test controls the display for your mod in the server connection screen +# MATCH_VERSION means that your mod will cause a red X if the versions on client and server differ. This is the default behaviour and should be what you choose if you have server and client elements to your mod. +# IGNORE_SERVER_VERSION means that your mod will not cause a red X if it's present on the server but not on the client. This is what you should use if you're a server only mod. +# IGNORE_ALL_VERSION means that your mod will not cause a red X if it's present on the client or the server. This is a special case and should only be used if your mod has no server component. +# NONE means that no display test is set on your mod. You need to do this yourself, see IExtensionPoint.DisplayTest for more information. You can define any scheme you wish with this value. +# IMPORTANT NOTE: this is NOT an instruction as to which environments (CLIENT or DEDICATED SERVER) your mod loads on. Your mod should load (and maybe do nothing!) whereever it finds itself. +#displayTest="MATCH_VERSION" # MATCH_VERSION is the default if nothing is specified (#optional) -Config file and github contain documentation. -''' +# The description text for the mod (multi line!) (#mandatory) +description='''${mod_description}''' # A dependency - use the . to indicate dependency for a specific modid. Dependencies are optional. -[[dependencies.advancedbackups]] #optional +[[dependencies.${mod_id}]] #optional # the modid of the dependency modId="forge" #mandatory # Does this dependency have to exist - if not, ordering below must be specified mandatory=true #mandatory # The version range of the dependency - versionRange="[40,)" #mandatory - # An ordering relationship for the dependency - BEFORE or AFTER required if the relationship is not mandatory + versionRange="${neo_version_range}" #mandatory + # An ordering relationship for the dependency - BEFORE or AFTER required if the dependency is not mandatory + # BEFORE - This mod is loaded BEFORE the dependency + # AFTER - This mod is loaded AFTER the dependency ordering="NONE" - # Side this dependency is applied on - BOTH, CLIENT or SERVER + # Side this dependency is applied on - BOTH, CLIENT, or SERVER side="BOTH" # Here's another dependency -[[dependencies.advancedbackups]] +[[dependencies.${mod_id}]] modId="minecraft" mandatory=true -# This version range declares a minimum of the current minecraft version up to but not including the next major version - versionRange="[1.19,1.20)" + # This version range declares a minimum of the current minecraft version up to but not including the next major version + versionRange="${minecraft_version_range}" ordering="NONE" side="BOTH" + +# Features are specific properties of the game environment, that you may want to declare you require. This example declares +# that your mod requires GL version 3.2 or higher. Other features will be added. They are side aware so declaring this won't +# stop your mod loading on the server for example. +#[features.${mod_id}] +#openGLVersion="[3.2,)" From 3d5908d784f472a03dd0302b1b45c7ce4eda84bb Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Thu, 21 Sep 2023 19:26:40 +0100 Subject: [PATCH 274/580] . --- .github/workflows/main.yml | 36 ------------------------------------ 1 file changed, 36 deletions(-) delete mode 100644 .github/workflows/main.yml diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml deleted file mode 100644 index 63e38af3..00000000 --- a/.github/workflows/main.yml +++ /dev/null @@ -1,36 +0,0 @@ -name: Merge Core -on: - push: - branches: - - core -jobs: - Merges: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - - name: Forge 1.18 - uses: peter-evans/create-pull-request@v5 - with: - commit-message: Merge Core Library - Forge 1.18 - title: Merge Core Library - body: Merge Core Library - branch: forge-1.18 - - - name: Fabric 1.18 - uses: peter-evans/create-pull-request@v5 - with: - commit-message: Merge Core Library - Fabric 1.18 - title: Merge Core Library - body: Merge Core Library - branch: fabric-1.18 - - - name: Forge 1.16 - uses: peter-evans/create-pull-request@v5 - with: - commit-message: Merge Core Library - Forge 1.16 - title: Merge Core Library - body: Merge Core Library - branch: forge-1.16 From 324acc31b305415f6e497b5e3d51b64501335351 Mon Sep 17 00:00:00 2001 From: Heather <66441550+MommyHeather@users.noreply.github.com> Date: Thu, 21 Sep 2023 21:07:48 +0100 Subject: [PATCH 275/580] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 11effd38..5e146fc9 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Forge - 1.19 +# Forge - 1.20 -This is the branch specifically for forge 1.19. -Any differences will be listed below. For full documentation, see the `core` branch. \ No newline at end of file +This is the branch specifically for forge 1.20. +Any differences will be listed below. For full documentation, see the `core` branch. From f2f4e6a9e11a24915dbc002e236565bd416ed948 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Fri, 22 Sep 2023 01:52:35 +0100 Subject: [PATCH 276/580] Fabric 1.20! Also works on 1.20.2. --- README.md | 4 ++-- gradle.properties | 11 ++++++----- .../advancedbackups/AdvancedBackupsCommand.java | 10 +++++----- src/main/resources/fabric.mod.json | 2 +- 4 files changed, 14 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index c6254984..09db287c 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Fabric - 1.19 +# Fabric - 1.20 -This is the branch specifically for fabric 1.19. +This is the branch specifically for fabric 1.20. Any differences will be listed below. For full documentation, see the `core` branch. diff --git a/gradle.properties b/gradle.properties index 223c6f03..d170e8aa 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,18 +4,19 @@ org.gradle.parallel=true # Fabric Properties # check these on https://fabricmc.net/develop -minecraft_version=1.19.2 -yarn_mappings=1.19.2+build.28 +minecraft_version=1.20 +yarn_mappings=1.20+build.1 loader_version=0.14.22 # Mod Properties version=2.0 +mod_version=2.0 maven_group=co.uk.mommyheather.advancedbackups -archives_base_name=advanced-backups +archives_base_name=advancedbackups modloaderName =fabric -minecraftVersion =1.19 +minecraftVersion =1.20 # Dependencies -fabric_version=0.76.1+1.19.2 +fabric_version=0.83.0+1.20 diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index 1b171a51..3132b698 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -13,35 +13,35 @@ public static void register(CommandDispatcher stack) { return runner.hasPermissionLevel(3); }).then(CommandManager.literal("check").executes((runner) -> { CoreCommandSystem.checkBackups((response) -> { - runner.getSource().sendFeedback(Text.of(response), true); + runner.getSource().sendFeedback(() -> Text.of(response), true); }); return 1; })) .then(CommandManager.literal("start").executes((runner) -> { CoreCommandSystem.startBackup((response) -> { - runner.getSource().sendFeedback(Text.of(response), true); + runner.getSource().sendFeedback(() -> Text.of(response), true); }); return 1; })) .then(CommandManager.literal("force-backup").executes((runner) -> { CoreCommandSystem.forceBackup((response) -> { - runner.getSource().sendFeedback(Text.of(response), true); + runner.getSource().sendFeedback(() -> Text.of(response), true); }); return 1; })) .then(CommandManager.literal("reload").executes((runner) -> { CoreCommandSystem.reloadConfig((response) -> { - runner.getSource().sendFeedback(Text.of(response), true); + runner.getSource().sendFeedback(() -> Text.of(response), true); }); return 1; })) .then(CommandManager.literal("reset-chain").executes((runner) -> { CoreCommandSystem.resetChainLength((response) -> { - runner.getSource().sendFeedback(Text.of(response), true); + runner.getSource().sendFeedback(() -> Text.of(response), true); }); return 1; })) diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 2f55f1f9..c5137f53 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -20,7 +20,7 @@ }, "depends": { "fabricloader": ">=0.14.22", - "minecraft": "~1.19.2", + "minecraft": "~1.20", "java": ">=17", "fabric-api": "*" } From 576c083666dda8402b2757ad933a7a9c157977f6 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Wed, 4 Oct 2023 16:31:52 +0100 Subject: [PATCH 277/580] Reflect new 2.2 command changes --- .../AdvancedBackupsCommand.java | 38 +++++++------------ 1 file changed, 14 insertions(+), 24 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index 705a3b4e..962b7e76 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -33,7 +33,7 @@ public int getRequiredPermissionLevel() public String getCommandUsage(ICommandSender icommandsender) { - return "/advancedbackups (check|start|force-backup|reload|reset-chain)"; + return "/advancedbackups (start|reload-config|reset-chain|snapshot)"; } @@ -43,45 +43,26 @@ public void processCommand(ICommandSender sender, String[] args) throws CommandE { throw new WrongUsageException(getCommandUsage(sender)); } - else if ("check".equals(args[0])) - { - Check.execute(sender); - } else if ("start".equals(args[0])) { Start.execute(sender); } - else if ("force-backup".equals(args[0])) - { - Force.execute(sender); - } - else if ("reload".equals(args[0])) + else if ("reload-config".equals(args[0])) { Reload.execute(sender); } else if ("reset-chain".equals(args[0])) { ResetChain.execute(sender); } + else if ("snapshot".equals(args[0])) { + Snapshot.execute(sender); + } else { throw new WrongUsageException(getCommandUsage(sender)); } } - public static class Check { - static public void execute(ICommandSender sender) { - CoreCommandSystem.checkBackups((response) -> { - sender.addChatMessage(new ChatComponentText(response)); - }); - } - } - public static class Force { - public static void execute(ICommandSender sender) { - CoreCommandSystem.forceBackup((response) -> { - sender.addChatMessage(new ChatComponentText(response)); - }); - } - } public static class Reload { public static void execute(ICommandSender sender) { CoreCommandSystem.reloadConfig((response) -> { @@ -106,5 +87,14 @@ public static void execute(ICommandSender sender) { } } + public static class Snapshot { + public static void execute(ICommandSender sender) { + CoreCommandSystem.snapshot((response) -> { + sender.addChatMessage(new ChatComponentText(response)); + }); + } + + } + } From f9dd104393941cb0dd271c0adcf576f1867113a5 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Thu, 5 Oct 2023 01:40:59 +0100 Subject: [PATCH 278/580] Support 2.2 command changes --- .../AdvancedBackupsCommand.java | 63 +++++++------------ 1 file changed, 21 insertions(+), 42 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index 5f8f92a1..37334a8d 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -2,7 +2,6 @@ import co.uk.mommyheather.advancedbackups.core.CoreCommandSystem; import net.minecraft.command.CommandException; -import net.minecraft.command.ICommand; import net.minecraft.command.ICommandSender; import net.minecraft.server.MinecraftServer; @@ -13,11 +12,10 @@ public class AdvancedBackupsCommand extends CommandTreeBase { public AdvancedBackupsCommand() { - addSubcommand(new Check()); addSubcommand(new Start()); - addSubcommand(new Force()); addSubcommand(new Reload()); addSubcommand(new ResetChain()); + addSubcommand(new Snapshot()); } @Override @@ -36,45 +34,7 @@ public int getRequiredPermissionLevel() @Override public String getUsage(ICommandSender icommandsender) { - return "/advancedbackups (check|start|force-backup|reload)"; - } - - public static class Check extends CommandTreeBase { - public Check(){} - @Override - public void execute(MinecraftServer server, ICommandSender sender, String[] args) throws CommandException { - CoreCommandSystem.checkBackups((response) -> { - sender.sendMessage(new TextComponentString(response)); - }); - } - @Override - public String getName() - { - return "check"; - } - @Override - public String getUsage(ICommandSender sender) { - return "commands.advancedbackups.check.usage"; - } - } - - public static class Force extends CommandTreeBase { - public Force(){} - @Override - public void execute(MinecraftServer server, ICommandSender sender, String[] args) throws CommandException { - CoreCommandSystem.forceBackup((response) -> { - sender.sendMessage(new TextComponentString(response)); - }); - } - @Override - public String getName() - { - return "force-backup"; - } - @Override - public String getUsage(ICommandSender sender) { - return "commands.advancedbackups.force.usage"; - } + return "/advancedbackups (check|start|reload-config|snapshot)"; } public static class Reload extends CommandTreeBase { @@ -133,4 +93,23 @@ public String getUsage(ICommandSender sender) { return "commands.advancedbackups.resetchain.usage"; } } + + public static class Snapshot extends CommandTreeBase { + public Snapshot(){} + @Override + public void execute(MinecraftServer server, ICommandSender sender, String[] args) throws CommandException { + CoreCommandSystem.snapshot((response) -> { + sender.sendMessage(new TextComponentString(response)); + }); + } + @Override + public String getName() + { + return "snapshot"; + } + @Override + public String getUsage(ICommandSender sender) { + return "commands.advancedbackups.snapshot.usage"; + } + } } From df5038e99c0c0e61cfc2f832eb72b208e485a8dc Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Thu, 5 Oct 2023 01:41:42 +0100 Subject: [PATCH 279/580] support 2.2 changes, actually this time --- .../mommyheather/advancedbackups/AdvancedBackupsCommand.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index 37334a8d..c674565a 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -48,11 +48,11 @@ public void execute(MinecraftServer server, ICommandSender sender, String[] args @Override public String getName() { - return "reload"; + return "reload-config"; } @Override public String getUsage(ICommandSender sender) { - return "commands.advancedbackups.reload.usage"; + return "commands.advancedbackups.reload-config.usage"; } } From f66bf967424657180f9cc98bf9ae4c32ea5664ad Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Thu, 5 Oct 2023 01:52:20 +0100 Subject: [PATCH 280/580] support 2.2 command changes --- .../AdvancedBackupsCommand.java | 21 +++++++------------ 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index 1e07383c..557d0504 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -11,36 +11,29 @@ public class AdvancedBackupsCommand { public static void register(CommandDispatcher stack) { stack.register(Commands.literal("advancedbackups").requires((runner) -> { return runner.hasPermission(3); - }).then(Commands.literal("check").executes((runner) -> { - CoreCommandSystem.checkBackups((response) -> { - runner.getSource().sendSuccess(new StringTextComponent(response), true); - }); - return 1; - })) - - .then(Commands.literal("start").executes((runner) -> { + }).then(Commands.literal("start").executes((runner) -> { CoreCommandSystem.startBackup((response) -> { runner.getSource().sendSuccess(new StringTextComponent(response), true); }); return 1; })) - .then(Commands.literal("force-backup").executes((runner) -> { - CoreCommandSystem.forceBackup((response) -> { + .then(Commands.literal("reload-config").executes((runner) -> { + CoreCommandSystem.reloadConfig((response) -> { runner.getSource().sendSuccess(new StringTextComponent(response), true); }); return 1; })) - .then(Commands.literal("reload").executes((runner) -> { - CoreCommandSystem.reloadConfig((response) -> { + .then(Commands.literal("reset-chain").executes((runner) -> { + CoreCommandSystem.resetChainLength((response) -> { runner.getSource().sendSuccess(new StringTextComponent(response), true); }); return 1; })) - .then(Commands.literal("reset-chain").executes((runner) -> { - CoreCommandSystem.resetChainLength((response) -> { + .then(Commands.literal("snapshot").executes((runner) -> { + CoreCommandSystem.snapshot((response) -> { runner.getSource().sendSuccess(new StringTextComponent(response), true); }); return 1; From 3c3d609f1aae81af69bc6720e0a5de0e9c8a80bc Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Thu, 5 Oct 2023 01:53:27 +0100 Subject: [PATCH 281/580] support 2.2 command changes --- .../AdvancedBackupsCommand.java | 23 +++++++------------ 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index 1b171a51..de198d12 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -11,36 +11,29 @@ public class AdvancedBackupsCommand { public static void register(CommandDispatcher stack) { stack.register(CommandManager.literal("advancedbackups").requires((runner) -> { return runner.hasPermissionLevel(3); - }).then(CommandManager.literal("check").executes((runner) -> { - CoreCommandSystem.checkBackups((response) -> { - runner.getSource().sendFeedback(Text.of(response), true); - }); - return 1; - })) - - .then(CommandManager.literal("start").executes((runner) -> { + }).then(CommandManager.literal("start").executes((runner) -> { CoreCommandSystem.startBackup((response) -> { runner.getSource().sendFeedback(Text.of(response), true); }); return 1; })) - .then(CommandManager.literal("force-backup").executes((runner) -> { - CoreCommandSystem.forceBackup((response) -> { + .then(CommandManager.literal("reload-config").executes((runner) -> { + CoreCommandSystem.reloadConfig((response) -> { runner.getSource().sendFeedback(Text.of(response), true); }); return 1; })) - - .then(CommandManager.literal("reload").executes((runner) -> { - CoreCommandSystem.reloadConfig((response) -> { + + .then(CommandManager.literal("reset-chain").executes((runner) -> { + CoreCommandSystem.resetChainLength((response) -> { runner.getSource().sendFeedback(Text.of(response), true); }); return 1; })) - .then(CommandManager.literal("reset-chain").executes((runner) -> { - CoreCommandSystem.resetChainLength((response) -> { + .then(CommandManager.literal("snapshot").executes((runner) -> { + CoreCommandSystem.snapshot((response) -> { runner.getSource().sendFeedback(Text.of(response), true); }); return 1; From 89e9096fb9d7c74bd88a98f1e9d856bf31fb0e2f Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Thu, 5 Oct 2023 02:07:46 +0100 Subject: [PATCH 282/580] rename command (which i forgot to do last commit) --- .../mommyheather/advancedbackups/AdvancedBackupsCommand.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index 962b7e76..1788e5f4 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -21,7 +21,7 @@ public AdvancedBackupsCommand() @Override public String getCommandName() { - return "advancedbackups"; + return "backup"; } @@ -33,7 +33,7 @@ public int getRequiredPermissionLevel() public String getCommandUsage(ICommandSender icommandsender) { - return "/advancedbackups (start|reload-config|reset-chain|snapshot)"; + return "/backup (start|reload-config|reset-chain|snapshot)"; } From 847f63d255d51a650cf6bbf3df9e36f03e3edd53 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Thu, 5 Oct 2023 10:41:12 +0100 Subject: [PATCH 283/580] Rename advancedbackups command as i forgot to earlier --- .../advancedbackups/AdvancedBackupsCommand.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index c674565a..7e32fc40 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -21,7 +21,7 @@ public AdvancedBackupsCommand() @Override public String getName() { - return "advancedbackups"; + return "backup"; } @@ -34,7 +34,7 @@ public int getRequiredPermissionLevel() @Override public String getUsage(ICommandSender icommandsender) { - return "/advancedbackups (check|start|reload-config|snapshot)"; + return "/backup (check|start|reload-config|snapshot)"; } public static class Reload extends CommandTreeBase { @@ -52,7 +52,7 @@ public String getName() } @Override public String getUsage(ICommandSender sender) { - return "commands.advancedbackups.reload-config.usage"; + return "commands.backup.reload-config.usage"; } } @@ -71,7 +71,7 @@ public String getName() } @Override public String getUsage(ICommandSender sender) { - return "commands.advancedbackups.start.usage"; + return "commands.backup.start.usage"; } } @@ -90,7 +90,7 @@ public String getName() } @Override public String getUsage(ICommandSender sender) { - return "commands.advancedbackups.resetchain.usage"; + return "commands.backup.resetchain.usage"; } } @@ -109,7 +109,7 @@ public String getName() } @Override public String getUsage(ICommandSender sender) { - return "commands.advancedbackups.snapshot.usage"; + return "commands.backup.snapshot.usage"; } } } From cfaf39336b460dd5821395d36afa04661f4aa0db Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Thu, 5 Oct 2023 10:55:26 +0100 Subject: [PATCH 284/580] rename advancedbackups command --- .../uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index 557d0504..a075fef2 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -9,7 +9,7 @@ public class AdvancedBackupsCommand { public static void register(CommandDispatcher stack) { - stack.register(Commands.literal("advancedbackups").requires((runner) -> { + stack.register(Commands.literal("backup").requires((runner) -> { return runner.hasPermission(3); }).then(Commands.literal("start").executes((runner) -> { CoreCommandSystem.startBackup((response) -> { From 84ddb503e3f30bdf1e51274778e19838e16c1536 Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Thu, 5 Oct 2023 14:49:16 +0100 Subject: [PATCH 285/580] rename advancedbackups command --- .../uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index de198d12..8504c006 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -9,7 +9,7 @@ public class AdvancedBackupsCommand { public static void register(CommandDispatcher stack) { - stack.register(CommandManager.literal("advancedbackups").requires((runner) -> { + stack.register(CommandManager.literal("backup").requires((runner) -> { return runner.hasPermissionLevel(3); }).then(CommandManager.literal("start").executes((runner) -> { CoreCommandSystem.startBackup((response) -> { From 68c6b2b241a9df5e33a59dc2f8c59265b5f9a97e Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Thu, 5 Oct 2023 16:01:36 +0100 Subject: [PATCH 286/580] support 2.2 command changes --- .../AdvancedBackupsCommand.java | 23 +++++++------------ 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index a0ce62b0..ad5ad197 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -9,38 +9,31 @@ public class AdvancedBackupsCommand { public static void register(CommandDispatcher stack) { - stack.register(Commands.literal("advancedbackups").requires((runner) -> { + stack.register(Commands.literal("backup").requires((runner) -> { return runner.hasPermission(3); - }).then(Commands.literal("check").executes((runner) -> { - CoreCommandSystem.checkBackups((response) -> { - runner.getSource().sendSuccess(new TextComponent(response), true); - }); - return 1; - })) - - .then(Commands.literal("start").executes((runner) -> { + }).then(Commands.literal("start").executes((runner) -> { CoreCommandSystem.startBackup((response) -> { runner.getSource().sendSuccess(new TextComponent(response), true); }); return 1; })) - .then(Commands.literal("force-backup").executes((runner) -> { - CoreCommandSystem.forceBackup((response) -> { + .then(Commands.literal("reload").executes((runner) -> { + CoreCommandSystem.reloadConfig((response) -> { runner.getSource().sendSuccess(new TextComponent(response), true); }); return 1; })) - .then(Commands.literal("reload").executes((runner) -> { - CoreCommandSystem.reloadConfig((response) -> { + .then(Commands.literal("reset-chain").executes((runner) -> { + CoreCommandSystem.resetChainLength((response) -> { runner.getSource().sendSuccess(new TextComponent(response), true); }); return 1; })) - .then(Commands.literal("reset-chain").executes((runner) -> { - CoreCommandSystem.resetChainLength((response) -> { + .then(Commands.literal("snapshot").executes((runner) -> { + CoreCommandSystem.snapshot((response) -> { runner.getSource().sendSuccess(new TextComponent(response), true); }); return 1; From 8140e5a5a17f09c2a40e47abe3df4480aa9e1eba Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Thu, 5 Oct 2023 16:11:10 +0100 Subject: [PATCH 287/580] support 2.2 command changes --- .../AdvancedBackupsCommand.java | 25 +++++++------------ 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index 1b171a51..4d866346 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -9,29 +9,15 @@ public class AdvancedBackupsCommand { public static void register(CommandDispatcher stack) { - stack.register(CommandManager.literal("advancedbackups").requires((runner) -> { + stack.register(CommandManager.literal("backup").requires((runner) -> { return runner.hasPermissionLevel(3); - }).then(CommandManager.literal("check").executes((runner) -> { - CoreCommandSystem.checkBackups((response) -> { - runner.getSource().sendFeedback(Text.of(response), true); - }); - return 1; - })) - - .then(CommandManager.literal("start").executes((runner) -> { + }).then(CommandManager.literal("start").executes((runner) -> { CoreCommandSystem.startBackup((response) -> { runner.getSource().sendFeedback(Text.of(response), true); }); return 1; })) - .then(CommandManager.literal("force-backup").executes((runner) -> { - CoreCommandSystem.forceBackup((response) -> { - runner.getSource().sendFeedback(Text.of(response), true); - }); - return 1; - })) - .then(CommandManager.literal("reload").executes((runner) -> { CoreCommandSystem.reloadConfig((response) -> { runner.getSource().sendFeedback(Text.of(response), true); @@ -45,6 +31,13 @@ public static void register(CommandDispatcher stack) { }); return 1; })) + + .then(CommandManager.literal("snapshot").executes((runner) -> { + CoreCommandSystem.snapshot((response) -> { + runner.getSource().sendFeedback(Text.of(response), true); + }); + return 1; + })) ); } From 3f9331f61091b7b23a9e55ee52c43a8d9a0954ca Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Thu, 5 Oct 2023 16:13:54 +0100 Subject: [PATCH 288/580] support 2.2 command changes --- .../AdvancedBackupsCommand.java | 23 +++++++------------ 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index 5e415c26..b83b67e4 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -9,38 +9,31 @@ public class AdvancedBackupsCommand { public static void register(CommandDispatcher stack) { - stack.register(Commands.literal("advancedbackups").requires((runner) -> { + stack.register(Commands.literal("backup").requires((runner) -> { return runner.hasPermission(3); - }).then(Commands.literal("check").executes((runner) -> { - CoreCommandSystem.checkBackups((response) -> { - runner.getSource().sendSuccess(Component.literal(response), true); - }); - return 1; - })) - - .then(Commands.literal("start").executes((runner) -> { + }).then(Commands.literal("start").executes((runner) -> { CoreCommandSystem.startBackup((response) -> { runner.getSource().sendSuccess(Component.literal(response), true); }); return 1; })) - .then(Commands.literal("force-backup").executes((runner) -> { - CoreCommandSystem.forceBackup((response) -> { + .then(Commands.literal("reload").executes((runner) -> { + CoreCommandSystem.reloadConfig((response) -> { runner.getSource().sendSuccess(Component.literal(response), true); }); return 1; })) - .then(Commands.literal("reload").executes((runner) -> { - CoreCommandSystem.reloadConfig((response) -> { + .then(Commands.literal("reset-chain").executes((runner) -> { + CoreCommandSystem.resetChainLength((response) -> { runner.getSource().sendSuccess(Component.literal(response), true); }); return 1; })) - .then(Commands.literal("reset-chain").executes((runner) -> { - CoreCommandSystem.resetChainLength((response) -> { + .then(Commands.literal("snapshot").executes((runner) -> { + CoreCommandSystem.snapshot((response) -> { runner.getSource().sendSuccess(Component.literal(response), true); }); return 1; From 828531a1e964dba42d5ed661c6f8494d87ce061a Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Thu, 5 Oct 2023 16:35:31 +0100 Subject: [PATCH 289/580] support 2.2 command changes --- .../AdvancedBackupsCommand.java | 25 +++++++------------ 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index 3132b698..462acc2c 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -9,29 +9,15 @@ public class AdvancedBackupsCommand { public static void register(CommandDispatcher stack) { - stack.register(CommandManager.literal("advancedbackups").requires((runner) -> { + stack.register(CommandManager.literal("backup").requires((runner) -> { return runner.hasPermissionLevel(3); - }).then(CommandManager.literal("check").executes((runner) -> { - CoreCommandSystem.checkBackups((response) -> { - runner.getSource().sendFeedback(() -> Text.of(response), true); - }); - return 1; - })) - - .then(CommandManager.literal("start").executes((runner) -> { + }).then(CommandManager.literal("start").executes((runner) -> { CoreCommandSystem.startBackup((response) -> { runner.getSource().sendFeedback(() -> Text.of(response), true); }); return 1; })) - .then(CommandManager.literal("force-backup").executes((runner) -> { - CoreCommandSystem.forceBackup((response) -> { - runner.getSource().sendFeedback(() -> Text.of(response), true); - }); - return 1; - })) - .then(CommandManager.literal("reload").executes((runner) -> { CoreCommandSystem.reloadConfig((response) -> { runner.getSource().sendFeedback(() -> Text.of(response), true); @@ -45,6 +31,13 @@ public static void register(CommandDispatcher stack) { }); return 1; })) + + .then(CommandManager.literal("snapshot").executes((runner) -> { + CoreCommandSystem.snapshot((response) -> { + runner.getSource().sendFeedback(() -> Text.of(response), true); + }); + return 1; + })) ); } From d9e3809bb88982fdf471f326f23eac75e23eaf5a Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Thu, 5 Oct 2023 17:30:48 +0100 Subject: [PATCH 290/580] support 2.2 command changes --- .../AdvancedBackupsCommand.java | 25 ++++++------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index 9b04a831..f048c3f2 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -9,18 +9,9 @@ public class AdvancedBackupsCommand { public static void register(CommandDispatcher stack) { - stack.register(Commands.literal("advancedbackups").requires((runner) -> { + stack.register(Commands.literal("backup").requires((runner) -> { return runner.hasPermission(3); - }).then(Commands.literal("check").executes((runner) -> { - CoreCommandSystem.checkBackups((response) -> { - runner.getSource().sendSuccess(() -> { - return Component.literal(response) ; - }, true); - }); - return 1; - })) - - .then(Commands.literal("start").executes((runner) -> { + }).then(Commands.literal("start").executes((runner) -> { CoreCommandSystem.startBackup((response) -> { runner.getSource().sendSuccess(() -> { return Component.literal(response) ; @@ -29,8 +20,8 @@ public static void register(CommandDispatcher stack) { return 1; })) - .then(Commands.literal("force-backup").executes((runner) -> { - CoreCommandSystem.forceBackup((response) -> { + .then(Commands.literal("reload").executes((runner) -> { + CoreCommandSystem.reloadConfig((response) -> { runner.getSource().sendSuccess(() -> { return Component.literal(response) ; }, true); @@ -38,8 +29,8 @@ public static void register(CommandDispatcher stack) { return 1; })) - .then(Commands.literal("reload").executes((runner) -> { - CoreCommandSystem.reloadConfig((response) -> { + .then(Commands.literal("reset-chain").executes((runner) -> { + CoreCommandSystem.resetChainLength((response) -> { runner.getSource().sendSuccess(() -> { return Component.literal(response) ; }, true); @@ -47,8 +38,8 @@ public static void register(CommandDispatcher stack) { return 1; })) - .then(Commands.literal("reset-chain").executes((runner) -> { - CoreCommandSystem.resetChainLength((response) -> { + .then(Commands.literal("snapshot").executes((runner) -> { + CoreCommandSystem.snapshot((response) -> { runner.getSource().sendSuccess(() -> { return Component.literal(response) ; }, true); From a521421035ab2276aad0357150a56e62322eaa6f Mon Sep 17 00:00:00 2001 From: RaVen <66441550+RaVenInTheDark@users.noreply.github.com> Date: Thu, 5 Oct 2023 19:12:41 +0100 Subject: [PATCH 291/580] Finally fix vscode runs! A simple prelaunchtask is all that's required to fix this with any 1.12 mod --- build.gradle | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/build.gradle b/build.gradle index ad85255e..ed67bad4 100644 --- a/build.gradle +++ b/build.gradle @@ -10,6 +10,18 @@ archivesBaseName = 'AdvancedBackups-' + modloaderName + "-" + minecraftVersion sourceCompatibility = targetCompatibility = compileJava.sourceCompatibility = compileJava.targetCompatibility = '1.8' // Need this here so eclipse task generates correctly. + + +task prepareVSCodeRun(type: Copy) { + from jar + into "run/mods" + rename (".*", "advancedbackups-vscode.jar") + //output of the jar task is copied into run/mods, with the name "advancedbackups-vscode.jar", overwriting any existing one +} + +prepareVSCodeRun.mustRunAfter jar + + minecraft { // The mappings can be changed at any time, and must be in the following format. // snapshot_YYYYMMDD Snapshot are built nightly. From 393408c4dfad704cff7ea8cd4ca03127d1f82b81 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Wed, 11 Oct 2023 22:49:49 +0100 Subject: [PATCH 292/580] don't flush save --- .../co/uk/mommyheather/advancedbackups/AdvancedBackups.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index e74a04bc..21c4f163 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -121,8 +121,8 @@ public static void enableSaving() { public static void saveOnce() { MinecraftServer server = AdvancedBackups.server; - server.saveAll(true, true, true); + server.saveAll(true, false, true); if (ConfigManager.silent.get()) return; warningLogger.accept(saveCompleteMessage); } -} \ No newline at end of file +} From 786f7994a9a852cf96446b12b7b301a2474741f4 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Wed, 11 Oct 2023 22:50:52 +0100 Subject: [PATCH 293/580] don't flush save --- .../co/uk/mommyheather/advancedbackups/AdvancedBackups.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 8a1200f2..2db3cbd2 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -121,8 +121,8 @@ public static void enableSaving() { public static void saveOnce() { MinecraftServer server = AdvancedBackups.server; - server.saveAll(true, true, true); + server.saveAll(true, false, true); if (ConfigManager.silent.get()) return; warningLogger.accept(saveCompleteMessage); } -} \ No newline at end of file +} From d428856b2e5dc8571e54fc43646b523d65a520c9 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Wed, 11 Oct 2023 22:51:09 +0100 Subject: [PATCH 294/580] don't flush save --- .../co/uk/mommyheather/advancedbackups/AdvancedBackups.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 8a1200f2..2db3cbd2 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -121,8 +121,8 @@ public static void enableSaving() { public static void saveOnce() { MinecraftServer server = AdvancedBackups.server; - server.saveAll(true, true, true); + server.saveAll(true, false, true); if (ConfigManager.silent.get()) return; warningLogger.accept(saveCompleteMessage); } -} \ No newline at end of file +} From a1874ac500f533e7cffcfb2f7f6d6e620eb7b30c Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Wed, 11 Oct 2023 22:52:57 +0100 Subject: [PATCH 295/580] don't flush save --- .../co/uk/mommyheather/advancedbackups/AdvancedBackups.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 6dfea64d..6059abfd 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -114,7 +114,7 @@ public static void enableSaving() { public static void saveOnce() { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - server.saveAllChunks(true, true, true); + server.saveAllChunks(true, false, true); if (ConfigManager.silent.get()) return; warningLogger.accept(saveCompleteMessage); } From 50fdb94f7f8e0d405c7f58e294e75ee7363e7deb Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Wed, 11 Oct 2023 22:53:13 +0100 Subject: [PATCH 296/580] dont flush save --- .../co/uk/mommyheather/advancedbackups/AdvancedBackups.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 644c1b57..0584a5c2 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -134,7 +134,7 @@ public static void enableSaving() { public static void saveOnce() { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - server.saveEverything(true, true, true); + server.saveEverything(true, false, true); if (ConfigManager.silent.get()) return; warningLogger.accept(saveCompleteMessage); } From 238240615946516147d10bc9a752b077d85984cf Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Wed, 11 Oct 2023 22:55:41 +0100 Subject: [PATCH 297/580] don't flush save --- .../co/uk/mommyheather/advancedbackups/AdvancedBackups.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 721d8e7f..bd2b2d5a 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -132,7 +132,7 @@ public static void enableSaving() { public static void saveOnce() { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - server.saveEverything(true, true, true); + server.saveEverything(true, false, true); if (ConfigManager.silent.get()) return; warningLogger.accept(saveCompleteMessage); } From 6d3093c1b99c984b946eb042c29352bc3cc91e4f Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Wed, 11 Oct 2023 22:57:07 +0100 Subject: [PATCH 298/580] don't flush save --- .../co/uk/mommyheather/advancedbackups/AdvancedBackups.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 721d8e7f..bd2b2d5a 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -132,7 +132,7 @@ public static void enableSaving() { public static void saveOnce() { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - server.saveEverything(true, true, true); + server.saveEverything(true, false, true); if (ConfigManager.silent.get()) return; warningLogger.accept(saveCompleteMessage); } From 2735aa24812effc68e8a1e7d4d96c4e97ad7ff35 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Thu, 12 Oct 2023 01:12:28 +0100 Subject: [PATCH 299/580] Update AdvancedBackupsCommand.java --- .../uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index b83b67e4..0ab938e5 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -18,7 +18,7 @@ public static void register(CommandDispatcher stack) { return 1; })) - .then(Commands.literal("reload").executes((runner) -> { + .then(Commands.literal("reload-config").executes((runner) -> { CoreCommandSystem.reloadConfig((response) -> { runner.getSource().sendSuccess(Component.literal(response), true); }); From 2612ce7143f4e4a754821718138d1ede9a8a445e Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Thu, 12 Oct 2023 01:12:47 +0100 Subject: [PATCH 300/580] Update AdvancedBackupsCommand.java --- .../uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index ad5ad197..142ec783 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -18,7 +18,7 @@ public static void register(CommandDispatcher stack) { return 1; })) - .then(Commands.literal("reload").executes((runner) -> { + .then(Commands.literal("reload-config").executes((runner) -> { CoreCommandSystem.reloadConfig((response) -> { runner.getSource().sendSuccess(new TextComponent(response), true); }); From 8b143e8c08b216cb0ed3810c425945dd7960ba77 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Thu, 12 Oct 2023 01:13:19 +0100 Subject: [PATCH 301/580] Update AdvancedBackupsCommand.java --- .../uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index f048c3f2..48919de9 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -20,7 +20,7 @@ public static void register(CommandDispatcher stack) { return 1; })) - .then(Commands.literal("reload").executes((runner) -> { + .then(Commands.literal("reload-config").executes((runner) -> { CoreCommandSystem.reloadConfig((response) -> { runner.getSource().sendSuccess(() -> { return Component.literal(response) ; From 54a2e925b80b710e917b829857526bac333a7691 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Thu, 12 Oct 2023 01:13:46 +0100 Subject: [PATCH 302/580] Update AdvancedBackupsCommand.java --- .../uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index 4d866346..8504c006 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -18,7 +18,7 @@ public static void register(CommandDispatcher stack) { return 1; })) - .then(CommandManager.literal("reload").executes((runner) -> { + .then(CommandManager.literal("reload-config").executes((runner) -> { CoreCommandSystem.reloadConfig((response) -> { runner.getSource().sendFeedback(Text.of(response), true); }); From 37b792c3e6f4fc21ba2d495ca375cefc68ca9ea1 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Thu, 12 Oct 2023 01:14:09 +0100 Subject: [PATCH 303/580] Update AdvancedBackupsCommand.java --- .../uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index 462acc2c..4ce0b5f5 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -18,7 +18,7 @@ public static void register(CommandDispatcher stack) { return 1; })) - .then(CommandManager.literal("reload").executes((runner) -> { + .then(CommandManager.literal("reload-config").executes((runner) -> { CoreCommandSystem.reloadConfig((response) -> { runner.getSource().sendFeedback(() -> Text.of(response), true); }); From 5ef7847b39360452f27b74642da213c72dedd18c Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sat, 14 Oct 2023 15:47:02 +0100 Subject: [PATCH 304/580] Support 2.5 core changes --- .../uk/mommyheather/advancedbackups/AdvancedBackups.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index bd2b2d5a..1d40105c 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -3,6 +3,7 @@ import com.mojang.logging.LogUtils; import co.uk.mommyheather.advancedbackups.core.ABCore; +import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; import net.minecraft.server.MinecraftServer; @@ -14,6 +15,8 @@ import net.minecraftforge.fml.common.Mod; import net.minecraftforge.server.ServerLifecycleHooks; import net.minecraftforge.event.RegisterCommandsEvent; +import net.minecraftforge.event.TickEvent; +import net.minecraftforge.event.TickEvent.Phase; import net.minecraftforge.event.entity.player.PlayerEvent; import net.minecraftforge.event.server.ServerStartedEvent; import net.minecraftforge.event.server.ServerStartingEvent; @@ -40,6 +43,12 @@ public AdvancedBackups() MinecraftForge.EVENT_BUS.register(this); } + @SubscribeEvent + public void onTickEnd(TickEvent.ServerTickEvent event) { + if (event.phase != Phase.END) return; + BackupTimer.check(); + } + @SubscribeEvent public void onServerStarting(ServerStartingEvent event) { From 1d66fe4917dec03d4c78a4edbe6f942876ba5cf0 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sat, 14 Oct 2023 16:11:18 +0100 Subject: [PATCH 305/580] .gitignore --- .gitignore | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..2c770e09 --- /dev/null +++ b/.gitignore @@ -0,0 +1,22 @@ +# eclipse +bin +*.launch +.settings +.metadata +.classpath +.project + +# idea +out +*.ipr +*.iws +*.iml +.idea + +# gradle +build +.gradle + +# other +eclipse +run From 60d7da3d6fc6c1bfd2b5157357195973fe6c8f2f Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sat, 14 Oct 2023 16:11:29 +0100 Subject: [PATCH 306/580] Support v2.5 core changes --- .../uk/mommyheather/advancedbackups/AdvancedBackups.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 2db3cbd2..d793ad7a 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -3,6 +3,7 @@ import net.fabricmc.api.ModInitializer; import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; import net.fabricmc.loader.impl.FabricLoaderImpl; import net.minecraft.server.MinecraftServer; @@ -16,6 +17,7 @@ import org.slf4j.LoggerFactory; import co.uk.mommyheather.advancedbackups.core.ABCore; +import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; @@ -71,6 +73,11 @@ public void onInitialize() { }); + ServerTickEvents.END_SERVER_TICK.register((server) -> { + BackupTimer.check(); + }); + + } From aae021b27a98c20c08030b67876e443420b6b637 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sat, 14 Oct 2023 16:58:13 +0100 Subject: [PATCH 307/580] support 2.5 core changes --- .../uk/mommyheather/advancedbackups/AdvancedBackups.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index bd2b2d5a..0176c51c 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -3,6 +3,7 @@ import com.mojang.logging.LogUtils; import co.uk.mommyheather.advancedbackups.core.ABCore; +import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; import net.minecraft.server.MinecraftServer; @@ -14,6 +15,7 @@ import net.minecraftforge.fml.common.Mod; import net.minecraftforge.server.ServerLifecycleHooks; import net.minecraftforge.event.RegisterCommandsEvent; +import net.minecraftforge.event.TickEvent; import net.minecraftforge.event.entity.player.PlayerEvent; import net.minecraftforge.event.server.ServerStartedEvent; import net.minecraftforge.event.server.ServerStartingEvent; @@ -85,6 +87,13 @@ public void registerCommands(RegisterCommandsEvent event){ } + @SubscribeEvent + public void onPostTick(TickEvent.ServerTickEvent event) { + if (!event.phase.equals(TickEvent.Phase.END)) return; + BackupTimer.check(); + } + + public static final String savesDisabledMessage = """ From 63d03edf13b6ce6bd4aa29a5cc9107686cc3134b Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sat, 14 Oct 2023 19:38:10 +0100 Subject: [PATCH 308/580] Support 2.5 core changes --- .../co/uk/mommyheather/advancedbackups/AdvancedBackups.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 2db3cbd2..bdb55ddb 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -3,6 +3,7 @@ import net.fabricmc.api.ModInitializer; import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; import net.fabricmc.loader.impl.FabricLoaderImpl; import net.minecraft.server.MinecraftServer; @@ -16,6 +17,7 @@ import org.slf4j.LoggerFactory; import co.uk.mommyheather.advancedbackups.core.ABCore; +import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; @@ -70,6 +72,10 @@ public void onInitialize() { AdvancedBackupsCommand.register(dispatcher); }); + ServerTickEvents.END_SERVER_TICK.register((server) -> { + BackupTimer.check(); + }); + } From e7d7f28d292e734fd49d7327878826ba543be095 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sat, 14 Oct 2023 19:58:08 +0100 Subject: [PATCH 309/580] support 2.5 core changes --- .../uk/mommyheather/advancedbackups/AdvancedBackups.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 0584a5c2..c4b18c8e 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -3,6 +3,7 @@ import com.mojang.logging.LogUtils; import co.uk.mommyheather.advancedbackups.core.ABCore; +import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; import net.minecraft.server.MinecraftServer; @@ -14,6 +15,7 @@ import net.minecraftforge.fml.common.Mod; import net.minecraftforge.server.ServerLifecycleHooks; import net.minecraftforge.event.RegisterCommandsEvent; +import net.minecraftforge.event.TickEvent; import net.minecraftforge.event.entity.player.PlayerEvent; import net.minecraftforge.event.server.ServerStartedEvent; import net.minecraftforge.event.server.ServerStartingEvent; @@ -86,6 +88,12 @@ public void registerCommands(RegisterCommandsEvent event){ AdvancedBackupsCommand.register(event.getDispatcher()); } + @SubscribeEvent + public void onTickEnd(TickEvent.ServerTickEvent event) { + if (!event.phase.equals(TickEvent.Phase.END)) return; + BackupTimer.check(); + } + public static final String savesDisabledMessage = """ From 2e69f847a7fda3cd28c99af0cfdd925327e29bd6 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sat, 14 Oct 2023 20:21:20 +0100 Subject: [PATCH 310/580] support 2.5 changes --- .../co/uk/mommyheather/advancedbackups/AdvancedBackups.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 21c4f163..d74e15a8 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -3,6 +3,7 @@ import net.fabricmc.api.ModInitializer; import net.fabricmc.fabric.api.command.v1.CommandRegistrationCallback; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; import net.fabricmc.loader.impl.FabricLoaderImpl; import net.minecraft.server.MinecraftServer; @@ -16,6 +17,7 @@ import org.slf4j.LoggerFactory; import co.uk.mommyheather.advancedbackups.core.ABCore; +import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; @@ -70,6 +72,10 @@ public void onInitialize() { AdvancedBackupsCommand.register(dispatcher); }); + + ServerTickEvents.END_SERVER_TICK.register((server) -> { + BackupTimer.check(); + }); } From 63bb61b3befcc5eb6d67eb2271b888bd4fa3f787 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sun, 15 Oct 2023 12:49:08 +0100 Subject: [PATCH 311/580] Support 2.5 changes --- .../uk/mommyheather/advancedbackups/AdvancedBackups.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 6059abfd..895ab9db 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -2,6 +2,7 @@ import co.uk.mommyheather.advancedbackups.core.ABCore; +import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; import net.minecraft.server.MinecraftServer; @@ -9,6 +10,7 @@ import net.minecraft.world.storage.FolderName; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.RegisterCommandsEvent; +import net.minecraftforge.event.TickEvent; import net.minecraftforge.event.entity.player.PlayerEvent.PlayerLoggedInEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.ModList; @@ -83,6 +85,12 @@ public void registerCommands(RegisterCommandsEvent event){ AdvancedBackupsCommand.register(event.getDispatcher()); } + @SubscribeEvent + public void onPostTick(TickEvent.ServerTickEvent event) { + if (!event.phase.equals(TickEvent.Phase.END)) return; + BackupTimer.check(); + } + public static final String savesDisabledMessage = "\n\n\n***************************************\nSAVING DISABLED - PREPARING FOR BACKUP!\n***************************************"; From 01adc2e027b3570a7a9de141ccd5ef0e409a2acf Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sun, 15 Oct 2023 13:40:09 +0100 Subject: [PATCH 312/580] support 2.5 core changes --- .../uk/mommyheather/advancedbackups/AdvancedBackups.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 44296074..df092db3 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -14,12 +14,14 @@ import net.minecraftforge.fml.common.event.FMLServerStoppingEvent; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.gameevent.PlayerEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; import net.minecraftforge.fml.relauncher.Side; import org.apache.logging.log4j.Logger; import co.uk.mommyheather.advancedbackups.core.ABCore; import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; +import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; import net.minecraftforge.common.MinecraftForge; @@ -111,6 +113,12 @@ public void onPlayerConnect(PlayerEvent.PlayerLoggedInEvent event) { ABCore.activity = true; } + @SubscribeEvent + public void onTickEnd(TickEvent.ServerTickEvent event) { + if (!event.phase.equals(TickEvent.Phase.END)) return; + BackupTimer.check(); + } + public static final String savesDisabledMessage = "\n\n\n***************************************\nSAVING DISABLED - PREPARING FOR BACKUP!\n***************************************"; From 2554ce3ddbf90ef2afb2210b2aa9cceb9950ca52 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sun, 15 Oct 2023 14:44:42 +0100 Subject: [PATCH 313/580] Support 2.5 core changes and fix an event handler issue --- .../advancedbackups/AdvancedBackups.java | 41 ++++++++++++++++--- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 4023b5fd..2a471a59 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -1,14 +1,19 @@ package co.uk.mommyheather.advancedbackups; +import net.minecraft.command.server.CommandSaveAll; import net.minecraft.init.Blocks; import net.minecraft.server.MinecraftServer; +import net.minecraft.util.IProgressUpdate; +import net.minecraft.world.MinecraftException; import net.minecraft.world.WorldServer; import org.apache.logging.log4j.Logger; import co.uk.mommyheather.advancedbackups.core.ABCore; import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; +import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; +import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.common.Loader; import cpw.mods.fml.common.Mod; import cpw.mods.fml.common.Mod.EventHandler; @@ -18,6 +23,7 @@ import cpw.mods.fml.common.event.FMLServerStoppingEvent; import cpw.mods.fml.common.eventhandler.SubscribeEvent; import cpw.mods.fml.common.gameevent.PlayerEvent; +import cpw.mods.fml.common.gameevent.TickEvent; import cpw.mods.fml.relauncher.Side; import net.minecraftforge.common.MinecraftForge; @@ -26,7 +32,6 @@ import java.lang.reflect.Method; import java.util.function.Consumer; - @Mod(modid = AdvancedBackups.MODID, name = AdvancedBackups.NAME, version = AdvancedBackups.VERSION, acceptableRemoteVersions = "*") public class AdvancedBackups { @@ -56,6 +61,7 @@ public AdvancedBackups() { // Register ourselves for server and other game events we are interested in MinecraftForge.EVENT_BUS.register(this); + FMLCommonHandler.instance().bus().register(this); } @EventHandler @@ -107,6 +113,12 @@ public void onServerStopping(FMLServerStoppingEvent event) { public void onPlayerConnected(PlayerEvent.PlayerLoggedInEvent event) { ABCore.activity = true; } + + @SubscribeEvent + public void onTickEnd(TickEvent.ServerTickEvent event) { + if (!event.phase.equals(TickEvent.Phase.END)) return; + BackupTimer.check(); + } public static final String savesDisabledMessage = "\n\n\n***************************************\nSAVING DISABLED - PREPARING FOR BACKUP!\n***************************************"; @@ -140,12 +152,31 @@ public static void enableSaving() { public static void saveOnce() { try { MinecraftServer server = AdvancedBackups.server; - Class[] classes = {Boolean.class}; - Method saveMethod = MinecraftServer.class.getMethod("saveAllWorlds", classes); - saveMethod.invoke(server, false); + if (server.getConfigurationManager() != null) + { + server.getConfigurationManager().saveAllPlayerData(); + } + + int i; + WorldServer worldserver; + boolean flag; + + for (i = 0; i < server.worldServers.length; ++i) + { + if (server.worldServers[i] != null) + { + worldserver = server.worldServers[i]; + flag = worldserver.levelSaving; + worldserver.levelSaving = false; + worldserver.saveAllChunks(true, (IProgressUpdate)null); + worldserver.levelSaving = flag; + } + } + + if (ConfigManager.silent.get()) return; warningLogger.accept(saveCompleteMessage); - } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException e) { + } catch (MinecraftException e) { // TODO Scream at user errorLogger.accept("FAILED TO SAVE WORLD!"); e.printStackTrace(); From 7b03fb5571ad54156891cbc294293fc8fef8ee76 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 17 Oct 2023 11:55:19 +0100 Subject: [PATCH 314/580] fix error that leaves saving disabled... FUCK ME --- .../co/uk/mommyheather/advancedbackups/AdvancedBackups.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 1d40105c..746c12db 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -131,7 +131,7 @@ public static void disableSaving() { public static void enableSaving() { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); for (ServerLevel level : server.getAllLevels()) { - if (level != null && !level.noSave) { + if (level != null && level.noSave) { level.noSave = false; } } From a608165cde7cf3dcd9e52c191d4a201e21647ef8 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 17 Oct 2023 12:12:31 +0100 Subject: [PATCH 315/580] fix the issue where saving breaks --- .../co/uk/mommyheather/advancedbackups/AdvancedBackups.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 2a471a59..2003fa46 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -126,7 +126,9 @@ public void onTickEnd(TickEvent.ServerTickEvent event) { public static final String saveCompleteMessage = "\n\n\n*************************************\nSAVE COMPLETE - PREPARING FOR BACKUP!\n*************************************"; - + //fun fact : this boolean is named wrong in MCP mappings! + //reference : net.minecraft.command.server.CommandSaveOff and CommandSaveOn + //notice how off sets the boolean to true, and on sets it to false! public static void disableSaving() { MinecraftServer server = AdvancedBackups.server; for (WorldServer level : server.worldServers) { @@ -141,7 +143,7 @@ public static void disableSaving() { public static void enableSaving() { MinecraftServer server = AdvancedBackups.server; for (WorldServer level : server.worldServers) { - if (level != null && !level.levelSaving) { + if (level != null && level.levelSaving) { level.levelSaving = false; } } From 6f150880934fdcc5c92d899e6f53e636488b0465 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 17 Oct 2023 12:46:51 +0100 Subject: [PATCH 316/580] fix issue with world saving not being enabled post backup --- .../co/uk/mommyheather/advancedbackups/AdvancedBackups.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index df092db3..0b391b8c 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -138,7 +138,7 @@ public static void disableSaving() { public static void enableSaving() { for (WorldServer level : server.worlds) { - if (level != null && !level.disableLevelSaving) { + if (level != null && level.disableLevelSaving) { level.disableLevelSaving = false; } } From 20517e9e3e475ac93261e61394e16cea40fd0b1c Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 17 Oct 2023 12:48:45 +0100 Subject: [PATCH 317/580] fix the infamous save bug --- .../co/uk/mommyheather/advancedbackups/AdvancedBackups.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 895ab9db..6d5dae91 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -112,7 +112,7 @@ public static void disableSaving() { public static void enableSaving() { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); for (ServerWorld level : server.getAllLevels()) { - if (level != null && !level.noSave) { + if (level != null && level.noSave) { level.noSave = false; } } From dea76a222d60aea42ba84ebccb06f1ab367042b9 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 17 Oct 2023 12:49:42 +0100 Subject: [PATCH 318/580] fix the save bug --- .../co/uk/mommyheather/advancedbackups/AdvancedBackups.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index d74e15a8..c838b4e4 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -117,7 +117,7 @@ public static void disableSaving() { public static void enableSaving() { MinecraftServer server = AdvancedBackups.server; for (ServerWorld level : server.getWorlds()) { - if (level != null && !level.savingDisabled) { + if (level != null && level.savingDisabled) { level.savingDisabled = false; } } From 7734fe045631006f90689190ca581522cb22b196 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 17 Oct 2023 12:50:51 +0100 Subject: [PATCH 319/580] fix the savebug --- .../co/uk/mommyheather/advancedbackups/AdvancedBackups.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index c4b18c8e..794eb7d1 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -132,7 +132,7 @@ public static void disableSaving() { public static void enableSaving() { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); for (ServerLevel level : server.getAllLevels()) { - if (level != null && !level.noSave) { + if (level != null && level.noSave) { level.noSave = false; } } From c95ddb6ee2cee554c0774d8b8177cbcd2c4b9515 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 17 Oct 2023 12:51:40 +0100 Subject: [PATCH 320/580] fix the savebug --- .../co/uk/mommyheather/advancedbackups/AdvancedBackups.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index bdb55ddb..6a4084c3 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -117,7 +117,7 @@ public static void disableSaving() { public static void enableSaving() { MinecraftServer server = AdvancedBackups.server; for (ServerWorld level : server.getWorlds()) { - if (level != null && !level.savingDisabled) { + if (level != null && level.savingDisabled) { level.savingDisabled = false; } } From 9c587fbc5327370ac7bff83274500045f6d1f12f Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 17 Oct 2023 12:52:55 +0100 Subject: [PATCH 321/580] fix the savebug --- .../co/uk/mommyheather/advancedbackups/AdvancedBackups.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index d793ad7a..dbc4cf77 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -118,7 +118,7 @@ public static void disableSaving() { public static void enableSaving() { MinecraftServer server = AdvancedBackups.server; for (ServerWorld level : server.getWorlds()) { - if (level != null && !level.savingDisabled) { + if (level != null && level.savingDisabled) { level.savingDisabled = false; } } From 0643c0c169d306ebcf616e026c53e4cb8502d5e4 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 17 Oct 2023 12:54:22 +0100 Subject: [PATCH 322/580] fix the savebug --- .../co/uk/mommyheather/advancedbackups/AdvancedBackups.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 0176c51c..c2130f61 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -131,7 +131,7 @@ public static void disableSaving() { public static void enableSaving() { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); for (ServerLevel level : server.getAllLevels()) { - if (level != null && !level.noSave) { + if (level != null && level.noSave) { level.noSave = false; } } From 44f48fe3c4ab3751bf99a6290d5f8c9e1179ab21 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sat, 21 Oct 2023 00:54:29 +0100 Subject: [PATCH 323/580] support 3.1 flush config --- .../co/uk/mommyheather/advancedbackups/AdvancedBackups.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 2003fa46..e316d9f4 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -151,7 +151,7 @@ public static void enableSaving() { warningLogger.accept(savesEnabledMessage); } - public static void saveOnce() { + public static void saveOnce(boolean unused) { //flush doesn't seem to be an option in 1.7.10 try { MinecraftServer server = AdvancedBackups.server; if (server.getConfigurationManager() != null) From 5e2cbdd2ef076b48aa96d576bc5e5fc3a8730e87 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sat, 21 Oct 2023 00:58:04 +0100 Subject: [PATCH 324/580] support 3.1 --- .../co/uk/mommyheather/advancedbackups/AdvancedBackups.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 0b391b8c..7a4b7c7e 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -146,7 +146,7 @@ public static void enableSaving() { warningLogger.accept(savesEnabledMessage); } - public static void saveOnce() { + public static void saveOnce(boolean unused) { //no flush bool in 1.12 either server.saveAllWorlds(false); if (ConfigManager.silent.get()) return; warningLogger.accept(saveCompleteMessage); From b9d744a24299f1d163d5f6f34a7d66f7d6ba62fc Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sat, 21 Oct 2023 01:14:26 +0100 Subject: [PATCH 325/580] Support 3.1 config changes --- .../co/uk/mommyheather/advancedbackups/AdvancedBackups.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 6d5dae91..7ec40cf6 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -120,9 +120,9 @@ public static void enableSaving() { warningLogger.accept(savesEnabledMessage); } - public static void saveOnce() { + public static void saveOnce(boolean flush) { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - server.saveAllChunks(true, false, true); + server.saveAllChunks(true, flush, true); if (ConfigManager.silent.get()) return; warningLogger.accept(saveCompleteMessage); } From f773a02596c89ff101518ffe5a32f8f697df8a82 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sat, 21 Oct 2023 01:17:22 +0100 Subject: [PATCH 326/580] Support 3.1 config changes --- .../co/uk/mommyheather/advancedbackups/AdvancedBackups.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index c838b4e4..366f8e8b 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -125,9 +125,9 @@ public static void enableSaving() { warningLogger.accept(savesEnabledMessage); } - public static void saveOnce() { + public static void saveOnce(boolean flush) { MinecraftServer server = AdvancedBackups.server; - server.saveAll(true, false, true); + server.saveAll(true, flush, true); if (ConfigManager.silent.get()) return; warningLogger.accept(saveCompleteMessage); } From 086136c041cd030d20302200083d8cdaa601c33f Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sat, 21 Oct 2023 01:25:27 +0100 Subject: [PATCH 327/580] Support 3.1 config changes --- .../co/uk/mommyheather/advancedbackups/AdvancedBackups.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 794eb7d1..a499004f 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -140,9 +140,9 @@ public static void enableSaving() { warningLogger.accept(savesEnabledMessage); } - public static void saveOnce() { + public static void saveOnce(boolean flush) { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - server.saveEverything(true, false, true); + server.saveEverything(true, flush, true); if (ConfigManager.silent.get()) return; warningLogger.accept(saveCompleteMessage); } From b8cd7c622faceee8be02464f73f152e068837a76 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sat, 21 Oct 2023 01:28:10 +0100 Subject: [PATCH 328/580] Support 3.1 config changes --- .../co/uk/mommyheather/advancedbackups/AdvancedBackups.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 6a4084c3..42fe632a 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -125,9 +125,9 @@ public static void enableSaving() { warningLogger.accept(savesEnabledMessage); } - public static void saveOnce() { + public static void saveOnce(boolean flush) { MinecraftServer server = AdvancedBackups.server; - server.saveAll(true, false, true); + server.saveAll(true, flush, true); if (ConfigManager.silent.get()) return; warningLogger.accept(saveCompleteMessage); } From 097335127a5c850c093fd18b230b501eeb497790 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sat, 21 Oct 2023 01:30:58 +0100 Subject: [PATCH 329/580] Support 3.1 config changes --- .../co/uk/mommyheather/advancedbackups/AdvancedBackups.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 746c12db..05933b12 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -139,9 +139,9 @@ public static void enableSaving() { warningLogger.accept(savesEnabledMessage); } - public static void saveOnce() { + public static void saveOnce(boolean flush) { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - server.saveEverything(true, false, true); + server.saveEverything(true, flush, true); if (ConfigManager.silent.get()) return; warningLogger.accept(saveCompleteMessage); } From 9622443dcfa6361622d203313e92f32e1fb39640 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sat, 21 Oct 2023 01:34:19 +0100 Subject: [PATCH 330/580] support 3.1 config changes --- .../co/uk/mommyheather/advancedbackups/AdvancedBackups.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index dbc4cf77..5809f5c2 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -126,9 +126,9 @@ public static void enableSaving() { warningLogger.accept(savesEnabledMessage); } - public static void saveOnce() { + public static void saveOnce(boolean flush) { MinecraftServer server = AdvancedBackups.server; - server.saveAll(true, false, true); + server.saveAll(true, flush, true); if (ConfigManager.silent.get()) return; warningLogger.accept(saveCompleteMessage); } From e2acb509a4b78d2a74ee2054c7d6881b941e288a Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sat, 21 Oct 2023 01:38:07 +0100 Subject: [PATCH 331/580] Support 3.1 config changes --- .../co/uk/mommyheather/advancedbackups/AdvancedBackups.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index c2130f61..f7a412b6 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -139,9 +139,9 @@ public static void enableSaving() { warningLogger.accept(savesEnabledMessage); } - public static void saveOnce() { + public static void saveOnce(boolean flush) { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - server.saveEverything(true, false, true); + server.saveEverything(true, flush, true); if (ConfigManager.silent.get()) return; warningLogger.accept(saveCompleteMessage); } From e69c0371efbebce1de29a295808742bfdb319a5b Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sat, 21 Oct 2023 01:42:13 +0100 Subject: [PATCH 332/580] Update README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 5e41c346..6081def4 100644 --- a/README.md +++ b/README.md @@ -2,3 +2,6 @@ This is the branch specifically for forge 1.7.10. Any differences will be listed below. For full documentation, see the `core` branch. + + +- Flush config value is ignored, but this is meaningless for most users as in most cases it should be kept at the default `false` From f778a95d719fda3bbe17b41ccae54cb18631db4c Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sat, 21 Oct 2023 01:42:23 +0100 Subject: [PATCH 333/580] Update README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 911a7b09..59c5927e 100644 --- a/README.md +++ b/README.md @@ -2,3 +2,6 @@ This is the branch specifically for forge 1.12. Any differences will be listed below. For full documentation, see the `core` branch. + + +- Flush config value is ignored, but this is meaningless for most users as in most cases it should be kept at the default `false` From 8662bc63443c4cb35b8e33611694ca5e035c7df0 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sun, 22 Oct 2023 01:05:34 +0100 Subject: [PATCH 334/580] I need a fucking language file! lol --- src/main/resources/assets/advancedbackups/lang/en_US.lang | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 src/main/resources/assets/advancedbackups/lang/en_US.lang diff --git a/src/main/resources/assets/advancedbackups/lang/en_US.lang b/src/main/resources/assets/advancedbackups/lang/en_US.lang new file mode 100644 index 00000000..eeca5f50 --- /dev/null +++ b/src/main/resources/assets/advancedbackups/lang/en_US.lang @@ -0,0 +1,4 @@ +advancedbackups.backup_starting=Backup starting! +advancedbackups.progress=Backup in progress : %s%% +advancedbackups.backup_failed=Backup failed : check log for more info. +advancedbackups.backup_finished=Backup complete! \ No newline at end of file From a4fd9b333ab1cef8a85fa725173a4ddaabc5c48f Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sun, 22 Oct 2023 01:10:21 +0100 Subject: [PATCH 335/580] another one-commit that shouldn't exist, but oh well. --- .../advancedbackups/AdvancedBackups.java | 7 ++ .../client/ABClientContactor.java | 75 +++++++++++++++++ .../client/ABClientRenderer.java | 71 ++++++++++++++++ .../network/NetworkHandler.java | 17 ++++ .../network/PacketBackupStatus.java | 80 +++++++++++++++++++ 5 files changed, 250 insertions(+) create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/client/ABClientContactor.java create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/client/ABClientRenderer.java create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index e316d9f4..7c52f2cc 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -9,10 +9,13 @@ import org.apache.logging.log4j.Logger; +import co.uk.mommyheather.advancedbackups.client.ABClientContactor; +import co.uk.mommyheather.advancedbackups.client.ABClientRenderer; import co.uk.mommyheather.advancedbackups.core.ABCore; import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.common.Loader; import cpw.mods.fml.common.Mod; @@ -61,7 +64,9 @@ public AdvancedBackups() { // Register ourselves for server and other game events we are interested in MinecraftForge.EVENT_BUS.register(this); + MinecraftForge.EVENT_BUS.register(new ABClientRenderer()); FMLCommonHandler.instance().bus().register(this); + NetworkHandler.init(); } @EventHandler @@ -89,6 +94,8 @@ public void onServerStarting(FMLServerStartingEvent event) ABCore.warningLogger = warningLogger; ABCore.errorLogger = errorLogger; + ABCore.clientContactor = new ABClientContactor(); + event.registerServerCommand(new AdvancedBackupsCommand()); ABCore.modJar = Loader.instance().getIndexedModList().get("advancedbackups").getSource(); diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ABClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ABClientContactor.java new file mode 100644 index 00000000..94b2e12f --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ABClientContactor.java @@ -0,0 +1,75 @@ +package co.uk.mommyheather.advancedbackups.client; + +import java.util.HashMap; + +import com.mojang.authlib.GameProfile; + +import co.uk.mommyheather.advancedbackups.AdvancedBackups; +import co.uk.mommyheather.advancedbackups.AdvancedBackupsCommand; +import co.uk.mommyheather.advancedbackups.interfaces.IClientContactor; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; +import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.server.management.ServerConfigurationManager; +import net.minecraft.world.WorldServer; + +@SuppressWarnings("unchecked") +public class ABClientContactor implements IClientContactor { + + @Override + public void backupComplete() { + ServerConfigurationManager configurationManager = AdvancedBackups.server.getConfigurationManager(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, 0, 0); + configurationManager.playerEntityList.forEach((player) -> { + if (player instanceof EntityPlayerMP) { + EntityPlayerMP playerMP = (EntityPlayerMP) player; + if (playerMP.canCommandSenderUseCommand(3, "advancedbackups")) { //if they can run the command, they should receive info on active backups + NetworkHandler.HANDLER.sendTo(packet, playerMP); + } + } + }); + } + + @Override + public void backupFailed() { + ServerConfigurationManager configurationManager = AdvancedBackups.server.getConfigurationManager(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, 0, 0); + configurationManager.playerEntityList.forEach((player) -> { + if (player instanceof EntityPlayerMP) { + EntityPlayerMP playerMP = (EntityPlayerMP) player; + if (playerMP.canCommandSenderUseCommand(3, "advancedbackups")) { //if they can run the command, they should receive info on active backups + NetworkHandler.HANDLER.sendTo(packet, playerMP); + } + } + }); + } + + @Override + public void backupProgress(int progress, int max) { + ServerConfigurationManager configurationManager = AdvancedBackups.server.getConfigurationManager(); + PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, progress, max); + configurationManager.playerEntityList.forEach((player) -> { + if (player instanceof EntityPlayerMP) { + EntityPlayerMP playerMP = (EntityPlayerMP) player; + if (playerMP.canCommandSenderUseCommand(3, "advancedbackups")) { //if they can run the command, they should receive info on active backups + NetworkHandler.HANDLER.sendTo(packet, playerMP); + } + } + }); + } + + @Override + public void backupStarting() { + ServerConfigurationManager configurationManager = AdvancedBackups.server.getConfigurationManager(); + PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, 0, 0); + configurationManager.playerEntityList.forEach((player) -> { + if (player instanceof EntityPlayerMP) { + EntityPlayerMP playerMP = (EntityPlayerMP) player; + if (playerMP.canCommandSenderUseCommand(3, "advancedbackups")) { //if they can run the command, they should receive info on active backups + NetworkHandler.HANDLER.sendTo(packet, playerMP); + } + } + }); + } + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ABClientRenderer.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ABClientRenderer.java new file mode 100644 index 00000000..5615ebb0 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ABClientRenderer.java @@ -0,0 +1,71 @@ +package co.uk.mommyheather.advancedbackups.client; + +import com.mojang.realmsclient.gui.ChatFormatting; + +import cpw.mods.fml.common.Mod.EventHandler; +import cpw.mods.fml.common.eventhandler.SubscribeEvent; +import net.minecraft.client.Minecraft; +import net.minecraft.client.resources.I18n; +import net.minecraft.init.Items; +import net.minecraft.item.Item; +import net.minecraft.stats.Achievement; +import net.minecraftforge.client.event.RenderGameOverlayEvent; + +public class ABClientRenderer { + + + public static boolean starting; + public static boolean started; + public static boolean failed; + public static boolean finished; + + public static int progress; + public static int max; + + + private static long time; + private static boolean timeSet = false; + + + @SubscribeEvent + public void onRenderEvent(RenderGameOverlayEvent.Text event) { + if (starting) { + event.left.add(ChatFormatting.GREEN + I18n.format("advancedbackups.backup_starting")); + } + else if (started) { + float percent = (float) progress / (float) max; + event.left.add(ChatFormatting.GREEN + I18n.format("advancedbackups.progress", round(percent * 100))); + } + else if (failed) { + event.left.add(ChatFormatting.RED + I18n.format("advancedbackups.backup_failed")); + if (!timeSet) { + time = System.currentTimeMillis(); + timeSet = true; + } + } + else if (finished) { + event.left.add(ChatFormatting.GREEN + I18n.format("advancedbackups.backup_finished")); + if (!timeSet) { + time = System.currentTimeMillis(); + timeSet = true; + } + } + + + if (timeSet && System.currentTimeMillis() >= time + 5000) { + starting = false; + started = false; + failed = false; + finished = false; + progress = 0; + max = 0; + timeSet = false; + } + } + + + private static String round (float value) { + return String.format("%.1f", value); + } + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java new file mode 100644 index 00000000..3c2a8135 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java @@ -0,0 +1,17 @@ +package co.uk.mommyheather.advancedbackups.network; + +import co.uk.mommyheather.advancedbackups.AdvancedBackups; +import cpw.mods.fml.common.network.simpleimpl.SimpleNetworkWrapper; +import cpw.mods.fml.relauncher.Side; + +public class NetworkHandler { + + public static final SimpleNetworkWrapper HANDLER = new SimpleNetworkWrapper(AdvancedBackups.MODID); + + public static void init() + { + HANDLER.registerMessage(new PacketBackupStatus.Handler(), PacketBackupStatus.class, 1, Side.CLIENT); + } + +} + diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java new file mode 100644 index 00000000..c893993f --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java @@ -0,0 +1,80 @@ +package co.uk.mommyheather.advancedbackups.network; + +import co.uk.mommyheather.advancedbackups.client.ABClientRenderer; +import cpw.mods.fml.common.network.simpleimpl.IMessage; +import cpw.mods.fml.common.network.simpleimpl.IMessageHandler; +import cpw.mods.fml.common.network.simpleimpl.MessageContext; +import io.netty.buffer.ByteBuf; + +public class PacketBackupStatus implements IMessage{ + public boolean starting; + public boolean started; + public boolean failed; + public boolean finished; + + public int progress; + public int max; + + + public PacketBackupStatus(boolean starting, boolean started, boolean failed, boolean finished, int progress, + int max) { + this.starting = starting; + this.started = started; + this.failed = failed; + this.finished = finished; + this.progress = progress; + this.max = max; + } + + public PacketBackupStatus() { + + } + + @Override + public void fromBytes(ByteBuf buf) { + starting = buf.readBoolean(); + started = buf.readBoolean(); + failed = buf.readBoolean(); + finished = buf.readBoolean(); + + progress = buf.readInt(); + max = buf.readInt(); + } + + @Override + public void toBytes(ByteBuf buf) { + buf.writeBoolean(starting); + buf.writeBoolean(started); + buf.writeBoolean(failed); + buf.writeBoolean(finished); + + buf.writeInt(progress); + buf.writeInt(max); + + } + + + public static class Handler implements IMessageHandler { + + @Override + public IMessage onMessage(PacketBackupStatus message, MessageContext ctx) { + + ABClientRenderer.starting = message.starting; + ABClientRenderer.started = message.started; + ABClientRenderer.failed = message.failed; + ABClientRenderer.finished = message.finished; + + ABClientRenderer.progress = message.progress; + ABClientRenderer.max = message.max; + + + return null; + + } + + } + + + + +} From 7169d5740b552b5772fe691a283cbc0798f4df5e Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sun, 22 Oct 2023 03:12:49 +0100 Subject: [PATCH 336/580] aaand, 1.12! This actually has a toast! --- .../advancedbackups/AdvancedBackups.java | 6 +- .../advancedbackups/client/BackupToast.java | 93 +++++++++++++++++++ .../client/ClientContactor.java | 57 ++++++++++++ .../network/NetworkHandler.java | 22 +++++ .../network/PacketBackupStatus.java | 85 +++++++++++++++++ .../assets/advancedbackups/lang/en_us.lang | 4 + 6 files changed, 265 insertions(+), 2 deletions(-) create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java create mode 100644 src/main/resources/assets/advancedbackups/lang/en_us.lang diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 7a4b7c7e..b5ee11bb 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -1,13 +1,11 @@ package co.uk.mommyheather.advancedbackups; -import net.minecraft.init.Blocks; import net.minecraft.server.MinecraftServer; import net.minecraft.world.WorldServer; import net.minecraftforge.fml.common.Loader; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod.EventBusSubscriber; import net.minecraftforge.fml.common.Mod.EventHandler; -import net.minecraftforge.fml.common.event.FMLInitializationEvent; import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; import net.minecraftforge.fml.common.event.FMLServerStartedEvent; import net.minecraftforge.fml.common.event.FMLServerStartingEvent; @@ -19,10 +17,12 @@ import org.apache.logging.log4j.Logger; +import co.uk.mommyheather.advancedbackups.client.ClientContactor; import co.uk.mommyheather.advancedbackups.core.ABCore; import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; import net.minecraftforge.common.MinecraftForge; import java.io.File; @@ -59,6 +59,7 @@ public AdvancedBackups() { // Register ourselves for server and other game events we are interested in MinecraftForge.EVENT_BUS.register(this); + NetworkHandler.registerMessages(); } @EventHandler @@ -86,6 +87,7 @@ public void onServerStarting(FMLServerStartingEvent event) ABCore.warningLogger = warningLogger; ABCore.errorLogger = errorLogger; + ABCore.clientContactor = new ClientContactor(); ABCore.modJar = Loader.instance().getIndexedModList().get("advancedbackups").getSource(); //ModList.get().getModFileById("advancedbackups").getFile().getFilePath().toFile(); diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java new file mode 100644 index 00000000..beea536b --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java @@ -0,0 +1,93 @@ +package co.uk.mommyheather.advancedbackups.client; + +import com.mojang.realmsclient.gui.ChatFormatting; + +import net.minecraft.client.gui.toasts.GuiToast; +import net.minecraft.client.gui.toasts.IToast; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.RenderHelper; +import net.minecraft.client.resources.I18n; +import net.minecraft.init.Items; +import net.minecraft.item.ItemStack; + +public class BackupToast implements IToast{ + + + public static boolean starting; + public static boolean started; + public static boolean failed; + public static boolean finished; + + public static int progress; + public static int max; + + public static boolean exists = false; + + private static long time; + private static boolean timeSet = false; + + public static final ItemStack stack = new ItemStack(Items.PAPER); + + + @Override + public Visibility draw(GuiToast toastGui, long delta) { + toastGui.getMinecraft().getTextureManager().bindTexture(TEXTURE_TOASTS); + GlStateManager.color(1.0F, 1.0F, 1.0F); + toastGui.drawTexturedModalRect(0, 0, 0, 0, 160, 32); + RenderHelper.enableGUIStandardItemLighting(); + toastGui.getMinecraft().getRenderItem().renderItemAndEffectIntoGUI(stack, 8, 8); + + if (!exists) { + toastGui.getMinecraft().fontRenderer.drawString(ChatFormatting.GREEN + I18n.format("advancedbackups.backup_finished"), 25, 12, -11534256); + return Visibility.HIDE; + } + + String title = "You shouldn't see this!"; + + + if (starting) { + title = ChatFormatting.GREEN + I18n.format("advancedbackups.backup_starting"); + } + else if (started) { + float percent = (float) progress / (float) max; + title = ChatFormatting.GREEN + I18n.format("advancedbackups.progress", round(percent * 100)); + } + else if (failed) { + title = ChatFormatting.RED + I18n.format("advancedbackups.backup_failed"); + if (!timeSet) { + time = System.currentTimeMillis(); + timeSet = true; + } + } + else if (finished) { + title = ChatFormatting.GREEN + I18n.format("advancedbackups.backup_finished"); + if (!timeSet) { + time = System.currentTimeMillis(); + timeSet = true; + } + } + + toastGui.getMinecraft().fontRenderer.drawString(title, 25, 12, -11534256); + + if (timeSet && System.currentTimeMillis() >= time + 5000) { + starting = false; + started = false; + failed = false; + finished = false; + progress = 0; + max = 0; + timeSet = false; + exists = false; + return Visibility.HIDE; + } + + return Visibility.SHOW; + + } + + + private static String round (float value) { + return String.format("%.1f", value); + } + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java new file mode 100644 index 00000000..1a5d639e --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java @@ -0,0 +1,57 @@ +package co.uk.mommyheather.advancedbackups.client; + +import java.util.List; + +import co.uk.mommyheather.advancedbackups.AdvancedBackups; +import co.uk.mommyheather.advancedbackups.interfaces.IClientContactor; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; +import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; +import net.minecraft.entity.player.EntityPlayerMP; + +public class ClientContactor implements IClientContactor { + + @Override + public void backupComplete() { + List players = AdvancedBackups.server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, 0, 0); + for (EntityPlayerMP player : players) { + if (player.canUseCommand(3, "backup")) { + NetworkHandler.HANDLER.sendTo(packet, player); + } + } + } + + @Override + public void backupFailed() { + List players = AdvancedBackups.server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, 0, 0); + for (EntityPlayerMP player : players) { + if (player.canUseCommand(3, "backup")) { + NetworkHandler.HANDLER.sendTo(packet, player); + } + } + } + + @Override + public void backupProgress(int progress, int max) { + List players = AdvancedBackups.server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, progress, max); + for (EntityPlayerMP player : players) { + if (player.canUseCommand(3, "backup")) { + NetworkHandler.HANDLER.sendTo(packet, player); + } + } + } + + @Override + public void backupStarting() { + List players = AdvancedBackups.server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, 0, 0); + for (EntityPlayerMP player : players) { + if (player.canUseCommand(3, "backup")) { + NetworkHandler.HANDLER.sendTo(packet, player); + } + } + } + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java new file mode 100644 index 00000000..06ba310a --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java @@ -0,0 +1,22 @@ +package co.uk.mommyheather.advancedbackups.network; + +import co.uk.mommyheather.advancedbackups.AdvancedBackups; +import net.minecraftforge.fml.common.network.NetworkRegistry; +import net.minecraftforge.fml.common.network.simpleimpl.SimpleNetworkWrapper; +import net.minecraftforge.fml.relauncher.Side; + +public class NetworkHandler { + public static SimpleNetworkWrapper HANDLER; + private static int packetId = 0; + + + public static int nextID() { + return packetId++; + } + + public static void registerMessages() { + HANDLER = NetworkRegistry.INSTANCE.newSimpleChannel(AdvancedBackups.MODID); + // Register messages which are sent from the client to the server here: + HANDLER.registerMessage(PacketBackupStatus.Handler.class, PacketBackupStatus.class, nextID(), Side.CLIENT); + } +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java new file mode 100644 index 00000000..297ceda1 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java @@ -0,0 +1,85 @@ +package co.uk.mommyheather.advancedbackups.network; + +import co.uk.mommyheather.advancedbackups.client.BackupToast; +import io.netty.buffer.ByteBuf; +import net.minecraft.client.Minecraft; +import net.minecraftforge.fml.common.network.simpleimpl.IMessage; +import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; +import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; + +public class PacketBackupStatus implements IMessage{ + public boolean starting; + public boolean started; + public boolean failed; + public boolean finished; + + public int progress; + public int max; + + + public PacketBackupStatus(boolean starting, boolean started, boolean failed, boolean finished, int progress, + int max) { + this.starting = starting; + this.started = started; + this.failed = failed; + this.finished = finished; + this.progress = progress; + this.max = max; + } + + public PacketBackupStatus() { + + } + + @Override + public void fromBytes(ByteBuf buf) { + starting = buf.readBoolean(); + started = buf.readBoolean(); + failed = buf.readBoolean(); + finished = buf.readBoolean(); + + progress = buf.readInt(); + max = buf.readInt(); + } + + @Override + public void toBytes(ByteBuf buf) { + buf.writeBoolean(starting); + buf.writeBoolean(started); + buf.writeBoolean(failed); + buf.writeBoolean(finished); + + buf.writeInt(progress); + buf.writeInt(max); + + } + + + public static class Handler implements IMessageHandler { + + @Override + public IMessage onMessage(PacketBackupStatus message, MessageContext ctx) { + + BackupToast.starting = message.starting; + BackupToast.started = message.started; + BackupToast.failed = message.failed; + BackupToast.finished = message.finished; + + BackupToast.progress = message.progress; + BackupToast.max = message.max; + + if (!BackupToast.exists) { + BackupToast.exists = true; + Minecraft.getMinecraft().getToastGui().add(new BackupToast()); + } + + return null; + + } + + } + + + + +} \ No newline at end of file diff --git a/src/main/resources/assets/advancedbackups/lang/en_us.lang b/src/main/resources/assets/advancedbackups/lang/en_us.lang new file mode 100644 index 00000000..3fc16b27 --- /dev/null +++ b/src/main/resources/assets/advancedbackups/lang/en_us.lang @@ -0,0 +1,4 @@ +advancedbackups.backup_starting=Backup starting! +advancedbackups.progress=Backup ongoing: %s%% +advancedbackups.backup_failed=Backup failed!\nCheck log for more info. +advancedbackups.backup_finished=Backup complete! \ No newline at end of file From 02dd87206b8110d331ed48f34e16b1cd7453f4e5 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sun, 22 Oct 2023 15:36:30 +0100 Subject: [PATCH 337/580] and 1.16! hehe --- .../advancedbackups/AdvancedBackups.java | 4 + .../advancedbackups/client/BackupToast.java | 93 +++++++++++++++++++ .../client/ClientContactor.java | 62 +++++++++++++ .../network/NetworkHandler.java | 37 ++++++++ .../network/PacketBackupStatus.java | 76 +++++++++++++++ .../assets/advancedbackups/lang/en_us.json | 6 ++ 6 files changed, 278 insertions(+) create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java create mode 100644 src/main/resources/assets/advancedbackups/lang/en_us.json diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 7ec40cf6..c82e18b0 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -1,10 +1,12 @@ package co.uk.mommyheather.advancedbackups; +import co.uk.mommyheather.advancedbackups.client.ClientContactor; import co.uk.mommyheather.advancedbackups.core.ABCore; import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; import net.minecraft.server.MinecraftServer; import net.minecraft.world.server.ServerWorld; import net.minecraft.world.storage.FolderName; @@ -39,6 +41,7 @@ public AdvancedBackups() { // Register ourselves for server and other game events we are interested in MinecraftForge.EVENT_BUS.register(this); + NetworkHandler.register(); } @SubscribeEvent @@ -57,6 +60,7 @@ public void onServerStarting(FMLServerStartingEvent event) ABCore.warningLogger = warningLogger; ABCore.errorLogger = errorLogger; + ABCore.clientContactor = new ClientContactor(); ABCore.modJar = ModList.get().getModFileById("advancedbackups").getFile().getFilePath().toFile(); diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java new file mode 100644 index 00000000..c72e59c6 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java @@ -0,0 +1,93 @@ +package co.uk.mommyheather.advancedbackups.client; + +import com.mojang.blaze3d.matrix.MatrixStack; +import com.mojang.blaze3d.platform.GlStateManager; +import com.mojang.blaze3d.systems.RenderSystem; + +import net.minecraft.client.gui.toasts.IToast; +import net.minecraft.client.gui.toasts.ToastGui; +import net.minecraft.client.renderer.RenderHelper; +import net.minecraft.client.resources.I18n; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.util.text.TextFormatting; + +public class BackupToast implements IToast { + + public static boolean starting; + public static boolean started; + public static boolean failed; + public static boolean finished; + + public static int progress; + public static int max; + + public static boolean exists = false; + + private static long time; + private static boolean timeSet = false; + + public static final ItemStack stack = new ItemStack(Items.PAPER); + + + @Override + public Visibility render(MatrixStack matrix, ToastGui toastGui, long delta) { + toastGui.getMinecraft().getTextureManager().bind(TEXTURE); + RenderSystem.color3f(1.0F, 1.0F, 1.0F); + toastGui.blit(matrix, 0, 0, 0, 0, this.width(), this.height()); + toastGui.getMinecraft().getItemRenderer().renderAndDecorateFakeItem(stack, 8, 8); + + if (!exists) { + toastGui.getMinecraft().font.draw(matrix, TextFormatting.GREEN + I18n.get("advancedbackups.backup_finished"), 25, 11, -11534256); + return Visibility.HIDE; + } + + String title = "You shouldn't see this!"; + + + if (starting) { + title = TextFormatting.GREEN + I18n.get("advancedbackups.backup_starting"); + } + else if (started) { + float percent = (float) progress / (float) max; + title = TextFormatting.GREEN + I18n.get("advancedbackups.progress", round(percent * 100)); + } + else if (failed) { + title = TextFormatting.RED + I18n.get("advancedbackups.backup_failed"); + if (!timeSet) { + time = System.currentTimeMillis(); + timeSet = true; + } + } + else if (finished) { + title = TextFormatting.GREEN + I18n.get("advancedbackups.backup_finished"); + if (!timeSet) { + time = System.currentTimeMillis(); + timeSet = true; + } + } + + toastGui.getMinecraft().font.draw(matrix, title, 25, 11, -11534256); + + if (timeSet && System.currentTimeMillis() >= time + 5000) { + starting = false; + started = false; + failed = false; + finished = false; + progress = 0; + max = 0; + timeSet = false; + exists = false; + return Visibility.HIDE; + } + + return Visibility.SHOW; + + } + + + private static String round (float value) { + return String.format("%.1f", value); + } + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java new file mode 100644 index 00000000..7589193a --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java @@ -0,0 +1,62 @@ +package co.uk.mommyheather.advancedbackups.client; + +import java.util.List; + +import co.uk.mommyheather.advancedbackups.AdvancedBackups; +import co.uk.mommyheather.advancedbackups.interfaces.IClientContactor; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; +import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; +import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.server.MinecraftServer; +import net.minecraftforge.fml.server.ServerLifecycleHooks; + +public class ClientContactor implements IClientContactor { + + @Override + public void backupComplete() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, 0, 0); + for (ServerPlayerEntity player : players) { + if (player.hasPermissions(3)) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupFailed() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, 0, 0); + for (ServerPlayerEntity player : players) { + if (player.hasPermissions(3)) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupProgress(int progress, int max) { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, progress, max); + for (ServerPlayerEntity player : players) { + if (player.hasPermissions(3)) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupStarting() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, 0, 0); + for (ServerPlayerEntity player : players) { + if (player.hasPermissions(3)) { + NetworkHandler.sendToClient(player, packet); + } + } + } +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java new file mode 100644 index 00000000..f9107760 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java @@ -0,0 +1,37 @@ +package co.uk.mommyheather.advancedbackups.network; + +import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.fml.network.NetworkDirection; +import net.minecraftforge.fml.network.NetworkRegistry; +import net.minecraftforge.fml.network.simple.SimpleChannel; + +public class NetworkHandler { + + private static final String PROTOCOL_VERSION = "1"; + private static int id = 0; + private static int id() { + return id++; + } + + public static final SimpleChannel INSTANCE = NetworkRegistry.newSimpleChannel( + new ResourceLocation("advancedbackups", "main"), + () -> PROTOCOL_VERSION, + (version) -> true, + (version) -> true + ); + + + public static void register() { + INSTANCE.messageBuilder(PacketBackupStatus.class, id()) + .encoder(PacketBackupStatus::toBytes) + .decoder(buf -> new PacketBackupStatus(buf)) + .consumer(PacketBackupStatus::handle) + .add(); + } + + public static void sendToClient(ServerPlayerEntity player, Object packet) { + INSTANCE.sendTo(packet, player.connection.connection, NetworkDirection.PLAY_TO_CLIENT); + } + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java new file mode 100644 index 00000000..d8db5ed2 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java @@ -0,0 +1,76 @@ +package co.uk.mommyheather.advancedbackups.network; + +import java.util.function.Supplier; + +import co.uk.mommyheather.advancedbackups.client.BackupToast; +import net.minecraft.client.Minecraft; +import net.minecraft.network.PacketBuffer; +import net.minecraftforge.fml.LogicalSide; +import net.minecraftforge.fml.network.NetworkEvent; + +public class PacketBackupStatus { + + public boolean starting; + public boolean started; + + public boolean failed; + public boolean finished; + + public int progress; + public int max; + + + public PacketBackupStatus(boolean starting, boolean started, boolean failed, boolean finished, int progress, + int max) { + this.starting = starting; + this.started = started; + this.failed = failed; + this.finished = finished; + this.progress = progress; + this.max = max; + } + + + public PacketBackupStatus(PacketBuffer buf) { + starting = buf.readBoolean(); + started = buf.readBoolean(); + failed = buf.readBoolean(); + finished = buf.readBoolean(); + + progress = buf.readInt(); + max = buf.readInt(); + } + + public void toBytes(PacketBuffer buf) { + buf.writeBoolean(starting); + buf.writeBoolean(started); + buf.writeBoolean(failed); + buf.writeBoolean(finished); + + buf.writeInt(progress); + buf.writeInt(max); + } + + public boolean handle(Supplier ctx) { + ctx.get().enqueueWork(() -> { + if (ctx.get().getDirection().getReceptionSide() == LogicalSide.CLIENT) { + BackupToast.starting = starting; + BackupToast.started = started; + BackupToast.failed = failed; + BackupToast.finished = finished; + + BackupToast.progress = progress; + BackupToast.max = max; + + if (!BackupToast.exists) { + BackupToast.exists = true; + Minecraft.getInstance().getToasts().addToast(new BackupToast()); + } + } + }); + ctx.get().setPacketHandled(true); + return true; + + } + +} diff --git a/src/main/resources/assets/advancedbackups/lang/en_us.json b/src/main/resources/assets/advancedbackups/lang/en_us.json new file mode 100644 index 00000000..cc68dae1 --- /dev/null +++ b/src/main/resources/assets/advancedbackups/lang/en_us.json @@ -0,0 +1,6 @@ +{ + "advancedbackups.backup_starting" : "Backup starting!", + "advancedbackups.progress": "Backup ongoing: %1$s%%", + "advancedbackups.backup_failed": "Backup failed!\nCheck log for more info.", + "advancedbackups.backup_finished": "Backup complete!" +} \ No newline at end of file From 879d60e7bbcf47750f0680148bbeda233fca7c78 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sun, 22 Oct 2023 16:51:46 +0100 Subject: [PATCH 338/580] thread safety! --- .../network/PacketBackupStatus.java | 29 +++++++++++-------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java index 297ceda1..86441983 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java @@ -60,18 +60,23 @@ public static class Handler implements IMessageHandler { + + BackupToast.starting = message.starting; + BackupToast.started = message.started; + BackupToast.failed = message.failed; + BackupToast.finished = message.finished; + + BackupToast.progress = message.progress; + BackupToast.max = message.max; + + if (!BackupToast.exists) { + BackupToast.exists = true; + Minecraft.getMinecraft().getToastGui().add(new BackupToast()); + } + + }); + return null; From 5ddfcdb44505912165d42adce3680cc0356a2010 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sun, 22 Oct 2023 17:28:59 +0100 Subject: [PATCH 339/580] and that's fabric 1.18! god damm i dislike fabric --- .../advancedbackups/AdvancedBackups.java | 7 ++ .../client/ClientContactor.java | 61 +++++++++++++ .../advancedbackups/network/BackupToast.java | 91 +++++++++++++++++++ .../network/NetworkHandler.java | 26 ++++++ .../network/PacketBackupStatus.java | 82 +++++++++++++++++ .../assets/advancedbackups/lang/en_us.json | 6 ++ 6 files changed, 273 insertions(+) create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/network/BackupToast.java create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java create mode 100644 src/main/resources/assets/advancedbackups/lang/en_us.json diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 366f8e8b..2f6aa032 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -16,10 +16,12 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import co.uk.mommyheather.advancedbackups.client.ClientContactor; import co.uk.mommyheather.advancedbackups.core.ABCore; import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; public class AdvancedBackups implements ModInitializer { // This logger is used to write text to the console and the log file. @@ -36,6 +38,10 @@ public class AdvancedBackups implements ModInitializer { @Override public void onInitialize() { + + NetworkHandler.init(); + + ServerLifecycleEvents.SERVER_STARTING.register((server) -> { AdvancedBackups.server = server; ABCore.worldName = server.getSaveProperties().getLevelName(); @@ -49,6 +55,7 @@ public void onInitialize() { ABCore.warningLogger = warningLogger; ABCore.errorLogger = errorLogger; + ABCore.clientContactor = new ClientContactor(); ABCore.modJar = new File(FabricLoaderImpl.INSTANCE.getModContainer("advancedbackups").get().getOrigin().toString()); diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java new file mode 100644 index 00000000..7b8e9237 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java @@ -0,0 +1,61 @@ +package co.uk.mommyheather.advancedbackups.client; + +import java.util.List; + +import co.uk.mommyheather.advancedbackups.AdvancedBackups; +import co.uk.mommyheather.advancedbackups.interfaces.IClientContactor; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; +import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.network.ServerPlayerEntity; + +public class ClientContactor implements IClientContactor { + + @Override + public void backupComplete() { + MinecraftServer server = AdvancedBackups.server; + List players = server.getPlayerManager().getPlayerList(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, 0, 0); + for (ServerPlayerEntity player : players) { + if (player.hasPermissionLevel(3)) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupFailed() { + MinecraftServer server = AdvancedBackups.server; + List players = server.getPlayerManager().getPlayerList(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, 0, 0); + for (ServerPlayerEntity player : players) { + if (player.hasPermissionLevel(3)) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupProgress(int progress, int max) { + MinecraftServer server = AdvancedBackups.server; + List players = server.getPlayerManager().getPlayerList(); + PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, progress, max); + for (ServerPlayerEntity player : players) { + if (player.hasPermissionLevel(3)) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupStarting() { + MinecraftServer server = AdvancedBackups.server; + List players = server.getPlayerManager().getPlayerList(); + PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, 0, 0); + for (ServerPlayerEntity player : players) { + if (player.hasPermissionLevel(3)) { + NetworkHandler.sendToClient(player, packet); + } + } + } +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/BackupToast.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/BackupToast.java new file mode 100644 index 00000000..5b0454eb --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/BackupToast.java @@ -0,0 +1,91 @@ +package co.uk.mommyheather.advancedbackups.network; + +import com.mojang.blaze3d.systems.RenderSystem; + +import net.minecraft.client.render.GameRenderer; +import net.minecraft.client.resource.language.I18n; +import net.minecraft.client.toast.Toast; +import net.minecraft.client.toast.ToastManager; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.util.Formatting; + +public class BackupToast implements Toast { + + public static boolean starting; + public static boolean started; + public static boolean failed; + public static boolean finished; + + public static int progress; + public static int max; + + public static boolean exists = false; + + private static long time; + private static boolean timeSet = false; + + public static final ItemStack stack = new ItemStack(Items.PAPER); + + @Override + public Visibility draw(MatrixStack matrix, ToastManager manager, long startTime) { + RenderSystem.setShader(GameRenderer::getPositionTexShader); + RenderSystem.setShaderTexture(0, TEXTURE); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + manager.drawTexture(matrix, 0, 0, 0, 0, this.getWidth(), this.getHeight()); + manager.getClient().getItemRenderer().renderGuiItemIcon(stack, 8, 8); + + if (!exists) { + manager.getClient().textRenderer.draw(matrix, Formatting.GREEN + I18n.translate("advancedbackups.backup_finished"), 25, 11, -11534256); + return Visibility.HIDE; + } + + String title = "You shouldn't see this!"; + + + if (starting) { + title = Formatting.GREEN + I18n.translate("advancedbackups.backup_starting"); + } + else if (started) { + float percent = (float) progress / (float) max; + title = Formatting.GREEN + I18n.translate("advancedbackups.progress", round(percent * 100)); + } + else if (failed) { + title = Formatting.RED + I18n.translate("advancedbackups.backup_failed"); + if (!timeSet) { + time = System.currentTimeMillis(); + timeSet = true; + } + } + else if (finished) { + title = Formatting.GREEN + I18n.translate("advancedbackups.backup_finished"); + if (!timeSet) { + time = System.currentTimeMillis(); + timeSet = true; + } + } + + manager.getClient().textRenderer.draw(matrix, title, 25, 11, -11534256); + + if (timeSet && System.currentTimeMillis() >= time + 5000) { + starting = false; + started = false; + failed = false; + finished = false; + progress = 0; + max = 0; + timeSet = false; + exists = false; + return Visibility.HIDE; + } + + return Visibility.SHOW; + } + + + private static String round (float value) { + return String.format("%.1f", value); + } + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java new file mode 100644 index 00000000..2e20d30d --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java @@ -0,0 +1,26 @@ +package co.uk.mommyheather.advancedbackups.network; + +import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; +import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; +import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.util.Identifier; + +public class NetworkHandler { + + public static Identifier STATUS_PACKET_ID = new Identifier("advancedbackups", "backup_status"); + + public static void init() { + ClientPlayNetworking.registerGlobalReceiver(STATUS_PACKET_ID, PacketBackupStatus::handle); + } + + + public static void sendToClient(ServerPlayerEntity player, PacketBackupStatus packet) { + + ServerPlayNetworking.send(player, STATUS_PACKET_ID, packet.write(PacketByteBufs.create())); + + } + + + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java new file mode 100644 index 00000000..5e4ab78e --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java @@ -0,0 +1,82 @@ +package co.uk.mommyheather.advancedbackups.network; + +import net.fabricmc.fabric.api.networking.v1.PacketSender; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientPlayNetworkHandler; +import net.minecraft.network.PacketByteBuf; + +public class PacketBackupStatus { + + public boolean starting; + public boolean started; + public boolean failed; + public boolean finished; + + public int progress; + public int max; + + + public PacketBackupStatus(boolean starting, boolean started, boolean failed, boolean finished, int progress, + int max) { + this.starting = starting; + this.started = started; + this.failed = failed; + this.finished = finished; + this.progress = progress; + this.max = max; + } + + public PacketBackupStatus() { + + } + + public void read(PacketByteBuf buf) { + starting = buf.readBoolean(); + started = buf.readBoolean(); + failed = buf.readBoolean(); + finished = buf.readBoolean(); + + progress = buf.readInt(); + max = buf.readInt(); + } + + public PacketByteBuf write(PacketByteBuf buf) { + buf.writeBoolean(starting); + buf.writeBoolean(started); + buf.writeBoolean(failed); + buf.writeBoolean(finished); + + buf.writeInt(progress); + buf.writeInt(max); + + return buf; + + } + + + + public static void handle(MinecraftClient client, ClientPlayNetworkHandler handler, PacketByteBuf buf, PacketSender responseSender) { + + PacketBackupStatus message = new PacketBackupStatus(); + message.read(buf); + + client.execute(() -> { + BackupToast.starting = message.starting; + BackupToast.started = message.started; + BackupToast.failed = message.failed; + BackupToast.finished = message.finished; + + BackupToast.progress = message.progress; + BackupToast.max = message.max; + + if (!BackupToast.exists) { + BackupToast.exists = true; + client.getToastManager().add(new BackupToast()); + } + + }); + + + } + + } diff --git a/src/main/resources/assets/advancedbackups/lang/en_us.json b/src/main/resources/assets/advancedbackups/lang/en_us.json new file mode 100644 index 00000000..cc68dae1 --- /dev/null +++ b/src/main/resources/assets/advancedbackups/lang/en_us.json @@ -0,0 +1,6 @@ +{ + "advancedbackups.backup_starting" : "Backup starting!", + "advancedbackups.progress": "Backup ongoing: %1$s%%", + "advancedbackups.backup_failed": "Backup failed!\nCheck log for more info.", + "advancedbackups.backup_finished": "Backup complete!" +} \ No newline at end of file From bb8fd124f3261fbc6d00b49f6b838022ddcaf761 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sun, 22 Oct 2023 19:29:45 +0100 Subject: [PATCH 340/580] move BackupToast to correct package --- .../advancedbackups/{network => client}/BackupToast.java | 2 +- .../advancedbackups/network/PacketBackupStatus.java | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) rename src/main/java/co/uk/mommyheather/advancedbackups/{network => client}/BackupToast.java (98%) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/BackupToast.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java similarity index 98% rename from src/main/java/co/uk/mommyheather/advancedbackups/network/BackupToast.java rename to src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java index 5b0454eb..62b1e7cf 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/BackupToast.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java @@ -1,4 +1,4 @@ -package co.uk.mommyheather.advancedbackups.network; +package co.uk.mommyheather.advancedbackups.client; import com.mojang.blaze3d.systems.RenderSystem; diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java index 5e4ab78e..c8ff2791 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java @@ -1,5 +1,6 @@ package co.uk.mommyheather.advancedbackups.network; +import co.uk.mommyheather.advancedbackups.client.BackupToast; import net.fabricmc.fabric.api.networking.v1.PacketSender; import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.ClientPlayNetworkHandler; From 87320edbe6ea5fe098c72cf6946634cad8e10d6f Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sun, 22 Oct 2023 19:40:23 +0100 Subject: [PATCH 341/580] Client contact, but for 1.18 forge. --- .../advancedbackups/AdvancedBackups.java | 5 + .../advancedbackups/client/BackupToast.java | 95 +++++++++++++++++++ .../client/ClientContactor.java | 61 ++++++++++++ .../network/NetworkHandler.java | 37 ++++++++ .../network/PacketBackupStatus.java | 76 +++++++++++++++ .../assets/advancedbackups/lang/en_us.json | 6 ++ 6 files changed, 280 insertions(+) create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java create mode 100644 src/main/resources/assets/advancedbackups/lang/en_us.json diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index a499004f..56d222a4 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -2,10 +2,12 @@ import com.mojang.logging.LogUtils; +import co.uk.mommyheather.advancedbackups.client.ClientContactor; import co.uk.mommyheather.advancedbackups.core.ABCore; import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.storage.LevelResource; @@ -40,6 +42,7 @@ public AdvancedBackups() { // Register ourselves for server and other game events we are interested in MinecraftForge.EVENT_BUS.register(this); + NetworkHandler.register(); } @SubscribeEvent @@ -57,6 +60,8 @@ public void onServerStarting(ServerStartingEvent event) ABCore.infoLogger = infoLogger; ABCore.warningLogger = warningLogger; ABCore.errorLogger = errorLogger; + + ABCore.clientContactor = new ClientContactor(); ABCore.modJar = ModList.get().getModFileById("advancedbackups").getFile().getFilePath().toFile(); diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java new file mode 100644 index 00000000..aeacde0f --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java @@ -0,0 +1,95 @@ +package co.uk.mommyheather.advancedbackups.client; + +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.PoseStack; + +import net.minecraft.ChatFormatting; +import net.minecraft.client.gui.components.toasts.Toast; +import net.minecraft.client.gui.components.toasts.ToastComponent; +import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.client.resources.language.I18n; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.TranslatableComponent; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; + +public class BackupToast implements Toast { + + public static boolean starting; + public static boolean started; + public static boolean failed; + public static boolean finished; + + public static int progress; + public static int max; + + public static boolean exists = false; + + private static long time; + private static boolean timeSet = false; + + public static final ItemStack stack = new ItemStack(Items.PAPER); + + + @Override + public Visibility render(PoseStack matrix, ToastComponent toastGui, long delta) { + RenderSystem.setShader(GameRenderer::getPositionTexShader); + RenderSystem.setShaderTexture(0, TEXTURE); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + toastGui.blit(matrix, 0, 0, 0, 0, this.width(), this.height()); + toastGui.getMinecraft().getItemRenderer().renderAndDecorateFakeItem(stack, 8, 8); + + if (!exists) { + toastGui.getMinecraft().font.draw(matrix, ChatFormatting.GREEN + I18n.get("advancedbackups.backup_finished"), 25, 11, -11534256); + return Visibility.HIDE; + } + + String title = "You shouldn't see this!"; + + + if (starting) { + title = ChatFormatting.GREEN + I18n.get("advancedbackups.backup_starting"); + } + else if (started) { + float percent = (float) progress / (float) max; + title = ChatFormatting.GREEN + I18n.get("advancedbackups.progress", round(percent * 100)); + } + else if (failed) { + title = ChatFormatting.RED + I18n.get("advancedbackups.backup_failed"); + if (!timeSet) { + time = System.currentTimeMillis(); + timeSet = true; + } + } + else if (finished) { + title = ChatFormatting.GREEN + I18n.get("advancedbackups.backup_finished"); + if (!timeSet) { + time = System.currentTimeMillis(); + timeSet = true; + } + } + + toastGui.getMinecraft().font.draw(matrix, title, 25, 11, -11534256); + + if (timeSet && System.currentTimeMillis() >= time + 5000) { + starting = false; + started = false; + failed = false; + finished = false; + progress = 0; + max = 0; + timeSet = false; + exists = false; + return Visibility.HIDE; + } + + return Visibility.SHOW; + + } + + + private static String round (float value) { + return String.format("%.1f", value); + } + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java new file mode 100644 index 00000000..ffa8bf23 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java @@ -0,0 +1,61 @@ +package co.uk.mommyheather.advancedbackups.client; + +import java.util.List; + +import co.uk.mommyheather.advancedbackups.interfaces.IClientContactor; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; +import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerPlayer; +import net.minecraftforge.server.ServerLifecycleHooks; + +public class ClientContactor implements IClientContactor { + + @Override + public void backupComplete() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, 0, 0); + for (ServerPlayer player : players) { + if (player.hasPermissions(3)) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupFailed() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, 0, 0); + for (ServerPlayer player : players) { + if (player.hasPermissions(3)) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupProgress(int progress, int max) { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, progress, max); + for (ServerPlayer player : players) { + if (player.hasPermissions(3)) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupStarting() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, 0, 0); + for (ServerPlayer player : players) { + if (player.hasPermissions(3)) { + NetworkHandler.sendToClient(player, packet); + } + } + } +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java new file mode 100644 index 00000000..69a388a4 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java @@ -0,0 +1,37 @@ +package co.uk.mommyheather.advancedbackups.network; + +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerPlayer; +import net.minecraftforge.network.NetworkDirection; +import net.minecraftforge.network.NetworkRegistry; +import net.minecraftforge.network.simple.SimpleChannel; + +public class NetworkHandler { + + private static final String PROTOCOL_VERSION = "1"; + private static int id = 0; + private static int id() { + return id++; + } + + public static final SimpleChannel INSTANCE = NetworkRegistry.newSimpleChannel( + new ResourceLocation("advancedbackups", "main"), + () -> PROTOCOL_VERSION, + (version) -> true, + (version) -> true + ); + + + public static void register() { + INSTANCE.messageBuilder(PacketBackupStatus.class, id()) + .encoder(PacketBackupStatus::toBytes) + .decoder(buf -> new PacketBackupStatus(buf)) + .consumer(PacketBackupStatus::handle) + .add(); + } + + public static void sendToClient(ServerPlayer player, Object packet) { + INSTANCE.sendTo(packet, player.connection.connection, NetworkDirection.PLAY_TO_CLIENT); + } + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java new file mode 100644 index 00000000..a7d0f1f5 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java @@ -0,0 +1,76 @@ +package co.uk.mommyheather.advancedbackups.network; + +import java.util.function.Supplier; + +import co.uk.mommyheather.advancedbackups.client.BackupToast; +import net.minecraft.client.Minecraft; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraftforge.fml.LogicalSide; +import net.minecraftforge.network.NetworkEvent; + +public class PacketBackupStatus { + + public boolean starting; + public boolean started; + + public boolean failed; + public boolean finished; + + public int progress; + public int max; + + + public PacketBackupStatus(boolean starting, boolean started, boolean failed, boolean finished, int progress, + int max) { + this.starting = starting; + this.started = started; + this.failed = failed; + this.finished = finished; + this.progress = progress; + this.max = max; + } + + + public PacketBackupStatus(FriendlyByteBuf buf) { + starting = buf.readBoolean(); + started = buf.readBoolean(); + failed = buf.readBoolean(); + finished = buf.readBoolean(); + + progress = buf.readInt(); + max = buf.readInt(); + } + + public void toBytes(FriendlyByteBuf buf) { + buf.writeBoolean(starting); + buf.writeBoolean(started); + buf.writeBoolean(failed); + buf.writeBoolean(finished); + + buf.writeInt(progress); + buf.writeInt(max); + } + + public boolean handle(Supplier ctx) { + ctx.get().enqueueWork(() -> { + if (ctx.get().getDirection().getReceptionSide() == LogicalSide.CLIENT) { + BackupToast.starting = starting; + BackupToast.started = started; + BackupToast.failed = failed; + BackupToast.finished = finished; + + BackupToast.progress = progress; + BackupToast.max = max; + + if (!BackupToast.exists) { + BackupToast.exists = true; + Minecraft.getInstance().getToasts().addToast(new BackupToast()); + } + } + }); + ctx.get().setPacketHandled(true); + return true; + + } + +} diff --git a/src/main/resources/assets/advancedbackups/lang/en_us.json b/src/main/resources/assets/advancedbackups/lang/en_us.json new file mode 100644 index 00000000..cc68dae1 --- /dev/null +++ b/src/main/resources/assets/advancedbackups/lang/en_us.json @@ -0,0 +1,6 @@ +{ + "advancedbackups.backup_starting" : "Backup starting!", + "advancedbackups.progress": "Backup ongoing: %1$s%%", + "advancedbackups.backup_failed": "Backup failed!\nCheck log for more info.", + "advancedbackups.backup_finished": "Backup complete!" +} \ No newline at end of file From c7a8865db7ac2770370182efa676b37316786fb0 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sun, 22 Oct 2023 20:34:41 +0100 Subject: [PATCH 342/580] Add progress bar! --- .../advancedbackups/client/BackupToast.java | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java index beea536b..70a90bcb 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java @@ -2,6 +2,7 @@ import com.mojang.realmsclient.gui.ChatFormatting; +import net.minecraft.client.gui.Gui; import net.minecraft.client.gui.toasts.GuiToast; import net.minecraft.client.gui.toasts.IToast; import net.minecraft.client.renderer.GlStateManager; @@ -9,6 +10,7 @@ import net.minecraft.client.resources.I18n; import net.minecraft.init.Items; import net.minecraft.item.ItemStack; +import net.minecraft.util.math.MathHelper; public class BackupToast implements IToast{ @@ -37,19 +39,27 @@ public Visibility draw(GuiToast toastGui, long delta) { RenderHelper.enableGUIStandardItemLighting(); toastGui.getMinecraft().getRenderItem().renderItemAndEffectIntoGUI(stack, 8, 8); + float percent = finished ? 100 : (float) progress / (float) max; + + Gui.drawRect(3, 28, 156, 29, -1); + float f = Math.min(156, ( + 156 * percent + )); + if (!exists) { toastGui.getMinecraft().fontRenderer.drawString(ChatFormatting.GREEN + I18n.format("advancedbackups.backup_finished"), 25, 12, -11534256); + Gui.drawRect(3, 28, 156, 29, -10948014); return Visibility.HIDE; } String title = "You shouldn't see this!"; + if (starting) { title = ChatFormatting.GREEN + I18n.format("advancedbackups.backup_starting"); } else if (started) { - float percent = (float) progress / (float) max; title = ChatFormatting.GREEN + I18n.format("advancedbackups.progress", round(percent * 100)); } else if (failed) { @@ -80,6 +90,10 @@ else if (finished) { exists = false; return Visibility.HIDE; } + + + Gui.drawRect(3, 28, (int) f, 29, -10948014); + return Visibility.SHOW; From e6ed136dda37a4164b1a31479acf5d815ccec76a Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sun, 22 Oct 2023 20:59:57 +0100 Subject: [PATCH 343/580] Update README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 5e41c346..8f24b346 100644 --- a/README.md +++ b/README.md @@ -2,3 +2,6 @@ This is the branch specifically for forge 1.7.10. Any differences will be listed below. For full documentation, see the `core` branch. + + +- Backup progress is sent to ops via form of a text overlay, rather than a toast. From 8ee4f5d327d6027a9023a4142e7dad5b192deea2 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sun, 22 Oct 2023 21:15:02 +0100 Subject: [PATCH 344/580] progress bar, in 1.16 --- .../advancedbackups/client/BackupToast.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java index c72e59c6..ea65b5d0 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java @@ -4,6 +4,7 @@ import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.systems.RenderSystem; +import net.minecraft.client.gui.AbstractGui; import net.minecraft.client.gui.toasts.IToast; import net.minecraft.client.gui.toasts.ToastGui; import net.minecraft.client.renderer.RenderHelper; @@ -37,8 +38,16 @@ public Visibility render(MatrixStack matrix, ToastGui toastGui, long delta) { toastGui.blit(matrix, 0, 0, 0, 0, this.width(), this.height()); toastGui.getMinecraft().getItemRenderer().renderAndDecorateFakeItem(stack, 8, 8); + float percent = finished ? 100 : (float) progress / (float) max; + + AbstractGui.fill(matrix, 3, 28, 156, 29, -1); + float f = Math.min(156, ( + 156 * percent + )); + if (!exists) { toastGui.getMinecraft().font.draw(matrix, TextFormatting.GREEN + I18n.get("advancedbackups.backup_finished"), 25, 11, -11534256); + AbstractGui.fill(matrix, 3, 28, 156, 29, -10948014); return Visibility.HIDE; } @@ -49,7 +58,6 @@ public Visibility render(MatrixStack matrix, ToastGui toastGui, long delta) { title = TextFormatting.GREEN + I18n.get("advancedbackups.backup_starting"); } else if (started) { - float percent = (float) progress / (float) max; title = TextFormatting.GREEN + I18n.get("advancedbackups.progress", round(percent * 100)); } else if (failed) { @@ -80,6 +88,8 @@ else if (finished) { exists = false; return Visibility.HIDE; } + + AbstractGui.fill(matrix, 3, 28, Math.max(3, (int) f), 29, -10948014); return Visibility.SHOW; From 094f46ff8038771e1eb7387491515e57975bef26 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sun, 22 Oct 2023 21:21:08 +0100 Subject: [PATCH 345/580] Progress bar, forge 1.18 --- .../advancedbackups/client/BackupToast.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java index aeacde0f..aacaba27 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java @@ -4,6 +4,7 @@ import com.mojang.blaze3d.vertex.PoseStack; import net.minecraft.ChatFormatting; +import net.minecraft.client.gui.Gui; import net.minecraft.client.gui.components.toasts.Toast; import net.minecraft.client.gui.components.toasts.ToastComponent; import net.minecraft.client.renderer.GameRenderer; @@ -39,8 +40,18 @@ public Visibility render(PoseStack matrix, ToastComponent toastGui, long delta) toastGui.blit(matrix, 0, 0, 0, 0, this.width(), this.height()); toastGui.getMinecraft().getItemRenderer().renderAndDecorateFakeItem(stack, 8, 8); + + float percent = finished ? 100 : (float) progress / (float) max; + + Gui.fill(matrix, 3, 28, 156, 29, -1); + float f = Math.min(156, ( + 156 * percent + )); + + if (!exists) { toastGui.getMinecraft().font.draw(matrix, ChatFormatting.GREEN + I18n.get("advancedbackups.backup_finished"), 25, 11, -11534256); + Gui.fill(matrix, 3, 28, 156, 29, -10948014); return Visibility.HIDE; } @@ -51,7 +62,6 @@ public Visibility render(PoseStack matrix, ToastComponent toastGui, long delta) title = ChatFormatting.GREEN + I18n.get("advancedbackups.backup_starting"); } else if (started) { - float percent = (float) progress / (float) max; title = ChatFormatting.GREEN + I18n.get("advancedbackups.progress", round(percent * 100)); } else if (failed) { @@ -83,6 +93,8 @@ else if (finished) { return Visibility.HIDE; } + Gui.fill(matrix, 3, 28, Math.max(3, (int) f), 29, -10948014); + return Visibility.SHOW; } From 7915b03fc56b930d9b22136c30cec21fb9f004f2 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sun, 22 Oct 2023 21:27:58 +0100 Subject: [PATCH 346/580] Progress bar, fabric 1.18! --- .../advancedbackups/client/BackupToast.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java index 62b1e7cf..6b0c5579 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java @@ -2,6 +2,7 @@ import com.mojang.blaze3d.systems.RenderSystem; +import net.minecraft.client.gui.DrawableHelper; import net.minecraft.client.render.GameRenderer; import net.minecraft.client.resource.language.I18n; import net.minecraft.client.toast.Toast; @@ -35,9 +36,18 @@ public Visibility draw(MatrixStack matrix, ToastManager manager, long startTime) RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); manager.drawTexture(matrix, 0, 0, 0, 0, this.getWidth(), this.getHeight()); manager.getClient().getItemRenderer().renderGuiItemIcon(stack, 8, 8); + + float percent = finished ? 100 : (float) progress / (float) max; + + DrawableHelper.fill(matrix, 3, 28, 156, 29, -1); + + float f = Math.min(156, ( + 156 * percent + )); if (!exists) { manager.getClient().textRenderer.draw(matrix, Formatting.GREEN + I18n.translate("advancedbackups.backup_finished"), 25, 11, -11534256); + DrawableHelper.fill(matrix, 3, 28, 156, 29, -10948014); return Visibility.HIDE; } @@ -48,7 +58,6 @@ public Visibility draw(MatrixStack matrix, ToastManager manager, long startTime) title = Formatting.GREEN + I18n.translate("advancedbackups.backup_starting"); } else if (started) { - float percent = (float) progress / (float) max; title = Formatting.GREEN + I18n.translate("advancedbackups.progress", round(percent * 100)); } else if (failed) { @@ -79,6 +88,8 @@ else if (finished) { exists = false; return Visibility.HIDE; } + + DrawableHelper.fill(matrix, 3, 28, Math.max(3, (int) f), 29, -10948014); return Visibility.SHOW; } From f7f41b168f60ddcf7012f1e7ecb27aefb0470716 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sun, 22 Oct 2023 21:43:26 +0100 Subject: [PATCH 347/580] Client contact, with progress bar, 1.19 fabric! --- .../advancedbackups/AdvancedBackups.java | 7 +- .../advancedbackups/client/BackupToast.java | 102 ++++++++++++++++++ .../client/ClientContactor.java | 61 +++++++++++ .../network/NetworkHandler.java | 26 +++++ .../network/PacketBackupStatus.java | 83 ++++++++++++++ .../assets/advancedbackups/lang/en_us.json | 6 ++ 6 files changed, 284 insertions(+), 1 deletion(-) create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java create mode 100644 src/main/resources/assets/advancedbackups/lang/en_us.json diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 42fe632a..fea2d6bb 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -16,10 +16,12 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import co.uk.mommyheather.advancedbackups.client.ClientContactor; import co.uk.mommyheather.advancedbackups.core.ABCore; import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; public class AdvancedBackups implements ModInitializer { // This logger is used to write text to the console and the log file. @@ -36,6 +38,9 @@ public class AdvancedBackups implements ModInitializer { @Override public void onInitialize() { + + NetworkHandler.init(); + ServerLifecycleEvents.SERVER_STARTING.register((server) -> { AdvancedBackups.server = server; ABCore.worldName = server.getSaveProperties().getLevelName(); @@ -49,7 +54,7 @@ public void onInitialize() { ABCore.warningLogger = warningLogger; ABCore.errorLogger = errorLogger; - + ABCore.clientContactor = new ClientContactor(); ABCore.modJar = new File(FabricLoaderImpl.INSTANCE.getModContainer("advancedbackups").get().getOrigin().toString()); diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java new file mode 100644 index 00000000..6b0c5579 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java @@ -0,0 +1,102 @@ +package co.uk.mommyheather.advancedbackups.client; + +import com.mojang.blaze3d.systems.RenderSystem; + +import net.minecraft.client.gui.DrawableHelper; +import net.minecraft.client.render.GameRenderer; +import net.minecraft.client.resource.language.I18n; +import net.minecraft.client.toast.Toast; +import net.minecraft.client.toast.ToastManager; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.util.Formatting; + +public class BackupToast implements Toast { + + public static boolean starting; + public static boolean started; + public static boolean failed; + public static boolean finished; + + public static int progress; + public static int max; + + public static boolean exists = false; + + private static long time; + private static boolean timeSet = false; + + public static final ItemStack stack = new ItemStack(Items.PAPER); + + @Override + public Visibility draw(MatrixStack matrix, ToastManager manager, long startTime) { + RenderSystem.setShader(GameRenderer::getPositionTexShader); + RenderSystem.setShaderTexture(0, TEXTURE); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + manager.drawTexture(matrix, 0, 0, 0, 0, this.getWidth(), this.getHeight()); + manager.getClient().getItemRenderer().renderGuiItemIcon(stack, 8, 8); + + float percent = finished ? 100 : (float) progress / (float) max; + + DrawableHelper.fill(matrix, 3, 28, 156, 29, -1); + + float f = Math.min(156, ( + 156 * percent + )); + + if (!exists) { + manager.getClient().textRenderer.draw(matrix, Formatting.GREEN + I18n.translate("advancedbackups.backup_finished"), 25, 11, -11534256); + DrawableHelper.fill(matrix, 3, 28, 156, 29, -10948014); + return Visibility.HIDE; + } + + String title = "You shouldn't see this!"; + + + if (starting) { + title = Formatting.GREEN + I18n.translate("advancedbackups.backup_starting"); + } + else if (started) { + title = Formatting.GREEN + I18n.translate("advancedbackups.progress", round(percent * 100)); + } + else if (failed) { + title = Formatting.RED + I18n.translate("advancedbackups.backup_failed"); + if (!timeSet) { + time = System.currentTimeMillis(); + timeSet = true; + } + } + else if (finished) { + title = Formatting.GREEN + I18n.translate("advancedbackups.backup_finished"); + if (!timeSet) { + time = System.currentTimeMillis(); + timeSet = true; + } + } + + manager.getClient().textRenderer.draw(matrix, title, 25, 11, -11534256); + + if (timeSet && System.currentTimeMillis() >= time + 5000) { + starting = false; + started = false; + failed = false; + finished = false; + progress = 0; + max = 0; + timeSet = false; + exists = false; + return Visibility.HIDE; + } + + DrawableHelper.fill(matrix, 3, 28, Math.max(3, (int) f), 29, -10948014); + + return Visibility.SHOW; + } + + + private static String round (float value) { + return String.format("%.1f", value); + } + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java new file mode 100644 index 00000000..7b8e9237 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java @@ -0,0 +1,61 @@ +package co.uk.mommyheather.advancedbackups.client; + +import java.util.List; + +import co.uk.mommyheather.advancedbackups.AdvancedBackups; +import co.uk.mommyheather.advancedbackups.interfaces.IClientContactor; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; +import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.network.ServerPlayerEntity; + +public class ClientContactor implements IClientContactor { + + @Override + public void backupComplete() { + MinecraftServer server = AdvancedBackups.server; + List players = server.getPlayerManager().getPlayerList(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, 0, 0); + for (ServerPlayerEntity player : players) { + if (player.hasPermissionLevel(3)) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupFailed() { + MinecraftServer server = AdvancedBackups.server; + List players = server.getPlayerManager().getPlayerList(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, 0, 0); + for (ServerPlayerEntity player : players) { + if (player.hasPermissionLevel(3)) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupProgress(int progress, int max) { + MinecraftServer server = AdvancedBackups.server; + List players = server.getPlayerManager().getPlayerList(); + PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, progress, max); + for (ServerPlayerEntity player : players) { + if (player.hasPermissionLevel(3)) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupStarting() { + MinecraftServer server = AdvancedBackups.server; + List players = server.getPlayerManager().getPlayerList(); + PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, 0, 0); + for (ServerPlayerEntity player : players) { + if (player.hasPermissionLevel(3)) { + NetworkHandler.sendToClient(player, packet); + } + } + } +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java new file mode 100644 index 00000000..2e20d30d --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java @@ -0,0 +1,26 @@ +package co.uk.mommyheather.advancedbackups.network; + +import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; +import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; +import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.util.Identifier; + +public class NetworkHandler { + + public static Identifier STATUS_PACKET_ID = new Identifier("advancedbackups", "backup_status"); + + public static void init() { + ClientPlayNetworking.registerGlobalReceiver(STATUS_PACKET_ID, PacketBackupStatus::handle); + } + + + public static void sendToClient(ServerPlayerEntity player, PacketBackupStatus packet) { + + ServerPlayNetworking.send(player, STATUS_PACKET_ID, packet.write(PacketByteBufs.create())); + + } + + + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java new file mode 100644 index 00000000..c8ff2791 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java @@ -0,0 +1,83 @@ +package co.uk.mommyheather.advancedbackups.network; + +import co.uk.mommyheather.advancedbackups.client.BackupToast; +import net.fabricmc.fabric.api.networking.v1.PacketSender; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientPlayNetworkHandler; +import net.minecraft.network.PacketByteBuf; + +public class PacketBackupStatus { + + public boolean starting; + public boolean started; + public boolean failed; + public boolean finished; + + public int progress; + public int max; + + + public PacketBackupStatus(boolean starting, boolean started, boolean failed, boolean finished, int progress, + int max) { + this.starting = starting; + this.started = started; + this.failed = failed; + this.finished = finished; + this.progress = progress; + this.max = max; + } + + public PacketBackupStatus() { + + } + + public void read(PacketByteBuf buf) { + starting = buf.readBoolean(); + started = buf.readBoolean(); + failed = buf.readBoolean(); + finished = buf.readBoolean(); + + progress = buf.readInt(); + max = buf.readInt(); + } + + public PacketByteBuf write(PacketByteBuf buf) { + buf.writeBoolean(starting); + buf.writeBoolean(started); + buf.writeBoolean(failed); + buf.writeBoolean(finished); + + buf.writeInt(progress); + buf.writeInt(max); + + return buf; + + } + + + + public static void handle(MinecraftClient client, ClientPlayNetworkHandler handler, PacketByteBuf buf, PacketSender responseSender) { + + PacketBackupStatus message = new PacketBackupStatus(); + message.read(buf); + + client.execute(() -> { + BackupToast.starting = message.starting; + BackupToast.started = message.started; + BackupToast.failed = message.failed; + BackupToast.finished = message.finished; + + BackupToast.progress = message.progress; + BackupToast.max = message.max; + + if (!BackupToast.exists) { + BackupToast.exists = true; + client.getToastManager().add(new BackupToast()); + } + + }); + + + } + + } diff --git a/src/main/resources/assets/advancedbackups/lang/en_us.json b/src/main/resources/assets/advancedbackups/lang/en_us.json new file mode 100644 index 00000000..cc68dae1 --- /dev/null +++ b/src/main/resources/assets/advancedbackups/lang/en_us.json @@ -0,0 +1,6 @@ +{ + "advancedbackups.backup_starting" : "Backup starting!", + "advancedbackups.progress": "Backup ongoing: %1$s%%", + "advancedbackups.backup_failed": "Backup failed!\nCheck log for more info.", + "advancedbackups.backup_finished": "Backup complete!" +} \ No newline at end of file From 042a456b6ff94d07834e6238718b3d2f748977ac Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sun, 22 Oct 2023 22:50:26 +0100 Subject: [PATCH 348/580] Client contact, but forge 1.19 --- .../advancedbackups/AdvancedBackups.java | 4 + .../advancedbackups/client/BackupToast.java | 105 ++++++++++++++++++ .../client/ClientContactor.java | 61 ++++++++++ .../network/NetworkHandler.java | 37 ++++++ .../network/PacketBackupStatus.java | 76 +++++++++++++ .../assets/advancedbackups/lang/en_us.json | 6 + 6 files changed, 289 insertions(+) create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java create mode 100644 src/main/resources/assets/advancedbackups/lang/en_us.json diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 05933b12..78fcb797 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -2,10 +2,12 @@ import com.mojang.logging.LogUtils; +import co.uk.mommyheather.advancedbackups.client.ClientContactor; import co.uk.mommyheather.advancedbackups.core.ABCore; import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.storage.LevelResource; @@ -41,6 +43,7 @@ public AdvancedBackups() { // Register ourselves for server and other game events we are interested in MinecraftForge.EVENT_BUS.register(this); + NetworkHandler.register(); } @SubscribeEvent @@ -64,6 +67,7 @@ public void onServerStarting(ServerStartingEvent event) ABCore.warningLogger = warningLogger; ABCore.errorLogger = errorLogger; + ABCore.clientContactor = new ClientContactor(); ABCore.modJar = ModList.get().getModFileById("advancedbackups").getFile().getFilePath().toFile(); diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java new file mode 100644 index 00000000..710d549f --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java @@ -0,0 +1,105 @@ +package co.uk.mommyheather.advancedbackups.client; + +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.PoseStack; + +import net.minecraft.ChatFormatting; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.gui.components.toasts.Toast; +import net.minecraft.client.gui.components.toasts.ToastComponent; +import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.client.resources.language.I18n; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; + +public class BackupToast implements Toast { + + public static boolean starting; + public static boolean started; + public static boolean failed; + public static boolean finished; + + public static int progress; + public static int max; + + public static boolean exists = false; + + private static long time; + private static boolean timeSet = false; + + public static final ItemStack stack = new ItemStack(Items.PAPER); + + + @Override + public Visibility render(PoseStack matrix, ToastComponent toastGui, long delta) { + RenderSystem.setShader(GameRenderer::getPositionTexShader); + RenderSystem.setShaderTexture(0, TEXTURE); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + toastGui.blit(matrix, 0, 0, 0, 0, this.width(), this.height()); + toastGui.getMinecraft().getItemRenderer().renderAndDecorateFakeItem(stack, 8, 8); + + + float percent = finished ? 100 : (float) progress / (float) max; + + Gui.fill(matrix, 3, 28, 156, 29, -1); + float f = Math.min(156, ( + 156 * percent + )); + + + if (!exists) { + toastGui.getMinecraft().font.draw(matrix, ChatFormatting.GREEN + I18n.get("advancedbackups.backup_finished"), 25, 11, -11534256); + Gui.fill(matrix, 3, 28, 156, 29, -10948014); + return Visibility.HIDE; + } + + String title = "You shouldn't see this!"; + + + if (starting) { + title = ChatFormatting.GREEN + I18n.get("advancedbackups.backup_starting"); + } + else if (started) { + title = ChatFormatting.GREEN + I18n.get("advancedbackups.progress", round(percent * 100)); + } + else if (failed) { + title = ChatFormatting.RED + I18n.get("advancedbackups.backup_failed"); + if (!timeSet) { + time = System.currentTimeMillis(); + timeSet = true; + } + } + else if (finished) { + title = ChatFormatting.GREEN + I18n.get("advancedbackups.backup_finished"); + if (!timeSet) { + time = System.currentTimeMillis(); + timeSet = true; + } + } + + toastGui.getMinecraft().font.draw(matrix, title, 25, 11, -11534256); + + if (timeSet && System.currentTimeMillis() >= time + 5000) { + starting = false; + started = false; + failed = false; + finished = false; + progress = 0; + max = 0; + timeSet = false; + exists = false; + return Visibility.HIDE; + } + + Gui.fill(matrix, 3, 28, Math.max(3, (int) f), 29, -10948014); + + return Visibility.SHOW; + + } + + + private static String round (float value) { + return String.format("%.1f", value); + } + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java new file mode 100644 index 00000000..ffa8bf23 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java @@ -0,0 +1,61 @@ +package co.uk.mommyheather.advancedbackups.client; + +import java.util.List; + +import co.uk.mommyheather.advancedbackups.interfaces.IClientContactor; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; +import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerPlayer; +import net.minecraftforge.server.ServerLifecycleHooks; + +public class ClientContactor implements IClientContactor { + + @Override + public void backupComplete() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, 0, 0); + for (ServerPlayer player : players) { + if (player.hasPermissions(3)) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupFailed() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, 0, 0); + for (ServerPlayer player : players) { + if (player.hasPermissions(3)) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupProgress(int progress, int max) { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, progress, max); + for (ServerPlayer player : players) { + if (player.hasPermissions(3)) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupStarting() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, 0, 0); + for (ServerPlayer player : players) { + if (player.hasPermissions(3)) { + NetworkHandler.sendToClient(player, packet); + } + } + } +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java new file mode 100644 index 00000000..69a388a4 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java @@ -0,0 +1,37 @@ +package co.uk.mommyheather.advancedbackups.network; + +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerPlayer; +import net.minecraftforge.network.NetworkDirection; +import net.minecraftforge.network.NetworkRegistry; +import net.minecraftforge.network.simple.SimpleChannel; + +public class NetworkHandler { + + private static final String PROTOCOL_VERSION = "1"; + private static int id = 0; + private static int id() { + return id++; + } + + public static final SimpleChannel INSTANCE = NetworkRegistry.newSimpleChannel( + new ResourceLocation("advancedbackups", "main"), + () -> PROTOCOL_VERSION, + (version) -> true, + (version) -> true + ); + + + public static void register() { + INSTANCE.messageBuilder(PacketBackupStatus.class, id()) + .encoder(PacketBackupStatus::toBytes) + .decoder(buf -> new PacketBackupStatus(buf)) + .consumer(PacketBackupStatus::handle) + .add(); + } + + public static void sendToClient(ServerPlayer player, Object packet) { + INSTANCE.sendTo(packet, player.connection.connection, NetworkDirection.PLAY_TO_CLIENT); + } + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java new file mode 100644 index 00000000..a7d0f1f5 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java @@ -0,0 +1,76 @@ +package co.uk.mommyheather.advancedbackups.network; + +import java.util.function.Supplier; + +import co.uk.mommyheather.advancedbackups.client.BackupToast; +import net.minecraft.client.Minecraft; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraftforge.fml.LogicalSide; +import net.minecraftforge.network.NetworkEvent; + +public class PacketBackupStatus { + + public boolean starting; + public boolean started; + + public boolean failed; + public boolean finished; + + public int progress; + public int max; + + + public PacketBackupStatus(boolean starting, boolean started, boolean failed, boolean finished, int progress, + int max) { + this.starting = starting; + this.started = started; + this.failed = failed; + this.finished = finished; + this.progress = progress; + this.max = max; + } + + + public PacketBackupStatus(FriendlyByteBuf buf) { + starting = buf.readBoolean(); + started = buf.readBoolean(); + failed = buf.readBoolean(); + finished = buf.readBoolean(); + + progress = buf.readInt(); + max = buf.readInt(); + } + + public void toBytes(FriendlyByteBuf buf) { + buf.writeBoolean(starting); + buf.writeBoolean(started); + buf.writeBoolean(failed); + buf.writeBoolean(finished); + + buf.writeInt(progress); + buf.writeInt(max); + } + + public boolean handle(Supplier ctx) { + ctx.get().enqueueWork(() -> { + if (ctx.get().getDirection().getReceptionSide() == LogicalSide.CLIENT) { + BackupToast.starting = starting; + BackupToast.started = started; + BackupToast.failed = failed; + BackupToast.finished = finished; + + BackupToast.progress = progress; + BackupToast.max = max; + + if (!BackupToast.exists) { + BackupToast.exists = true; + Minecraft.getInstance().getToasts().addToast(new BackupToast()); + } + } + }); + ctx.get().setPacketHandled(true); + return true; + + } + +} diff --git a/src/main/resources/assets/advancedbackups/lang/en_us.json b/src/main/resources/assets/advancedbackups/lang/en_us.json new file mode 100644 index 00000000..cc68dae1 --- /dev/null +++ b/src/main/resources/assets/advancedbackups/lang/en_us.json @@ -0,0 +1,6 @@ +{ + "advancedbackups.backup_starting" : "Backup starting!", + "advancedbackups.progress": "Backup ongoing: %1$s%%", + "advancedbackups.backup_failed": "Backup failed!\nCheck log for more info.", + "advancedbackups.backup_finished": "Backup complete!" +} \ No newline at end of file From 6b14de88b68f5d5ef3f147585572c212b2a25208 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Mon, 23 Oct 2023 00:21:30 +0100 Subject: [PATCH 349/580] Client contact, but fabric 1.20! --- .../advancedbackups/AdvancedBackups.java | 7 +- .../advancedbackups/client/BackupToast.java | 100 ++++++++++++++++++ .../client/ClientContactor.java | 62 +++++++++++ .../network/NetworkHandler.java | 26 +++++ .../network/PacketBackupStatus.java | 83 +++++++++++++++ .../assets/advancedbackups/lang/en_us.json | 6 ++ 6 files changed, 283 insertions(+), 1 deletion(-) create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java create mode 100644 src/main/resources/assets/advancedbackups/lang/en_us.json diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 5809f5c2..5a3544ff 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -16,10 +16,12 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import co.uk.mommyheather.advancedbackups.client.ClientContactor; import co.uk.mommyheather.advancedbackups.core.ABCore; import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; public class AdvancedBackups implements ModInitializer { // This logger is used to write text to the console and the log file. @@ -36,6 +38,9 @@ public class AdvancedBackups implements ModInitializer { @Override public void onInitialize() { + + NetworkHandler.init(); + ServerLifecycleEvents.SERVER_STARTING.register((server) -> { AdvancedBackups.server = server; ABCore.worldName = server.getSaveProperties().getLevelName(); @@ -49,7 +54,7 @@ public void onInitialize() { ABCore.warningLogger = warningLogger; ABCore.errorLogger = errorLogger; - + ABCore.clientContactor = new ClientContactor(); ABCore.modJar = new File(FabricLoaderImpl.INSTANCE.getModContainer("advancedbackups").get().getOrigin().toString()); diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java new file mode 100644 index 00000000..92fe93fb --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java @@ -0,0 +1,100 @@ +package co.uk.mommyheather.advancedbackups.client; + +import com.mojang.blaze3d.systems.RenderSystem; + +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.render.GameRenderer; +import net.minecraft.client.resource.language.I18n; +import net.minecraft.client.toast.Toast; +import net.minecraft.client.toast.ToastManager; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.util.Formatting; + +public class BackupToast implements Toast { + + public static boolean starting; + public static boolean started; + public static boolean failed; + public static boolean finished; + + public static int progress; + public static int max; + + public static boolean exists = false; + + private static long time; + private static boolean timeSet = false; + + public static final ItemStack stack = new ItemStack(Items.PAPER); + + @Override + public Visibility draw(DrawContext context, ToastManager manager, long startTime) { + context.drawTexture(TEXTURE, 0, 0, 0, 0, this.getWidth(), this.getHeight()); + + context.drawItemWithoutEntity(stack, 8, 8);; + + float percent = finished ? 100 : (float) progress / (float) max; + + context.fill(3, 28, 156, 29, -1); + + float f = Math.min(156, ( + 156 * percent + )); + + if (!exists) { + context.drawText(manager.getClient().textRenderer, Formatting.GREEN + I18n.translate("advancedbackups.backup_finished"), 25, 11, -11534256, false); + context.fill(3, 28, 156, 29, -10948014); + return Visibility.HIDE; + } + + String title = "You shouldn't see this!"; + + + if (starting) { + title = Formatting.GREEN + I18n.translate("advancedbackups.backup_starting"); + } + else if (started) { + title = Formatting.GREEN + I18n.translate("advancedbackups.progress", round(percent * 100)); + } + else if (failed) { + title = Formatting.RED + I18n.translate("advancedbackups.backup_failed"); + if (!timeSet) { + time = System.currentTimeMillis(); + timeSet = true; + } + } + else if (finished) { + title = Formatting.GREEN + I18n.translate("advancedbackups.backup_finished"); + if (!timeSet) { + time = System.currentTimeMillis(); + timeSet = true; + } + } + + context.drawText(manager.getClient().textRenderer, title, 25, 11, -11534256, false); + + if (timeSet && System.currentTimeMillis() >= time + 5000) { + starting = false; + started = false; + failed = false; + finished = false; + progress = 0; + max = 0; + timeSet = false; + exists = false; + return Visibility.HIDE; + } + + context.fill(3, 28, Math.max(3, (int) f), 29, -10948014); + + return Visibility.SHOW; + } + + + private static String round (float value) { + return String.format("%.1f", value); + } + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java new file mode 100644 index 00000000..3bba1b9a --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java @@ -0,0 +1,62 @@ +package co.uk.mommyheather.advancedbackups.client; + +import java.util.List; + +import co.uk.mommyheather.advancedbackups.AdvancedBackups; +import co.uk.mommyheather.advancedbackups.interfaces.IClientContactor; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; +import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.network.ServerPlayerEntity; + +public class ClientContactor implements IClientContactor { + + @Override + public void backupComplete() { + MinecraftServer server = AdvancedBackups.server; + List players = server.getPlayerManager().getPlayerList(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, 0, 0); + for (ServerPlayerEntity player : players) { + if (player.hasPermissionLevel(3)) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupFailed() { + MinecraftServer server = AdvancedBackups.server; + List players = server.getPlayerManager().getPlayerList(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, 0, 0); + for (ServerPlayerEntity player : players) { + if (player.hasPermissionLevel(3)) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupProgress(int progress, int max) { + System.out.println("HI"); + MinecraftServer server = AdvancedBackups.server; + List players = server.getPlayerManager().getPlayerList(); + PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, progress, max); + for (ServerPlayerEntity player : players) { + if (player.hasPermissionLevel(3)) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupStarting() { + MinecraftServer server = AdvancedBackups.server; + List players = server.getPlayerManager().getPlayerList(); + PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, 0, 0); + for (ServerPlayerEntity player : players) { + if (player.hasPermissionLevel(3)) { + NetworkHandler.sendToClient(player, packet); + } + } + } +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java new file mode 100644 index 00000000..2e20d30d --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java @@ -0,0 +1,26 @@ +package co.uk.mommyheather.advancedbackups.network; + +import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; +import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; +import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.util.Identifier; + +public class NetworkHandler { + + public static Identifier STATUS_PACKET_ID = new Identifier("advancedbackups", "backup_status"); + + public static void init() { + ClientPlayNetworking.registerGlobalReceiver(STATUS_PACKET_ID, PacketBackupStatus::handle); + } + + + public static void sendToClient(ServerPlayerEntity player, PacketBackupStatus packet) { + + ServerPlayNetworking.send(player, STATUS_PACKET_ID, packet.write(PacketByteBufs.create())); + + } + + + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java new file mode 100644 index 00000000..c8ff2791 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java @@ -0,0 +1,83 @@ +package co.uk.mommyheather.advancedbackups.network; + +import co.uk.mommyheather.advancedbackups.client.BackupToast; +import net.fabricmc.fabric.api.networking.v1.PacketSender; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientPlayNetworkHandler; +import net.minecraft.network.PacketByteBuf; + +public class PacketBackupStatus { + + public boolean starting; + public boolean started; + public boolean failed; + public boolean finished; + + public int progress; + public int max; + + + public PacketBackupStatus(boolean starting, boolean started, boolean failed, boolean finished, int progress, + int max) { + this.starting = starting; + this.started = started; + this.failed = failed; + this.finished = finished; + this.progress = progress; + this.max = max; + } + + public PacketBackupStatus() { + + } + + public void read(PacketByteBuf buf) { + starting = buf.readBoolean(); + started = buf.readBoolean(); + failed = buf.readBoolean(); + finished = buf.readBoolean(); + + progress = buf.readInt(); + max = buf.readInt(); + } + + public PacketByteBuf write(PacketByteBuf buf) { + buf.writeBoolean(starting); + buf.writeBoolean(started); + buf.writeBoolean(failed); + buf.writeBoolean(finished); + + buf.writeInt(progress); + buf.writeInt(max); + + return buf; + + } + + + + public static void handle(MinecraftClient client, ClientPlayNetworkHandler handler, PacketByteBuf buf, PacketSender responseSender) { + + PacketBackupStatus message = new PacketBackupStatus(); + message.read(buf); + + client.execute(() -> { + BackupToast.starting = message.starting; + BackupToast.started = message.started; + BackupToast.failed = message.failed; + BackupToast.finished = message.finished; + + BackupToast.progress = message.progress; + BackupToast.max = message.max; + + if (!BackupToast.exists) { + BackupToast.exists = true; + client.getToastManager().add(new BackupToast()); + } + + }); + + + } + + } diff --git a/src/main/resources/assets/advancedbackups/lang/en_us.json b/src/main/resources/assets/advancedbackups/lang/en_us.json new file mode 100644 index 00000000..cc68dae1 --- /dev/null +++ b/src/main/resources/assets/advancedbackups/lang/en_us.json @@ -0,0 +1,6 @@ +{ + "advancedbackups.backup_starting" : "Backup starting!", + "advancedbackups.progress": "Backup ongoing: %1$s%%", + "advancedbackups.backup_failed": "Backup failed!\nCheck log for more info.", + "advancedbackups.backup_finished": "Backup complete!" +} \ No newline at end of file From 156b8cc4098fe8cd3c09faf9dceaaa5dd2d5af8c Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Mon, 23 Oct 2023 00:53:06 +0100 Subject: [PATCH 350/580] and this is forge 1.20! --- .../advancedbackups/AdvancedBackups.java | 4 + .../advancedbackups/client/BackupToast.java | 103 ++++++++++++++++++ .../client/ClientContactor.java | 61 +++++++++++ .../network/NetworkHandler.java | 37 +++++++ .../network/PacketBackupStatus.java | 76 +++++++++++++ .../assets/advancedbackups/lang/en_us.json | 6 + 6 files changed, 287 insertions(+) create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java create mode 100644 src/main/resources/assets/advancedbackups/lang/en_us.json diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index f7a412b6..e5af7713 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -2,10 +2,12 @@ import com.mojang.logging.LogUtils; +import co.uk.mommyheather.advancedbackups.client.ClientContactor; import co.uk.mommyheather.advancedbackups.core.ABCore; import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.storage.LevelResource; @@ -40,6 +42,7 @@ public AdvancedBackups() { // Register ourselves for server and other game events we are interested in MinecraftForge.EVENT_BUS.register(this); + NetworkHandler.register(); } @SubscribeEvent @@ -57,6 +60,7 @@ public void onServerStarting(ServerStartingEvent event) ABCore.warningLogger = warningLogger; ABCore.errorLogger = errorLogger; + ABCore.clientContactor = new ClientContactor(); ABCore.modJar = ModList.get().getModFileById("advancedbackups").getFile().getFilePath().toFile(); diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java new file mode 100644 index 00000000..c08baf68 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java @@ -0,0 +1,103 @@ +package co.uk.mommyheather.advancedbackups.client; + +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.PoseStack; + +import net.minecraft.ChatFormatting; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.components.toasts.Toast; +import net.minecraft.client.gui.components.toasts.ToastComponent; +import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.client.resources.language.I18n; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; + +public class BackupToast implements Toast { + + public static boolean starting; + public static boolean started; + public static boolean failed; + public static boolean finished; + + public static int progress; + public static int max; + + public static boolean exists = false; + + private static long time; + private static boolean timeSet = false; + + public static final ItemStack stack = new ItemStack(Items.PAPER); + + + @Override + public Visibility render(GuiGraphics graphics, ToastComponent toastGui, long delta) { + graphics.blit(TEXTURE, 0, 0, 0, 0, this.width(), this.height()); + graphics.renderFakeItem(stack, 8, 8); + + + float percent = finished ? 100 : (float) progress / (float) max; + + graphics.fill(3, 28, 156, 29, -1); + float f = Math.min(156, ( + 156 * percent + )); + + + if (!exists) { + graphics.drawString(toastGui.getMinecraft().font, ChatFormatting.GREEN + I18n.get("advancedbackups.backup_finished"), 25, 11, -11534256); + graphics.fill(3, 28, 156, 29, -10948014); + return Visibility.HIDE; + } + + String title = "You shouldn't see this!"; + + + if (starting) { + title = ChatFormatting.GREEN + I18n.get("advancedbackups.backup_starting"); + } + else if (started) { + title = ChatFormatting.GREEN + I18n.get("advancedbackups.progress", round(percent * 100)); + } + else if (failed) { + title = ChatFormatting.RED + I18n.get("advancedbackups.backup_failed"); + if (!timeSet) { + time = System.currentTimeMillis(); + timeSet = true; + } + } + else if (finished) { + title = ChatFormatting.GREEN + I18n.get("advancedbackups.backup_finished"); + if (!timeSet) { + time = System.currentTimeMillis(); + timeSet = true; + } + } + + graphics.drawString(toastGui.getMinecraft().font, title, 25, 11, -11534256); + + if (timeSet && System.currentTimeMillis() >= time + 5000) { + starting = false; + started = false; + failed = false; + finished = false; + progress = 0; + max = 0; + timeSet = false; + exists = false; + return Visibility.HIDE; + } + + graphics.fill(3, 28, Math.max(3, (int) f), 29, -10948014); + + return Visibility.SHOW; + + } + + + private static String round (float value) { + return String.format("%.1f", value); + } + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java new file mode 100644 index 00000000..ffa8bf23 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java @@ -0,0 +1,61 @@ +package co.uk.mommyheather.advancedbackups.client; + +import java.util.List; + +import co.uk.mommyheather.advancedbackups.interfaces.IClientContactor; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; +import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerPlayer; +import net.minecraftforge.server.ServerLifecycleHooks; + +public class ClientContactor implements IClientContactor { + + @Override + public void backupComplete() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, 0, 0); + for (ServerPlayer player : players) { + if (player.hasPermissions(3)) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupFailed() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, 0, 0); + for (ServerPlayer player : players) { + if (player.hasPermissions(3)) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupProgress(int progress, int max) { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, progress, max); + for (ServerPlayer player : players) { + if (player.hasPermissions(3)) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupStarting() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, 0, 0); + for (ServerPlayer player : players) { + if (player.hasPermissions(3)) { + NetworkHandler.sendToClient(player, packet); + } + } + } +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java new file mode 100644 index 00000000..0c856fa0 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java @@ -0,0 +1,37 @@ +package co.uk.mommyheather.advancedbackups.network; + +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerPlayer; +import net.minecraftforge.network.NetworkDirection; +import net.minecraftforge.network.NetworkRegistry; +import net.minecraftforge.network.simple.SimpleChannel; + +public class NetworkHandler { + + private static final String PROTOCOL_VERSION = "1"; + private static int id = 0; + private static int id() { + return id++; + } + + public static final SimpleChannel INSTANCE = NetworkRegistry.newSimpleChannel( + new ResourceLocation("advancedbackups", "main"), + () -> PROTOCOL_VERSION, + (version) -> true, + (version) -> true + ); + + + public static void register() { + INSTANCE.messageBuilder(PacketBackupStatus.class, id()) + .encoder(PacketBackupStatus::toBytes) + .decoder(buf -> new PacketBackupStatus(buf)) + .consumerNetworkThread(PacketBackupStatus::handle) + .add(); + } + + public static void sendToClient(ServerPlayer player, Object packet) { + INSTANCE.sendTo(packet, player.connection.connection, NetworkDirection.PLAY_TO_CLIENT); + } + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java new file mode 100644 index 00000000..a7d0f1f5 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java @@ -0,0 +1,76 @@ +package co.uk.mommyheather.advancedbackups.network; + +import java.util.function.Supplier; + +import co.uk.mommyheather.advancedbackups.client.BackupToast; +import net.minecraft.client.Minecraft; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraftforge.fml.LogicalSide; +import net.minecraftforge.network.NetworkEvent; + +public class PacketBackupStatus { + + public boolean starting; + public boolean started; + + public boolean failed; + public boolean finished; + + public int progress; + public int max; + + + public PacketBackupStatus(boolean starting, boolean started, boolean failed, boolean finished, int progress, + int max) { + this.starting = starting; + this.started = started; + this.failed = failed; + this.finished = finished; + this.progress = progress; + this.max = max; + } + + + public PacketBackupStatus(FriendlyByteBuf buf) { + starting = buf.readBoolean(); + started = buf.readBoolean(); + failed = buf.readBoolean(); + finished = buf.readBoolean(); + + progress = buf.readInt(); + max = buf.readInt(); + } + + public void toBytes(FriendlyByteBuf buf) { + buf.writeBoolean(starting); + buf.writeBoolean(started); + buf.writeBoolean(failed); + buf.writeBoolean(finished); + + buf.writeInt(progress); + buf.writeInt(max); + } + + public boolean handle(Supplier ctx) { + ctx.get().enqueueWork(() -> { + if (ctx.get().getDirection().getReceptionSide() == LogicalSide.CLIENT) { + BackupToast.starting = starting; + BackupToast.started = started; + BackupToast.failed = failed; + BackupToast.finished = finished; + + BackupToast.progress = progress; + BackupToast.max = max; + + if (!BackupToast.exists) { + BackupToast.exists = true; + Minecraft.getInstance().getToasts().addToast(new BackupToast()); + } + } + }); + ctx.get().setPacketHandled(true); + return true; + + } + +} diff --git a/src/main/resources/assets/advancedbackups/lang/en_us.json b/src/main/resources/assets/advancedbackups/lang/en_us.json new file mode 100644 index 00000000..cc68dae1 --- /dev/null +++ b/src/main/resources/assets/advancedbackups/lang/en_us.json @@ -0,0 +1,6 @@ +{ + "advancedbackups.backup_starting" : "Backup starting!", + "advancedbackups.progress": "Backup ongoing: %1$s%%", + "advancedbackups.backup_failed": "Backup failed!\nCheck log for more info.", + "advancedbackups.backup_finished": "Backup complete!" +} \ No newline at end of file From 74d18fc4b1eda983f481325b003d297cf83782c1 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Mon, 23 Oct 2023 23:44:02 +0100 Subject: [PATCH 351/580] fix error on dedicated server --- .../advancedbackups/client/ClientBridge.java | 28 +++++++++++++++++++ .../network/PacketBackupStatus.java | 20 ++----------- 2 files changed, 30 insertions(+), 18 deletions(-) create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/client/ClientBridge.java diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientBridge.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientBridge.java new file mode 100644 index 00000000..eb248361 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientBridge.java @@ -0,0 +1,28 @@ +package co.uk.mommyheather.advancedbackups.client; + +import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; +import net.minecraft.client.Minecraft; + +public class ClientBridge { + + public static void handle(PacketBackupStatus message) { + + Minecraft.getMinecraft().addScheduledTask(() -> { + BackupToast.starting = message.starting; + BackupToast.started = message.started; + BackupToast.failed = message.failed; + BackupToast.finished = message.finished; + + BackupToast.progress = message.progress; + BackupToast.max = message.max; + + if (!BackupToast.exists) { + BackupToast.exists = true; + Minecraft.getMinecraft().getToastGui().add(new BackupToast()); + } + + }); + + } + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java index 86441983..af0d22d0 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java @@ -1,8 +1,7 @@ package co.uk.mommyheather.advancedbackups.network; -import co.uk.mommyheather.advancedbackups.client.BackupToast; +import co.uk.mommyheather.advancedbackups.client.ClientBridge; import io.netty.buffer.ByteBuf; -import net.minecraft.client.Minecraft; import net.minecraftforge.fml.common.network.simpleimpl.IMessage; import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; @@ -60,22 +59,7 @@ public static class Handler implements IMessageHandler { - - BackupToast.starting = message.starting; - BackupToast.started = message.started; - BackupToast.failed = message.failed; - BackupToast.finished = message.finished; - - BackupToast.progress = message.progress; - BackupToast.max = message.max; - - if (!BackupToast.exists) { - BackupToast.exists = true; - Minecraft.getMinecraft().getToastGui().add(new BackupToast()); - } - - }); + ClientBridge.handle(message); return null; From b5d759c165acf240e73394ff989396d64febebb0 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 24 Oct 2023 00:08:13 +0100 Subject: [PATCH 352/580] drop version dependency to allow 1.16.4 compatability --- src/main/resources/META-INF/mods.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/resources/META-INF/mods.toml b/src/main/resources/META-INF/mods.toml index ce017df3..cdf61fed 100644 --- a/src/main/resources/META-INF/mods.toml +++ b/src/main/resources/META-INF/mods.toml @@ -6,7 +6,7 @@ # The name of the mod loader type to load - for regular FML @Mod mods it should be javafml modLoader="javafml" #mandatory # A version range to match for said mod loader - for regular FML @Mod it will be the forge version -loaderVersion="[36,)" #mandatory This is typically bumped every Minecraft version by Forge. See our download page for lists of versions. +loaderVersion="[34,)" #mandatory This is typically bumped every Minecraft version by Forge. See our download page for lists of versions. # The license for you mod. This is mandatory metadata and allows for easier comprehension of your redistributive properties. # Review your options at https://choosealicense.com/. All rights reserved is the default copyright stance, and is thus the default here. license="MIT" @@ -43,7 +43,7 @@ A powerful and highly configurable backup mod. Visit https://github.com/MommyHea # Does this dependency have to exist - if not, ordering below must be specified mandatory=true #mandatory # The version range of the dependency - versionRange="[36,)" #mandatory + versionRange="[34,)" #mandatory # An ordering relationship for the dependency - BEFORE or AFTER required if the relationship is not mandatory ordering="NONE" # Side this dependency is applied on - BOTH, CLIENT or SERVER @@ -53,6 +53,6 @@ A powerful and highly configurable backup mod. Visit https://github.com/MommyHea modId="minecraft" mandatory=true # This version range declares a minimum of the current minecraft version up to but not including the next major version - versionRange="[1.16.5,1.17)" + versionRange="[1.16,1.17)" ordering="NONE" side="BOTH" From 22e70186f9b7693ea3bd0d473083305a82a9c7aa Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 24 Oct 2023 00:08:22 +0100 Subject: [PATCH 353/580] fix crash on dewdicated server --- .../advancedbackups/client/ClientWrapper.java | 32 +++++++++++++++++++ .../network/PacketBackupStatus.java | 21 ++---------- 2 files changed, 34 insertions(+), 19 deletions(-) create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java new file mode 100644 index 00000000..a9fd2a4c --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java @@ -0,0 +1,32 @@ +package co.uk.mommyheather.advancedbackups.client; + +import java.util.function.Supplier; + +import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; +import net.minecraft.client.Minecraft; +import net.minecraftforge.fml.LogicalSide; +import net.minecraftforge.fml.network.NetworkEvent.Context; + +public class ClientWrapper { + + public static void handle(Supplier ctx, PacketBackupStatus packet) { + + ctx.get().enqueueWork(() -> { + if (ctx.get().getDirection().getReceptionSide() == LogicalSide.CLIENT) { + BackupToast.starting = packet.starting; + BackupToast.started = packet.started; + BackupToast.failed = packet.failed; + BackupToast.finished = packet.finished; + + BackupToast.progress = packet.progress; + BackupToast.max = packet.max; + + if (!BackupToast.exists) { + BackupToast.exists = true; + Minecraft.getInstance().getToasts().addToast(new BackupToast()); + } + } + }); + } + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java index d8db5ed2..c80a6106 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java @@ -2,10 +2,8 @@ import java.util.function.Supplier; -import co.uk.mommyheather.advancedbackups.client.BackupToast; -import net.minecraft.client.Minecraft; +import co.uk.mommyheather.advancedbackups.client.ClientWrapper; import net.minecraft.network.PacketBuffer; -import net.minecraftforge.fml.LogicalSide; import net.minecraftforge.fml.network.NetworkEvent; public class PacketBackupStatus { @@ -52,22 +50,7 @@ public void toBytes(PacketBuffer buf) { } public boolean handle(Supplier ctx) { - ctx.get().enqueueWork(() -> { - if (ctx.get().getDirection().getReceptionSide() == LogicalSide.CLIENT) { - BackupToast.starting = starting; - BackupToast.started = started; - BackupToast.failed = failed; - BackupToast.finished = finished; - - BackupToast.progress = progress; - BackupToast.max = max; - - if (!BackupToast.exists) { - BackupToast.exists = true; - Minecraft.getInstance().getToasts().addToast(new BackupToast()); - } - } - }); + ClientWrapper.handle(ctx, this); ctx.get().setPacketHandled(true); return true; From 35fe5c938f20e75056cb2577fac17b9858a133c7 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 24 Oct 2023 00:49:24 +0100 Subject: [PATCH 354/580] Fix serverside crash --- .../advancedbackups/AdvancedBackups.java | 2 -- .../advancedbackups/client/ClientWrapper.java | 36 +++++++++++++++++++ .../network/NetworkHandler.java | 7 +--- .../network/PacketBackupStatus.java | 17 ++------- src/main/resources/fabric.mod.json | 3 ++ 5 files changed, 42 insertions(+), 23 deletions(-) create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 2f6aa032..33d899c0 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -39,8 +39,6 @@ public class AdvancedBackups implements ModInitializer { @Override public void onInitialize() { - NetworkHandler.init(); - ServerLifecycleEvents.SERVER_STARTING.register((server) -> { AdvancedBackups.server = server; diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java new file mode 100644 index 00000000..2f0b4f8f --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java @@ -0,0 +1,36 @@ +package co.uk.mommyheather.advancedbackups.client; + +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; +import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; +import net.fabricmc.api.ClientModInitializer; +import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; +import net.minecraft.client.MinecraftClient; + +public class ClientWrapper implements ClientModInitializer { + + public static void handle(MinecraftClient client, PacketBackupStatus message) { + + client.execute(() -> { + BackupToast.starting = message.starting; + BackupToast.started = message.started; + BackupToast.failed = message.failed; + BackupToast.finished = message.finished; + + BackupToast.progress = message.progress; + BackupToast.max = message.max; + + if (!BackupToast.exists) { + BackupToast.exists = true; + client.getToastManager().add(new BackupToast()); + } + + }); + + } + + @Override + public void onInitializeClient() { + ClientPlayNetworking.registerGlobalReceiver(NetworkHandler.STATUS_PACKET_ID, PacketBackupStatus::handle); + + } +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java index 2e20d30d..0930a159 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java @@ -1,6 +1,5 @@ package co.uk.mommyheather.advancedbackups.network; -import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; import net.minecraft.server.network.ServerPlayerEntity; @@ -8,11 +7,7 @@ public class NetworkHandler { - public static Identifier STATUS_PACKET_ID = new Identifier("advancedbackups", "backup_status"); - - public static void init() { - ClientPlayNetworking.registerGlobalReceiver(STATUS_PACKET_ID, PacketBackupStatus::handle); - } + public static final Identifier STATUS_PACKET_ID = new Identifier("advancedbackups", "backup_status"); public static void sendToClient(ServerPlayerEntity player, PacketBackupStatus packet) { diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java index c8ff2791..a2064dde 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java @@ -1,6 +1,6 @@ package co.uk.mommyheather.advancedbackups.network; -import co.uk.mommyheather.advancedbackups.client.BackupToast; +import co.uk.mommyheather.advancedbackups.client.ClientWrapper; import net.fabricmc.fabric.api.networking.v1.PacketSender; import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.ClientPlayNetworkHandler; @@ -61,21 +61,8 @@ public static void handle(MinecraftClient client, ClientPlayNetworkHandler handl PacketBackupStatus message = new PacketBackupStatus(); message.read(buf); - client.execute(() -> { - BackupToast.starting = message.starting; - BackupToast.started = message.started; - BackupToast.failed = message.failed; - BackupToast.finished = message.finished; - - BackupToast.progress = message.progress; - BackupToast.max = message.max; - - if (!BackupToast.exists) { - BackupToast.exists = true; - client.getToastManager().add(new BackupToast()); - } + ClientWrapper.handle(client, message); - }); } diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 408a7798..b9331a07 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -16,6 +16,9 @@ "entrypoints": { "main": [ "co.uk.mommyheather.advancedbackups.AdvancedBackups" + ], + "client": [ + "co.uk.mommyheather.advancedbackups.client.ClientWrapper" ] }, "depends": { From 7ae87c01f4047f242f0f94e803d0e5fae00b4145 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 24 Oct 2023 01:24:21 +0100 Subject: [PATCH 355/580] Fix dedicated server crash --- .../advancedbackups/client/ClientWrapper.java | 23 +++++++++++++++++++ .../network/PacketBackupStatus.java | 16 ++----------- 2 files changed, 25 insertions(+), 14 deletions(-) create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java new file mode 100644 index 00000000..59709b69 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java @@ -0,0 +1,23 @@ +package co.uk.mommyheather.advancedbackups.client; + +import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; +import net.minecraft.client.Minecraft; + +public class ClientWrapper { + + public static void handle(PacketBackupStatus packet) { + BackupToast.starting = packet.starting; + BackupToast.started = packet.started; + BackupToast.failed = packet.failed; + BackupToast.finished = packet.finished; + + BackupToast.progress = packet.progress; + BackupToast.max = packet.max; + + if (!BackupToast.exists) { + BackupToast.exists = true; + Minecraft.getInstance().getToasts().addToast(new BackupToast()); + } + } + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java index a7d0f1f5..2de6fbac 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java @@ -2,8 +2,7 @@ import java.util.function.Supplier; -import co.uk.mommyheather.advancedbackups.client.BackupToast; -import net.minecraft.client.Minecraft; +import co.uk.mommyheather.advancedbackups.client.ClientWrapper; import net.minecraft.network.FriendlyByteBuf; import net.minecraftforge.fml.LogicalSide; import net.minecraftforge.network.NetworkEvent; @@ -54,18 +53,7 @@ public void toBytes(FriendlyByteBuf buf) { public boolean handle(Supplier ctx) { ctx.get().enqueueWork(() -> { if (ctx.get().getDirection().getReceptionSide() == LogicalSide.CLIENT) { - BackupToast.starting = starting; - BackupToast.started = started; - BackupToast.failed = failed; - BackupToast.finished = finished; - - BackupToast.progress = progress; - BackupToast.max = max; - - if (!BackupToast.exists) { - BackupToast.exists = true; - Minecraft.getInstance().getToasts().addToast(new BackupToast()); - } + ClientWrapper.handle(this); } }); ctx.get().setPacketHandled(true); From d79a8b673a7e4b89cab6918c4c83a05f6e4a3f57 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 24 Oct 2023 13:56:21 +0100 Subject: [PATCH 356/580] cap version at 1.19.2, we'll need a separate 1.19.4 branch --- src/main/resources/META-INF/mods.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/resources/META-INF/mods.toml b/src/main/resources/META-INF/mods.toml index e7b49321..403ff7e8 100644 --- a/src/main/resources/META-INF/mods.toml +++ b/src/main/resources/META-INF/mods.toml @@ -57,6 +57,7 @@ Config file and github contain documentation. modId="minecraft" mandatory=true # This version range declares a minimum of the current minecraft version up to but not including the next major version - versionRange="[1.19,1.20)" +# 1.19.3 is a break - as such, we can't support it with this branch, and we'll need a new one... fuck me + versionRange="[1.19,1.19.3)" ordering="NONE" side="BOTH" From 337a975a2497d82ed6fef35208a526a171887cd5 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 24 Oct 2023 14:00:37 +0100 Subject: [PATCH 357/580] fix serverside crash --- .../advancedbackups/client/ClientWrapper.java | 23 +++++++++++++++++++ .../network/PacketBackupStatus.java | 16 ++----------- 2 files changed, 25 insertions(+), 14 deletions(-) create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java new file mode 100644 index 00000000..59709b69 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java @@ -0,0 +1,23 @@ +package co.uk.mommyheather.advancedbackups.client; + +import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; +import net.minecraft.client.Minecraft; + +public class ClientWrapper { + + public static void handle(PacketBackupStatus packet) { + BackupToast.starting = packet.starting; + BackupToast.started = packet.started; + BackupToast.failed = packet.failed; + BackupToast.finished = packet.finished; + + BackupToast.progress = packet.progress; + BackupToast.max = packet.max; + + if (!BackupToast.exists) { + BackupToast.exists = true; + Minecraft.getInstance().getToasts().addToast(new BackupToast()); + } + } + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java index a7d0f1f5..2de6fbac 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java @@ -2,8 +2,7 @@ import java.util.function.Supplier; -import co.uk.mommyheather.advancedbackups.client.BackupToast; -import net.minecraft.client.Minecraft; +import co.uk.mommyheather.advancedbackups.client.ClientWrapper; import net.minecraft.network.FriendlyByteBuf; import net.minecraftforge.fml.LogicalSide; import net.minecraftforge.network.NetworkEvent; @@ -54,18 +53,7 @@ public void toBytes(FriendlyByteBuf buf) { public boolean handle(Supplier ctx) { ctx.get().enqueueWork(() -> { if (ctx.get().getDirection().getReceptionSide() == LogicalSide.CLIENT) { - BackupToast.starting = starting; - BackupToast.started = started; - BackupToast.failed = failed; - BackupToast.finished = finished; - - BackupToast.progress = progress; - BackupToast.max = max; - - if (!BackupToast.exists) { - BackupToast.exists = true; - Minecraft.getInstance().getToasts().addToast(new BackupToast()); - } + ClientWrapper.handle(this); } }); ctx.get().setPacketHandled(true); From d832542dad9b93a9ccbff9b634974a62a02a108c Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 24 Oct 2023 14:07:46 +0100 Subject: [PATCH 358/580] Adjust output jar name to reflect needing a separate jar for 1.19.3/4 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 5b712214..0ada9a94 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,4 +6,4 @@ org.gradle.daemon=false modloaderName =forge -minecraftVersion =1.19 \ No newline at end of file +minecraftVersion =1.19.2 \ No newline at end of file From d987a0be65a78b0e9bc20531af3136dbe2cc5d5b Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 24 Oct 2023 14:52:52 +0100 Subject: [PATCH 359/580] Fix crash on 1.19.3/4 --- build.gradle | 6 +++--- gradle/wrapper/gradle-wrapper.properties | 2 +- .../uk/mommyheather/advancedbackups/client/BackupToast.java | 4 ++-- src/main/resources/META-INF/mods.toml | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/build.gradle b/build.gradle index acd8118d..ab32b114 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,7 @@ plugins { id 'eclipse' id 'maven-publish' - id 'net.minecraftforge.gradle' version '5.1.+' + id 'net.minecraftforge.gradle' version '[6.0,6.2)' } @@ -27,7 +27,7 @@ minecraft { // // Use non-default mappings at your own risk. They may not always work. // Simply re-run your setup task after changing the mappings to update your workspace. - mappings channel: 'official', version: '1.19.2' + mappings channel: 'official', version: '1.19.4' // accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg') // Currently, this location cannot be changed from the default. @@ -117,7 +117,7 @@ dependencies { // Specify the version of Minecraft to use. If this is any group other than 'net.minecraft', it is assumed // that the dep is a ForgeGradle 'patcher' dependency, and its patches will be applied. // The userdev artifact is a special name and will get all sorts of transformations applied to it. - minecraft 'net.minecraftforge:forge:1.19.2-43.2.0' + minecraft 'net.minecraftforge:forge:1.19.4-45.2.4' //implementation files('dependencies/jansi-2.4.0.jar') //extraLibs files('dependencies/jansi-2.4.0.jar') diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index ae04661e..fae08049 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java index 710d549f..53125427 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java @@ -35,8 +35,8 @@ public Visibility render(PoseStack matrix, ToastComponent toastGui, long delta) RenderSystem.setShader(GameRenderer::getPositionTexShader); RenderSystem.setShaderTexture(0, TEXTURE); RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); - toastGui.blit(matrix, 0, 0, 0, 0, this.width(), this.height()); - toastGui.getMinecraft().getItemRenderer().renderAndDecorateFakeItem(stack, 8, 8); + ToastComponent.blit(matrix, 0, 0, 0, 0, this.width(), this.height()); + toastGui.getMinecraft().getItemRenderer().renderAndDecorateFakeItem(matrix, stack, 8, 8); float percent = finished ? 100 : (float) progress / (float) max; diff --git a/src/main/resources/META-INF/mods.toml b/src/main/resources/META-INF/mods.toml index 403ff7e8..acd79570 100644 --- a/src/main/resources/META-INF/mods.toml +++ b/src/main/resources/META-INF/mods.toml @@ -58,6 +58,6 @@ Config file and github contain documentation. mandatory=true # This version range declares a minimum of the current minecraft version up to but not including the next major version # 1.19.3 is a break - as such, we can't support it with this branch, and we'll need a new one... fuck me - versionRange="[1.19,1.19.3)" + versionRange="[1.19.3,1.20)" ordering="NONE" side="BOTH" From ca61df58f0c0fceb0c534850d58b0db2a582f4ce Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 24 Oct 2023 15:06:22 +0100 Subject: [PATCH 360/580] update jar output name --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 5b712214..44f431f2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,4 +6,4 @@ org.gradle.daemon=false modloaderName =forge -minecraftVersion =1.19 \ No newline at end of file +minecraftVersion =1.19.3 \ No newline at end of file From 172e09d5c8293c9a133826dad0fe3888d3606ce2 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 24 Oct 2023 15:34:08 +0100 Subject: [PATCH 361/580] Fix dedicated server crash --- .../advancedbackups/AdvancedBackups.java | 2 - .../advancedbackups/client/ClientWrapper.java | 45 +++++++++++++++++++ .../network/NetworkHandler.java | 4 -- .../network/PacketBackupStatus.java | 27 +---------- src/main/resources/fabric.mod.json | 3 ++ 5 files changed, 49 insertions(+), 32 deletions(-) create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index fea2d6bb..6cc17b4e 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -39,8 +39,6 @@ public class AdvancedBackups implements ModInitializer { @Override public void onInitialize() { - NetworkHandler.init(); - ServerLifecycleEvents.SERVER_STARTING.register((server) -> { AdvancedBackups.server = server; ABCore.worldName = server.getSaveProperties().getLevelName(); diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java new file mode 100644 index 00000000..3560bdf8 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java @@ -0,0 +1,45 @@ +package co.uk.mommyheather.advancedbackups.client; + +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; +import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; +import net.fabricmc.api.ClientModInitializer; +import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; +import net.fabricmc.fabric.api.networking.v1.PacketSender; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientPlayNetworkHandler; +import net.minecraft.network.PacketByteBuf; + +public class ClientWrapper implements ClientModInitializer { + + @Override + public void onInitializeClient() { + ClientPlayNetworking.registerGlobalReceiver(NetworkHandler.STATUS_PACKET_ID, ClientWrapper::handle); + } + + + + public static void handle(MinecraftClient client, ClientPlayNetworkHandler handler, PacketByteBuf buf, PacketSender responseSender) { + + PacketBackupStatus message = new PacketBackupStatus(); + message.read(buf); + + client.execute(() -> { + BackupToast.starting = message.starting; + BackupToast.started = message.started; + BackupToast.failed = message.failed; + BackupToast.finished = message.finished; + + BackupToast.progress = message.progress; + BackupToast.max = message.max; + + if (!BackupToast.exists) { + BackupToast.exists = true; + client.getToastManager().add(new BackupToast()); + } + + }); + + + } + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java index 2e20d30d..1a064957 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java @@ -10,10 +10,6 @@ public class NetworkHandler { public static Identifier STATUS_PACKET_ID = new Identifier("advancedbackups", "backup_status"); - public static void init() { - ClientPlayNetworking.registerGlobalReceiver(STATUS_PACKET_ID, PacketBackupStatus::handle); - } - public static void sendToClient(ServerPlayerEntity player, PacketBackupStatus packet) { diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java index c8ff2791..b4d76afb 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java @@ -54,30 +54,5 @@ public PacketByteBuf write(PacketByteBuf buf) { } - - - public static void handle(MinecraftClient client, ClientPlayNetworkHandler handler, PacketByteBuf buf, PacketSender responseSender) { - - PacketBackupStatus message = new PacketBackupStatus(); - message.read(buf); - - client.execute(() -> { - BackupToast.starting = message.starting; - BackupToast.started = message.started; - BackupToast.failed = message.failed; - BackupToast.finished = message.finished; - - BackupToast.progress = message.progress; - BackupToast.max = message.max; - if (!BackupToast.exists) { - BackupToast.exists = true; - client.getToastManager().add(new BackupToast()); - } - - }); - - - } - - } +} diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 2f55f1f9..8c190de3 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -16,6 +16,9 @@ "entrypoints": { "main": [ "co.uk.mommyheather.advancedbackups.AdvancedBackups" + ], + "client": [ + "co.uk.mommyheather.advancedbackups.client.ClientWrapper" ] }, "depends": { From 8b2ac3fb2d9d621bb84fd44522d18494a50a3b39 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 24 Oct 2023 15:47:49 +0100 Subject: [PATCH 362/580] Mark output jar as 1.19.2 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 223c6f03..1289043a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -13,7 +13,7 @@ version=2.0 maven_group=co.uk.mommyheather.advancedbackups archives_base_name=advanced-backups modloaderName =fabric -minecraftVersion =1.19 +minecraftVersion =1.19.3 # Dependencies fabric_version=0.76.1+1.19.2 From bc73b7650118cadcdee91d53fb0080917e336730 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 24 Oct 2023 16:57:16 +0100 Subject: [PATCH 363/580] fix 1.19.3 crash --- gradle.properties | 8 ++++---- .../mommyheather/advancedbackups/client/BackupToast.java | 5 ++--- .../advancedbackups/network/NetworkHandler.java | 1 - src/main/resources/fabric.mod.json | 2 +- 4 files changed, 7 insertions(+), 9 deletions(-) diff --git a/gradle.properties b/gradle.properties index 1289043a..957e4820 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,9 +4,9 @@ org.gradle.parallel=true # Fabric Properties # check these on https://fabricmc.net/develop -minecraft_version=1.19.2 -yarn_mappings=1.19.2+build.28 -loader_version=0.14.22 +minecraft_version=1.19.4 +yarn_mappings=1.19.4+build.2 +loader_version=0.14.24 # Mod Properties version=2.0 @@ -16,6 +16,6 @@ modloaderName =fabric minecraftVersion =1.19.3 # Dependencies -fabric_version=0.76.1+1.19.2 +fabric_version=0.87.1+1.19.4 diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java index 6b0c5579..8a8915ee 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java @@ -31,11 +31,10 @@ public class BackupToast implements Toast { @Override public Visibility draw(MatrixStack matrix, ToastManager manager, long startTime) { - RenderSystem.setShader(GameRenderer::getPositionTexShader); RenderSystem.setShaderTexture(0, TEXTURE); RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); - manager.drawTexture(matrix, 0, 0, 0, 0, this.getWidth(), this.getHeight()); - manager.getClient().getItemRenderer().renderGuiItemIcon(stack, 8, 8); + DrawableHelper.drawTexture(matrix, 0, 0, 0, 0, this.getWidth(), this.getHeight()); + manager.getClient().getItemRenderer().renderInGui(matrix, stack, 8, 8); float percent = finished ? 100 : (float) progress / (float) max; diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java index 1a064957..72185c57 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java @@ -1,6 +1,5 @@ package co.uk.mommyheather.advancedbackups.network; -import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; import net.minecraft.server.network.ServerPlayerEntity; diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 8c190de3..12543992 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -23,7 +23,7 @@ }, "depends": { "fabricloader": ">=0.14.22", - "minecraft": "~1.19.2", + "minecraft": ">=1.19.3", "java": ">=17", "fabric-api": "*" } From b30714b2ece08d153b863ddfb0ebc33e5fd9cc9f Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 24 Oct 2023 18:14:50 +0100 Subject: [PATCH 364/580] Fix serverside crash, change jar name (1.20.2 needs different jar) --- gradle.properties | 2 +- .../advancedbackups/AdvancedBackups.java | 2 - .../client/ClientContactor.java | 1 - .../advancedbackups/client/ClientWrapper.java | 46 +++++++++++++++++++ .../network/NetworkHandler.java | 4 -- .../network/PacketBackupStatus.java | 28 +---------- src/main/resources/fabric.mod.json | 5 +- 7 files changed, 52 insertions(+), 36 deletions(-) create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java diff --git a/gradle.properties b/gradle.properties index d170e8aa..9850ca29 100644 --- a/gradle.properties +++ b/gradle.properties @@ -14,7 +14,7 @@ mod_version=2.0 maven_group=co.uk.mommyheather.advancedbackups archives_base_name=advancedbackups modloaderName =fabric -minecraftVersion =1.20 +minecraftVersion =1.20.1 # Dependencies fabric_version=0.83.0+1.20 diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 5a3544ff..7c82168d 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -39,8 +39,6 @@ public class AdvancedBackups implements ModInitializer { @Override public void onInitialize() { - NetworkHandler.init(); - ServerLifecycleEvents.SERVER_STARTING.register((server) -> { AdvancedBackups.server = server; ABCore.worldName = server.getSaveProperties().getLevelName(); diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java index 3bba1b9a..7b8e9237 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java @@ -37,7 +37,6 @@ public void backupFailed() { @Override public void backupProgress(int progress, int max) { - System.out.println("HI"); MinecraftServer server = AdvancedBackups.server; List players = server.getPlayerManager().getPlayerList(); PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, progress, max); diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java new file mode 100644 index 00000000..462dd7b9 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java @@ -0,0 +1,46 @@ +package co.uk.mommyheather.advancedbackups.client; + +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; +import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; +import net.fabricmc.api.ClientModInitializer; +import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; +import net.fabricmc.fabric.api.networking.v1.PacketSender; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientPlayNetworkHandler; +import net.minecraft.network.PacketByteBuf; + +public class ClientWrapper implements ClientModInitializer { + + @Override + public void onInitializeClient() { + ClientPlayNetworking.registerGlobalReceiver(NetworkHandler.STATUS_PACKET_ID, ClientWrapper::handle); + } + + + + + public static void handle(MinecraftClient client, ClientPlayNetworkHandler handler, PacketByteBuf buf, PacketSender responseSender) { + + PacketBackupStatus message = new PacketBackupStatus(); + message.read(buf); + + client.execute(() -> { + BackupToast.starting = message.starting; + BackupToast.started = message.started; + BackupToast.failed = message.failed; + BackupToast.finished = message.finished; + + BackupToast.progress = message.progress; + BackupToast.max = message.max; + + if (!BackupToast.exists) { + BackupToast.exists = true; + client.getToastManager().add(new BackupToast()); + } + + }); + + + } + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java index 2e20d30d..1a064957 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java @@ -10,10 +10,6 @@ public class NetworkHandler { public static Identifier STATUS_PACKET_ID = new Identifier("advancedbackups", "backup_status"); - public static void init() { - ClientPlayNetworking.registerGlobalReceiver(STATUS_PACKET_ID, PacketBackupStatus::handle); - } - public static void sendToClient(ServerPlayerEntity player, PacketBackupStatus packet) { diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java index c8ff2791..db47da17 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java @@ -54,30 +54,4 @@ public PacketByteBuf write(PacketByteBuf buf) { } - - - public static void handle(MinecraftClient client, ClientPlayNetworkHandler handler, PacketByteBuf buf, PacketSender responseSender) { - - PacketBackupStatus message = new PacketBackupStatus(); - message.read(buf); - - client.execute(() -> { - BackupToast.starting = message.starting; - BackupToast.started = message.started; - BackupToast.failed = message.failed; - BackupToast.finished = message.finished; - - BackupToast.progress = message.progress; - BackupToast.max = message.max; - - if (!BackupToast.exists) { - BackupToast.exists = true; - client.getToastManager().add(new BackupToast()); - } - - }); - - - } - - } +} diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index c5137f53..8eb6c936 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -16,11 +16,14 @@ "entrypoints": { "main": [ "co.uk.mommyheather.advancedbackups.AdvancedBackups" + ], + "client": [ + "co.uk.mommyheather.advancedbackups.client.ClientWrapper" ] }, "depends": { "fabricloader": ">=0.14.22", - "minecraft": "~1.20", + "minecraft": ">=1.20", "java": ">=17", "fabric-api": "*" } From 677afb257ce485265cbec3be95c6d4e8def5ffb3 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 24 Oct 2023 19:08:46 +0100 Subject: [PATCH 365/580] Fix issues on 1.20.2 --- build.gradle | 2 +- gradle.properties | 11 +++++------ gradle/wrapper/gradle-wrapper.jar | Bin 62076 -> 63721 bytes gradle/wrapper/gradle-wrapper.properties | 3 ++- .../advancedbackups/client/BackupToast.java | 4 +++- src/main/resources/fabric.mod.json | 2 +- 6 files changed, 12 insertions(+), 10 deletions(-) diff --git a/build.gradle b/build.gradle index 922c32ce..914145b7 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ plugins { - id 'fabric-loom' version '1.3-SNAPSHOT' + id 'fabric-loom' version '1.4-SNAPSHOT' id 'maven-publish' } diff --git a/gradle.properties b/gradle.properties index 9850ca29..c2803258 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,9 +4,9 @@ org.gradle.parallel=true # Fabric Properties # check these on https://fabricmc.net/develop -minecraft_version=1.20 -yarn_mappings=1.20+build.1 -loader_version=0.14.22 +minecraft_version=1.20.2 +yarn_mappings=1.20.2+build.4 +loader_version=0.14.24 # Mod Properties version=2.0 @@ -14,9 +14,8 @@ mod_version=2.0 maven_group=co.uk.mommyheather.advancedbackups archives_base_name=advancedbackups modloaderName =fabric -minecraftVersion =1.20.1 +minecraftVersion =1.20.2 # Dependencies -fabric_version=0.83.0+1.20 - +fabric_version=0.90.4+1.20.2 diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index c1962a79e29d3e0ab67b14947c167a862655af9b..7f93135c49b765f8051ef9d0a6055ff8e46073d8 100644 GIT binary patch delta 37652 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 delta 36122 zcmY(qQ*@wR6Rn$$ZL4G3wr$(C^~UL#9otUFwrzE6+v#9`dz>-$8UKA=FUx=)eZ;1Or zd~{}NCcVW==2~aNQ2E z`CuaUA4}uu727iJ0V!-;H~aMz1lDHz%8n7{{yDokd(C1tmag30=jUCr9=ds!n{yYkX;R zPI2rG=1~{&b=dnRr>4*vu5rRTE1oe;EEQ3Y*7S{MD4s{600@@fZBfQS1yXYQe)_X9 zWF!2Qg61I8rPN`2OT}5|UzoQ!4e6snbv?A9W9mc#f+_Vt$C~0_8W~0&pvu-5ju15v z%*EJ{Ulk*jk>k%?Ewp$t)^fkm{Vf@BC;U(7c-Ud=NGDjib2RSXc9j^-tpSX%dHb}p zxQb&FHTA*)Kn7fGMtj)olHETj#8OzC_j4}mbanP4V7}JsC|uT!aZWMOW3kC|@e(dfZ~y~V z@_8>n(HBd{$_|}}BN~?jicz-kw^>awsjuDuMxTx{utSV9=zece)Ki2N8gV>72h}Ff zkMLQwu2KSk+Ay`5vuwI<4k-X`T zC3FKuw9J@?izpw9&^bqq9=a2_@FsD#Lefgmr$|E43L{e|teI*t2G?d(E`g*W zZT^~^P9kl*MJPDiCLrDc^KR2)Ag9EcT2FSIT6dkBp8$m8TSk z1*6X3q)^8tbec))-fX&3+Q1#KuiEEXA!WexaCcs{%q4bTM2Q2UjlI~m{i~-E^d2k0 zXQ>D8E&Qibix0q&5$xRqy}|gDp*ai+DJp zq8Kud1-4I?3o8x%yV{@)luLxxop@9I@|&;m7mgyG@4g~?MlXxjshX}|mlYX78cr&r z)9BsWSw2!z4K=&cDguESTuA-C{X~@itg`?7&M|8R%@j#UHEylhJc8(`dU(6mJ6b() zmuKPNGQwqRvB}hVTPiT@KE*7DU-<)P1j+Roo;AV|;oa{*@wajDmBdSDok;f2!3c%e zub;RSe5?GeMHYtl=#I}u-KL@&CZCg1gvqV zagwiuSfdRS)+p2mQE=mlgn9FdqPqk84M-$gzDjxTxgf!l23Uai|2TurDbe<}j*O?* zh_W-{8<^99kENpo9RX2@h=FPfDI|R%7`GIEU`3@FtX1?4y!i2F&dvUZE3uNarPP9y zK=cE#4{`On($c`!HF*gV8|hxU(lDHe@SyP1=;F7qXW zx?Ce#9GClVDCF{Y?gad8{44nVc7_Gw>P2=yw@_xKmBJj#CaDn~N{)l0hhT!U%2gXZ z4Le$?)JZHl!ZSJz;^4fQ>J0UB0=o}VQb7Vc3*Q@v^M(I>UX|eI8DvVW(mqmKSMj9r zk*UJ2Xx3@2%;e=BT)L^y&~I%h?lwyg@1An9UC{k>N097VEKJM!Ym%^H!^<;>L%e3E zCfng|NUtu1I5tBPbUOUnw=iap%-C!7oh(*XVeBMcOaP#l_=5ZZ%&-Bic7K^Jn;02NadkRB9_= z*iAA`t}BeEa6Te#g!b3zm<#Ji@V|SoOXf+rU|s*Pf3V+BtBXT|M`}^}?fA~ckflc; zj9sweaZ{<79Y3jTwB}FheMB%&o$T9V$!Y?mV+`VpHl_K(yA-VaVVl57Oc*5KSq%1t zIAJa{!am`;W+hV`s%ZNV>co36u{scvV@P$%_U6lw79BRCug1g>0Z1G zIs#tFh_f%rt5rV{Tj}ukVwSBt0}3mXf^-^RT0@F)pTfw@q)UK#8kt9K#qX@Xb{!uu zq*hW!C1ekWm`&h_gSKk>7xYJV*yO7hBf|-W$2Nwi+uSleLxhd;;&SX?19KGll^QGd;n6irTXNp+t?F*S zjFgG6Zy@?Ppzd(&OkXw}s=I;~7IpprzDI12Jg77$DVgfOt+X$LANKC#2vV*K7(Byz z1-qnezu~;n{(VPx3`tj$h;%O^H|x=%qYh_j1iXsTLk(^;b;|n+PRr1Jk^0qpnIL`L zSlVNL~27L|5I{gd~B_fTL>NQ=#$a_cJ^B)`LvJYWi(9FFt&Bqp?|BPW32O4fc3;5x` zI^vy}xkgXuI> zo9>CF1S_yn&0Ntr6NcE>OQo1X{Z;1bW0B-GXQDs3vAVF@xK|myujWGz417#qS!KfL5 zPpxv@3W&-=XcC!TvjWDEChH{%3i)$Mm4Sav1n0XA8&eLE!0`7RmLbz!|LdhA$!X4( zJOXA-BvKBq>&d3;4R_9Gz}*pTAg&Eg`r3?MHi zXrUI5nN&+xkdfB8lx7!U-eV}wE`J2T@)oyxGDEDXl6PRn;zj8n9*g-RzVQ@xF)5TA z<&a;@Yv)Z#TI;n-4Ow;7A<~S0{Vy2Sz>SZ+DIy99-}r^V8tpl>6Kv~=Ub9DO!K3bpK&6{au9}md1z?T~RI?^)L za7r#`(RZwV-!EBOfMvb%a8C?_uhm`)vo}WK5WV)Kft%D~7VZ)Fw*x$*`jY)JKB5ta z*L~PB(Tdv{4_YPc$VKfC96Sdw93^@ahN&}+T?zTyjTf*a)E}qGjji%d&F05T$EZpt z@{IioV}s~wtaHpx+7x_gL5*O%qvUk4v1mmosgG%wS;;alekSVVo%*|otc#7MtU`MP zvHc5*5w;6QX-F-aNLRnnP=@9`a!&SuoHp9SbU>TcVVmcsOZ8Rwycsh1%$w5>Hfhm& z3s?IcU@4{eMM8qtJQ;+q6)&Bu!e#=swv32Q(&x5X_f%#f!@o=*YolWHCxK z#08Csf2bzRVt$a%!PsOQiQzPrYS*6m~w~rk=hDS9x#05auP=EBFU|51{v^84U(b~9$k%k{kwzZ3-U+JHJcZd zc})&214p-AW2b9eZAM7O{|BecaiVnEILQXMcd}M+$6Z4=4bl1LoA<4tN_Ugzvgz>D z6cA6#4Z*ASiZ&8#86?pHjY4a!L{3}gV*WV$wZAMQA;kF5BJqV$sa^G^m&y6$7kc2j z<&doyu5A$oJ9!GpRsAL=))?%?Y^B>J8ptiU7_NT5;DVJNm)faxnJql)eDhXhfYAf} z?Hk%#I)iMR9zjJD#Jk;>w9TWFrhp(;5iP6jgQ6Q9;eS+f8)rMD@`=?WS^~D z`geXXA0py{t3OdJ;0Xo#blQ~`#9HC_tE(=< zOp%PdUOU)xac$Yfg;{j+zZ0hEp=bdHf~HxGP;QRo69)mxtJ1ShrrEUwaBE<`FXI7eEqh>)f29GMQt--aWV zMRDgX0`h_AUD0T;+onceaW4;``d#Dz_*j;0{3Bz=cY_eP&oL zC0i>sSk1 zXm{OlrxjOgLynpcS6IL<#{;e{NjIZ&qr>hKMo--kIR}=WaFxJP`eNe9E!K0Ui5_E# z`|VbhC34#q+<_;r1p`{?&V#dL$FTBZL3fOq&@2mF+VD2CTBa!R->>TNAvS-Qqah9x zGnZ~2MJ|1?VjBX#jVWfo!VMVfr8^o}wZ3o?oJ$eAL>|m4cs+$LHYJxQ3 zR}GRjX+~6ax8B-<*OPFGA%pU}vRXLJby8F1zQoz|5^Z7%P@2~)uW+*?zbg<-xEa1N-ipwKSYUQXqT^|7 zx_jj@>zki?DSgm(PK5dA2nG}iiur=B@*mDoUe1)K3CB-Ezd)NiVm0Pt91TD5pgjb_ zI;BXdy1YIeyy+=)nChIdA&MzCX9`JWG9|Ltn!U;Btx)@4Ry#~BQ1h7wHZ@R(%jVid z|3rI!LvRBL4STnv<#(Q#BYqHqWuxm{wRe~sqLPb7bTSc^&U?3VbMy0CTtT+$L2pfM z3cGx@H`Z3Tqe%x?y${Pv3Q92zewt-(=RRx1CN+Wqce*;MmV5T3@I*7lxm@w;`#;x+ z1VV@fMg{H^eQf+AIfr_kL>P2kN1#0Fbw{8JO!rRFF(|sDvpjkEVE_iW10{7yQwYAjm7NYU4}!Ce z%IUK&V$(mpjKk!4td#f|df~URHcG0WIG+Y@x90|S_al=Q`9{U zBo8r{_MBOC4LE7O%Iob7088&ribIFxS)eM_rlEFMk%Z)2UQbDykd~ul7M;tc-*GWR zZG{eD1bh4K#J{KyJcT);##pLkUN_M5%|1dms*l#BUDTGZTX-+FOiU^i5u4T6NV7iT z34&_xQ+d)`zrDabycvLmv5T0jS2zoRO*oaTuQ6?{nhYK%FRELruGtPWrw|fQe0XA( z@jedR^U1D=9)h(JsyEN^N5|#r$+Qr+aLTRd33iPt-!H!a`yo^tA}ff6}-b^&s&cZSzm{gJ?^(Wbmc3*YX=`$(p3z zwv6yrR@D0x?&Dh_TQB4tA^^a(G1RADxh#c{a zWf21R1*&M4uXbE)quQy+Qn0cgyb+1e9oWLnCe~O$q$7Rq$cylXJ$}vbyb~c7D59hE zkoU|TH`pToD-{R7PMV_uIRqTaFjl{49))Y6eY^l@1fVf!=;Q-YJL^OGBli+0WNo-8T$Sg{ekh|vk-4Y(z;F6 zpKfFB1L1?;ZUmgcQ52xFe5>#=#QlR6eNyF&S`ea2J9V(Ne*{WF)|UkT7vBg2P~+rl zc3tR_lwzzh`vsw7Wey=g%62X>v6DHL@Bo*BsiI#ks8gO$bw*CbtCS;;wv*uXtg z-eEN=)t)5=lR$ZP8KRDTO0U`YDA#2#vw2xCojm;4%Yw_|8{sLU-oN~WQ}fA|E?#&f z%HX~J`($%S^W_TV2AH!oD|XsauMt{=dwBF58po9OKgCzP7#R$J==peyCHM0LB36&i z_yOVYllun8uuVv3t#n&hAKhYi#;Ja?{8x)f5_y+D{NS9}9R@J%ir}#7O0KBo;ctD< zEt($PA=gGLMelrxFe*Uw>!b#aHntduwb z44HfONOoL6_JT8jHb`^qzBv#aB~Bo#WswdyWp)&18O1K!W>BGiHwYiny{U4=G5C1L z^>QJOu*54rF5Jio4CJ!NeahOaZ<=ExwX`75w>z%=-U94C%6bB)TEE?OJ}0E1NqsG zL>Vb)in&baxP?EMvWcstelgWZlXk*c{HcS+QSF2V?q`E%RI<(U>zT>cxWdQM3bAtv zp7`drrDKtu4f_7fc1g8}iN{=GQT;@GBSD9n^tcs6^d@QhC5vv^7K4&!3FU9E*8dvA zr2I5L(L?Nbk66K9p0$vKGQsyw7|B1x;jj8{EkL)TLK-qvGG*H16cf=MuIF0)ZxysT zVTD>3vc!h8;UKpTf()s`Y@^IC6UbVs`)^aDOk`%A2Qrr;{peH2|K$$8A=#i46a=Ia z5(I?v|6R8~xv>E?d&Na1^nmM?d1W5_I@q2-_$}BF79r#)Xoh(@?LM>cp?Gt)#$sFP z4HO_;FqARi2WjM9WAA8rUd%}gf&vFMgZ}KK|BUN3|H)&(=hGWppm++o853ziUhg{- zt%*V~i24Ai3<;(3f(Jr|*#|*-`Z`ZjwmTZo_FZ_1YVf zIJGivLkX`ozzD}?i$#5a!~I`inRiWR?w*3-(H!=WkCAerW|%GXfD}Dpf!eP{m`Bt> zHNQS`zeHf>FPrz0(UX$kin?qop3StUd}l$JE%-RrUrf&zq}Yx+cb}9fXnK&*mEz*N zT(WIOCb=E(={a3iyq4=$uldUFzw(ou^iPTGCF8t;e-i_8RVT+x zghn89Bl9zKx{X%{MOtQOtzIBz^3d+|Mlf5fZ)<_)U}IVibM2Rys4JWn%lG5@`3zqY zNMciXMr?|M$`R)S_>ynJ&t61Kk2vEt-3zOzgVA7}Ri+On82@N6h!T5voA5e)-_(RK z<6{0^^Z8tn4zg*1-`z@AE!+OPY$dKNb$AGV&l|pBE>}f8oXpN63LFo5bT@(S^H6VyPtUEWS~P+@YW;uwH_5s&@sf`B);L((~8& z2<(#Bh&$yweX*|`erx=~%E(xUd&D>cVBd5OGf6E5%(TA_Ns`!;BFhD;ef=dw`;HV; z(?>{k6!)D2XN!=fAX=prl&4v!RF=5T9w$r3RfqW2t&=9PzY+cy^9;J)gR&nWAVpvx zAYA_sb0mH#Fl2w6Mjig(9}wJhl$RCBdjdkhx59rm#n-dX)$aoRUdPx)@ z*s7YDnIt_Q`@_+i@#xlPb(28i=P>21p%gf(ydTKV39e3h=qBj`X-i8B%bqt2iw!{l z_=04Lu=K|ctVm8@Nfc2|FCnvV+YBr*)`$o%L^dZrPHLkyIbq*iy$vKD3E>g-@Xi8& zCQC>|RX61oawM%5F+^w=zh-nj&7dW7K|TRM{gO0DNV>e^e>-3hApIdM0u zB2gW^k^c%`n+dQdRBp_}QQCEUT)+a3N;#8nBCQfoD{9N&Pe|0^L)W!em4 zB2|Ic6B!Z03=!euNRS9mPm_Vf{4>Vng8A|mcd&BV*M~-j(-z4LDbc^mRJsRHi=K&e z;jnz)X>zt+*|<%(qqEQZhCi-6n0)wP-x0wIa?N87Dy2U;Me=!gJR(AfKyeTXL%>HM! zp?_I;Y?Mr5(uk-x1#1FD0DXQ)M-@T_$bO-x&rab24^&1&N^* zX?|0f`Zek*)9D-(JOoT}-uT~KOa;6>e~|`?SD#85OGGeWAwVEB@~BOX9~Fdqx67|A z{mC!*&pvC_=iM|?f*mG+Y(BpNwBZNcH=1)>kUZ(X+t=KwSXEv!2i8$~=nouJ5MHhV zi97w#|K@H$`)}B*cMp>8MbACp#AIIR1T3Qn8=*MVT))vb9!2wyvSh{CqdqIO`8KSx z?m?yI^>(O)3EN7bu;)-OAq~|t5$v^0VQZgFquaWTL|6VM|3}z2{7e!FAYb|hNO3*i zOA4*Kk)ls)Dh?@o{*{ew^+c++(E7jSxR|6)JI0e3)Z9RKU&1#Qn`otRs~$>A3E~A{ zvWRFu`a!+zb90HOCgbR3-)qg^a%8oh>+x`(@B_>mOjhf^Rxoa49Ib?|&cxGlFp7At zU-l)XcqcL&l?F2%V*$(pPNx67=V6_y)N9d&&sQy(q@RB)&XGIQwPIXL&W1buHS1;7 z%J(b_F-|b3fMp0PvHC@lOh=lP&JP7hB98vIS7aPYn~iarfYchN&?VoyApzkc-bPh! zkmCMe^8Rq@>*@d4b(CEx=SG)Q$-F2%X|~YFmS&*J8P~W`$pH~cUNx~u+?|qH$XAeX zFIetc(@dnozD24BV!AsyF)MC|zvN`ycx^a|n*;RsT#32^Tn?(!`1ft1xiW;OZVPK> zhQ@!qmRWV#X11=mszNo#N-bsc@~7u-;K6cwt&-xX&CK}L=^G?cJt53B;WA@?V11yq zMNt3MbP^mmxuYd&SZq`9$iAmWXBOEG4Yh={$|RA&{zm*?UaR3p@F9|?#bf}#Hu;lL zWap52<*l54E0X!4P&-+s&b2K#wrW{#+ieet?_|zxtNk#+zMtlNj*}F4WKzk`evjO< z-ZS1CJ3zn}s8e8SEL$Z9OS#3}kOYDv{iRkp8Ve);nRp#^h0j5#kw6MM+u#y0GXiUU7+yi8A&Mx@E9-<%C z;OnfBUoK%i@Ht)-aR>;KE`34C|MBe)!)?3a^FO~}O;63GK!Vc_RtE?;o^|Enrum+g zn*J!R=~{3QUhR0qy`NkYk>JzydWg8+Ijv@rOZKzIh_i7m8akSzglO*>(t`PGGd;oz zwGAf@rmmHG0)4L|alntPJe-_j7MIHtG>{GTJ~MKv5i#->80oAkc=;{5lAgg2pAZYu zQf);d82QWJ&QL?4wrzN5JA)J_FfVmW><8&LSraX#Das<+b16uaVT^0I$@Ladld3)o znm!9&p*3yQs0Tj}I5y;qU#B@VieIA!m%2FAO9B##Q#4nu<`plD49qy6s88x z5RTJf^AxMGMzR7Fw(z~@+7J~4!EDv_C7+$FfcBif>ZLxu14^%$4 zy-=~OY7waE(J0tdhRgSuC#liMA(5B)(wmpcl9m4X8_0&cFtJyn81XEv-+ zCqAryPQge)6osY{X5Qqwqg2k;`zy>Ed#qu59R`_N_COWw3gRrGR<;Ml}FCW?>Cu82m?U7 zd>hMJrN)%rd(s5oQZaQ7PNuP$MIpJwK)Y0pS8~+crS|;4VqEk52lsZN)C(0_cLQx< z<5N`aipemSM9uT%LmGJoOlP#{)WEda zpEbKkvFU(=%xXoPd>>mP8;i?M;e;$^Cu&Z))>NaVsNYpK8cX)oRkivp&Vcz-rTQd8 zCE9DMBdi`_`DqN4D28(5@}@>T3v!v-UVAVKitgI5zBD1}Lb)v%LGgG6QcF14-3%4G zUMe^5YybkpKn(^*Nc$w|{7Te{RX(?w23uG#2Fz9})L<$7=xM_g-f2YYd?#NWRjb^&>=yObBwT+JPe#C^!| z)U84Q#R2NS-a^5O!-EIW2)9^nbIM5mI@iKV7lf9Iks%;V_cNnhp=DB(-+Rt!*`o-%fYNM@ri)r3V>)Be=!mKz>1gA~)0 zWTDEYyGGup35-b8R^?Ug)2SRc4?Yq#5Fn#eIG05c5hDpSS>Edj&CuZrOjLb6$1K8_ z>P;;e`Gb~~DF4a&1~e{GCSFyP=l8vVX$`UbDBF&4?a#;{eFz7o#=V{=%O?rJ9cGM! z&^c2y?2xSF<-wlwKt*AQk%DxKixbP5wqmioR3_JxT(YazOTZtOMRV|GDm|Qb;OzW` zng%73v$K_}r`3s>_=PHYyd|m`6;PR(Q(AWC)i|u+i?C3VK_rCp+8Y*+ zHQ6;9x!ftg!6u@}qPe5OJPFg*%i0Zop2cv~bEy2{vj8b`86NGcSu@|I*tFZ7tb9@5 zln6cF*zXdmj@_^_!CfG!fxI5^2mLns!y5>-IFi5t1Gqq~7ZY9uPYB23jh-viAX+!9 zC;SnEKTDtw7ZWFz0ZwpG(-d$!{tH)4npfr9%@HiZDK?`t8q(70dY*kCkcYcTml11@ z{SMb7*Ti#)wWD-HXNbWdr#eodky0 zfY6q-46HX;v7xdb`j9`a1zDrOvscBSoIi=T_b1>TQHVNdguf=)aUNp6H4t~2l@Yh@ zbBOkk7_uL73|IEu2?M1H>v%r}SFI?*K zmn-K)nSrk9#|P*;Nu7__CXX&U>}N`a9hdL+RHlF`x2QMMoLFX8SxO{YcGNYy1r26^ z=r}%9RR7D1Xl2G>>AYAA+a>RE{xATnZX7J!uP86S!n8l3o92)HqRHX_&Yit!4e?G2 zkWRdl1XVH5MvF~o(lzoC(A<~c@O#QMTUkBXk@h`8+qW1)S8RGk=-05#i3LpxO|iDv zy2P_$9%j}xl1i`A5l`6$)%?hmJNy5t(#Q^W>Y8HXI6!-&0F}2IZ3d!!I?1V;J>%Z!4b&G&Lf|Ue4Vs z4Aw^whQ-7Ah!q#gLnP><|A~j7BKRohu~J1RZ>>ipY0q%_^iRzKNVu?@d55-rKy^XE zb6`A}sCe909yEAK-U$g?iYfWSgUI;!8G#C8FA{e3WWv#lF%Aaxq(j*`XUG)j;$8;1 z4XWzEZ34p&QQWKQKgnD`<+!QXHBVJ`gSJC92vgNERseD}TIPsLb$fB&y!g&wvX45g+lD9=bgnJcT%z9#qhv3-j zV{ULwxx4?hX;Wy4LAQDuX9f;OL)z-!=wlwITKRjt#1Z+=8j&$84%7bf_3Vza3haOwzZe; z$%97^y%2|QHiG~FqUp@Ii2$|h4XgdH`nTt8MI(eof7p6kGXG%dsQxSNhOKw~jy&wJ zt$?n0ma3i$vJO&Ld|A3zwfH0*q^VsYIN0(=h%eW-`?J2?&C!j+reyyZ+doS+<}^FK z?lJ4rux+IevIazAO(&3%AMjOI!?)r4D%^o6?&J{(qj;gfgw88~;_Z-41Gyqvg>Qkhgz|}^rDtzMV;{^beu=w#GLNR>K|Gjk^-S>!a;iG| z3vpr`j3caeM55Uf1G(L-8H;2@O&mZIN#da(Hq8gLttnLzeQYzn_FQ(hQaVW)w1p z;y>kylQ8UvXr{18rC4>YpI8s=xIe0mUG#z(*o=5rSTI(YuU8I)?fR12(7(fDy%5s& zG>iR^Vqc*$oj|8q;7en~qveFEUgs&q*T^i3^v_X}+}G%`kP{Kz#+KJeI7w-ch$-T4 zKdJ42-TF5XUpgu4$4as!-y z(z>CT2XGguGK^PD}pjD>m#xS%=v^J z^1xaHIHWp_8O>Gy`WEFj<8}1W_#>(n7Nb2&VjE|OJ-NRpv8gG7e|Kt+=6$aCI3R0;_{BiV5TO^vp(JTXyS4fJ7lb?w#%Su&Zv|)^?j4JS<$zGb2qbnldJ-b<&I+-XjR}({B7wI)70|kEtxhL$lR-kh9#G4@R>PGLDmcXr&&QYX{{aPZ|J;1g{mFA(}_- zT?~%9C-<@+15r=<*a}~=k;`KI*Y8XLeO4=NH&?I30Yg>+KUMGeEM41nz`Km*Yl_jg zQbq>-;o+FsuU)7OhT_!)CO5|UjBm_8LJM+8>-I1{QndGyPi|SS6Js+LVl^XI8Du`_ z?z|WuuIt6V)|0w&lMaECAuittL#L_ZJGrP)yr%Mr7Chz;@JiJ6=NnuLU6>b&Mfjl; z^EoI5tMaCIM{O}l=Dc(t@G?~4c;l|Hx}pZfIjQRa*&j2}zx$>RjWGpWuO>*-OXf5+ zf7YQL{gt%ix0}5g)(M~P&{+*m!rB`b1ibHvs}<{tnCO)y)!PBeOJN0SQJcX`6?YE9 zN}qMO4#lov?7wRf)<>{(RIyl&&aO0hBt!(Dz*9)+C^)4BE38*ab2 zg}L$!_5PxsKcOmm)|!ATnzzVdahO4DyqC&hiBK(@+8d&7jP6l;OXX8-I=Iz=8dp|h z5~3vNPl?|X2nVIj#7R=U?|OACt@T&Y{G%SHN-+~qyrXZd@fYW6zJcC@8J5r-9PeI5{R~WP))G6h_7d zA!21M@0A`(Q5+q~$|Y(({(GeOtTgK@@)gN#u+Yue<*#bTP5k*8!8$nBlyG!Ldwlzj z=g%VG>+^s-@Zq&KkS`cC?f?xfPlwBKU*rcCvwC3AEbw@i6gKIT*TPivX+f_ye}AHr z-gp}pR;ANpvDXpi4aZ4Ghwg-Ch`39;xlme1?`K*#GzW-Fs7y0sAD~Ubx4(IbGF>u` zOVM%IT#$J8t%@#im9z~En&(Q%v0t7NN%*bH!rps=ODgW*soit)i~n0Mn( zyweQ^0V#r*WDH_7>jsDH9RU_ykD-D`!ed1?N*a+dm5peQRnU|ZA2|js{SEuSZyXIMY8BSY8oJ}$EI(nG*_<~u{mp$s9zhpt)D~yu8 zOO-nI{>y%~CBT0_H2V1KVa||HZWg_U6d;3WVy$^H2;?sl{V7n`EU1b&ShDQEtMp6x zFO(B%8Bdy~kwpuNBbGle_7~bnRPy9!*hkdfZ_oK}(BqwL$3tT?<(GNH4*PvJW$cS6 z0g+7Brg-z7OYr`=F;Ala3YEXs6Sn;}CJU~RI#g`T=iI}WPARun6!^0^cE&r1kbq}B z0A+Elc^G5qdpb%*J9modgc;!!XO`yzbK1+kK5SMQEiEYD==_^PC?1HIV)Ql31_NIa z+x9x@m1`6+56-->BYYB~kN-w6h)R#|9*0sXVXA+XUG${4V)8B62<9pWjX*Ss{+s2$ zK>yl*QETC3<#fViA72(AOI}J;q+kwI#|AnjUjuz%rA3I1Ek%avmqreGyL^kjhjU}l z7lQw71*88wWf^0S+kXm)+`m%RPuq{DLRJsH7t{bZST2I(@pjIaP1l~A&Xdb6%UQq= zbeI0W%xdI|&RjUN@krSCnb}N)v+$^R*H2;Cw4n)e0!=2AezH=4?U3CspEL?dG%b}# zkOwv$^SCk`2Vs?MiY3&pRp*FMRCE5Ra=p@0!!B3S1B)yAYt9|0;T(X7qBQpo+ZB#Iyr{)v{6ba&lDC)eT%8C}7kU zH?*#f!cP)Ujxr;6?Y$ zi_a&~Ffq>g9<2)^Y&tvONv9=}td>Ri zv_M4oF`>akdA%c!i}i8AJ{|lnEI9NOyWh0G05R@?bt<@xDV|MvuZ0lv~L4 zd>WwGZiSx5!oIO@|7MRf?}@mFdz5qZbwZeb)!OcmhgE<7__>5`+9ijzWx?p<*EciC4>}7K znw)*nrno9W;*O;X2a@NK8d7fjzmdCiOIj-QAsE0YFfeP&d0H< zz5WsD4TnHp*#cki3?2x?fl?Yp`uZXG8o76A|5tiJAu7l1C41{6oBxE{@gwU3Rwt?JS>Tlt@#k8@vbdcRs@!!paHfl=ZN zn%js!DLBiNe*R02kvSC3L7L?eonBI5wMQ>`J6NmHnq1jU-k1?)R>jAZxmqN@TYI*< zl^algSS>lwExpx`4>EMeKf|z7u8|oyCp8bWN2kF)NjSkptV;y6u7NQ_?^y}ec`(+6D~F>&<>SP7w*to*_faM3aaVTc>X7(#dt9T;kF*tI%waeL zjre)Sai)ZDJeb_6PWqz=aps$5r?#^nD$@LGz6(z@;L{t=3dbU9M?=k8wfav zmK$CWN3KHbT;MBeO%$WjWH=4qbw9D=u5;&FnCB9u!bK}*sY!eJxw3Ul~u&_8V57}4_D_H+X=8h``UK9wQbwBZQE}DTidp6+qT_px3=xK_r9CFIMh3UYvn}Dk7B#j) zM@$7Kr$>E$xF*FTk}2Mlfc*}vZ4O)DAhpCOXo6|6dwY!h58JBRVV*H&+Tyc(-ByVI%myd<%f}t48z{XjI!^ zsf53X#{T%D2x)4V#JQ&#Y|jhTy2cG8bcLb90w(xtjdy+ z>}L$jH+15JVt>`?$d)NO@grTg2ntD-Q?aCS@G?$C>Ddod^9iHdqwUW(Xj~8{t~Dd0 z6a>+ThPfrI?LV_s8?rEbnKVwRb-f^t5PP{Wef{)-9OVsBhkepB+cY%|gjYOu!m-mmB&*_d6-xHpbt+b@q&6_-*gz(h+x%-M>fd5HB-02Jc^e7W! zL;(8iLwptXFv|vTceV%-r2PFaN}l%bO`8-ieoSI>Y>@G3SVgop0q}8C7?` zNR(GW7{(njV$V<%V8lHGYf`QDc3wx9DwLW@HL5@yt_9yaOX1}fMV~s91x>&7J_BES zc1n-*8yyw>7DoT9fa8re<$_mtu4=eo1*B1X4Rnm)z49z&=)lP%JaI8$>(fgT(lj0bhM)R7C{@(`Uc;5U5=C_c`yeTt9jPW3$o zFrR{D^P0$4x7v{%{ySM--90#r0j1!UTCb#;UO^h#&fXsXwZ;aL2OK4D`EC59P>M%o zx6D!e;yE<$?bTW;RPIGI!v9zql$4A2D zC3UtoW~)nQD~rdcv#qVIwWS3jGwa`9J4AZ>icoVqAiW~Lp{%5&!^S7y&4xwLY*@9q zqRK^2!-cTE$BOUO5sHSTLnL89Xy8`LF5%Sh%24$N5xd2w@O?ZSxyCLj%TQ{dQ-pvW z2|nG9y|BTMbXt{{S?cy&_r*6m*U`nvmf(139k>u1Z8OK5ip(BDq~+=zD*hgHV4&W9 zw8-!;VEXcpS`r&4_Tq1z$idJK3Y0%9c)0AuPN;=-Frh)_peiOCXpMQ}Pe)l9*>VZ~ zBDeT(zwqw%@Wh*Sc9EHbBS`$bEt~M+BU|8IGev|Xz3){gLFVLs3}&^#ZJOSR_x>o_ z8zz=wrkPQ)^e7qdPk_+3JD~;qwQlWYX=1{V1Tfz6l3=f;9rxl@hM^Mrf{CX(KgW=w ztL9yN%j$SsuUkE4JS7ngu7&`s+-!xo+_Q%;sJ$|WFj!a%Fa;>ASJb923Ib$Fv!O~jk7ug z8ckAA{~Xc^8XBxGznI_QVy-0*ddGOvu5&D)PP*XuHzo$ddcG^$aK_bZ+jtTN0$R<( z@L5tBY!F^1_FKwnCG4hF3eXU7O5G?o?bAh&(>>)O^p~-q0<>#dAbn@z$E9>fw8fh~ z2zUS@Ga&Bf7R_35p@ASa<`C+op``nfaH4IG)UxJg+3|WhS=+xSYR#yHCeEV5T$fIz ztoE0;S0^!atm$dD2;IQa3Uhw50(Pn|OgR~6D5t!FB>LHZ?fEYtU}(a2rBO>clo(!1 zPM>$)lQhWw&9vN&w;XwYN1}&K&GzS3k(>QYJtrgAcFt%p%$jDc?z~`z6H@Cj6y;iekBGRsGi@W#=(W|tV#rn;<3#h)M^Q{`q z+uKSnJ)u0o*_~~(`qX+?Jm49=l>f%XS)dx8KUIH^7H?Z#JZbJvStk2-Yh4LT<8u#EK^hd}k!Dkg8Q&gPSLHTwO~JPb|Vl6NwUjel^CDPhnA2Ou!#7>yb1egY7# z6hD-Y&K&h*BsJ+ImBJSM5oBe)TzeJcrw&a+3i$@c<36i<$Xd<$W^Q7a#sQ95x&0r!+pmmmzi}P_aTFml&&D=oQvE!SWWR ztG}I&oYgzezxM9s^#iAG)`9R1w!lV|a*cKJzTnQuAJspV9smQC4*jNa(DrJ#1z?$@ zm&~DTj1=}5X6}-sXkw-Oj2#vDOCSv3`$M-v!}g8*!wJjalJ#dIQ-^1n;Cc?%O zxc8me(piz^>CCD%M{;ID(%#>!X(MVvn#+x8`mTr2Gy3Thcs!5h4m8iOTgiY(mX3+{nb8E%RX2FD7@<;t~Glr->}0(ozdSAGtO+m zl^02ttRAh@!=G;K@1&)mpo?CikA9oN7(G7%9AT@(>>lJ1^BhTf*Vw4^oKC154U?U& zDmuY5!2lO4)ae+3Tws#1IP)zg?%7!Mk*)^YBUDcP0YI6NH#*8Eh6<7`wMa8t-Kn;yrzThd2K^G2!oU!G(yC14v}P>HU!;93-WP4+ zE*|5K?kV-9vK52HOO3j8Ctb1X7`PAz<*&`Gs8<1Q+VUC;Kh4xgmE-5ePJH-|0W?aa zof_i>0fb?roa>X4UN=-cL{;qQHHo21`K$&R?s=Jpn!8|!<-{-2LnvYp={ijvPmGTqFMbh!Pp zy{LQ3HSIjq1}U|Tb}`0U+31bVRY*@tr@S4r&j46zVp=R4IS)pt2VF!$Nu@W5c4~Vm z^?jgo8QxXa;H}}SC5mn)c3UKmu4hr?wQya@C2F_hkM;Bb5Mkuu@+tQ=^`^a)_qI9ux#v7wezQZ_DiR6HmuyI4@Xz`h-6z-qIW*J=fIM&g*V8&6V!>BZ4xncIe%^lc=RP;dovS`$ECQ&t>!-<34hY`dI(YFlBcOaK*5b zeIJF%ek;ImcQc4Hr#Kx2)D?C;;z^*sH7+ObTc)P!toCFy$s-%9`}~H*10{RR}}JA&5F-YYx9`qK9u*@MOA;}GvIn~=V0B2_(bAR z?G!pB7q`sWnffugMOm_lmkSSntl$zptR>*bKZPybgccsdTfPYvFeStFo8$;6wFrvARZ5EO*N^=8N#lmMcH>j@%&N_A zntg{O^rFL>a$eCT8bBrDLNrX?1JX?OZ3hCfMzoTZgV_q@47X?#jd>?x0^+#KVm3pe zZ!}$gFGAB(e13}gJjC#vxVEgFs@zpG7(0q`OLUD!Ua|UZ^B}VwYp52&%FlPVIAdThp%9kL|V|40^w?_2hWKjt?%frhB z4U9DGQCt1L6E=q}8*uVfY&6yMGwWj&8;nf@BV_MR1~4oEmnh$nTj5_}Vi6FkLWtfC zt2x_QfwsQwh)p7@dcfv@SqhC>f4ea%8xYjVReX4>r9JAuyCs zoH2V|96j2-qn+NA<>fQ?#7#c7^}mBtFG9Mq`AM$*PWsXnT63cN#{`~=>q~LmQFms{ ziJPI|yK?Y~4X;FnV}U0hxT0~XgCD`3{R&U_1vsLVIv5`V3v`|8u4kMS34d!y5cy{aveFg5X^uuPFWv;)5#bR7aA+UB`A@%hE|BEqBJDSPMa{02la za>;`q5UQ0cMhM%%;Ax!7h3qJw+J)>SWVnQ{M@SM#P|AjkpjWp;@QYgYmwVku=L7QO zKWzu+I$qCkO8N&{na}zpL=p@YYKNhN8Esk=#fI70|L$bCV(rQ$Qo~j;AA`IX) zxQs1`I3j)&N`GPfd(XM!d!vXWRWucV09a=)%0s)v zTm!=M&XqdnBk@SXT=}ypR9-;yp9q&fkT|`9%?rZcm25SN=1YB2LRE2WBug3~-l=d& z5z90d=S;mZeMPkTia<2o#ijG60v`FlwihYFE*rgIms|OSFk3Xdp1`hdpSkq&0pDQQ zcxpSq4fw9ce=cqjz=5h=)LEW`pf|NnP+Bmu2J|ILJTwA@1=rtD;0cB&!a2DT{T5FS zb=TeGt!kshzJq)24Ikyo;f>CPZM?{OQ)8*~v4!81ln~8Hq}Bw#oALu(keT(6oS-T` zq=Qe@pyUhc9tr|B`d?|@ZMGFf0A&lihR0y0>?r-a1A!v*4d7icDT^I zgA(>qXYUvl8jpLD#6OZhVE7@SG*k|_hj@!I$bx-nOi1`)FPtibK%{6A{$hQtd~eXz z!Ax1EHPMsW&~nXFX0#ob<=o;A2@(p8d{At49qsf&<}F7;kb4eyK~w~dfXueEgv!`~ zJbfW)zZ6jvsSkM->0I)&UAS$t$GOJ0>@dg=LKO(OfYK?%(o7(lO#Lud2Sb0{XHQh6M-1t)EmvR^*-ov_q1AC# z$!~_m!H4+mA2sV@9PrcKVsZ5)^LLL8+Lj{p55#HRb_=dA3iE5@l<%nTEp}VFUSi@B zQLE5xly=6V8K(sYvOV5+0YpK#;GUrXDe7k`Xc|aAeC|euxab2U zo+xBSS^?m3qWcMilEXlSQ$(5R)3f|(2}b5DEHs(vAH6rl)rT&jq!9}!>?~bD4W9o+fWk&CKfIY3;uvsqOloL=Gxp= zQ{&l{Cap7a@}ZWx`MNnKy4{o7ns z!j%>QqExkUEj88A=ApKJON;r5n*rCvNBr0Zi+YpNlgnCvauV#f)pV* zJDmOXx&qYfZ)F-BUtaq9np5jUoUPgH=?r!4#9G{1tMnna0Le0zqCJR%98amCsrHIJ zbcj0UE4J?1J^1c_5j5R3fAQdN_W9s%4nV;PtY4uBY+i#q1V$`i_}6a1dsS~!LhJ4T zF`*7lDuzA_Q4d^O92Q5;s~hB0p3ymfI<)%~^QvXL`fJr5=;z;m>j}5@mHTdRIDdZM ztBMSzbTWKcnL<6Pc9*2wtWDa-4Zlv-%t-=NPk;t%6`=?gERH5~;V#Be1KqZ)0%F&D z#$Ke+s1*WRdQlU>o=2!-qM5}GH@TMpMaWXv9^1bHx-cg?&qDm|Nd^}*$`ufhKPU#dj1j3&e)0$vBJ)}zK2!q#3$;i9|8c%14 zp3Scq=I(V={99AgEF{2>{Vir&adWiw?jC8Jx7p6zB2uz!b>0+hN<5hwhj6vVaEM{A z%{^Bn4sny_WeI+L5Y7jlzkB141J%@oq>MV(FPb8#XKp@Tp%oZVppdSJbupd&Ub_nXaq~mYrPgXy|+)*Tmgkfymenw?1 zA&8UH73sw-me3ofSOTViJjMuv2ovPAz{?S2vJO1Xz#<|18;pCbp?}HEY-pr^)HwO% zA7{cpqhMjs!1(|sLjqU=CGcJ#izK(Eehg+`6^s``ejV~Fcf9z$dJUf1<{-l@ZWV==HLKdq zZWqEezna+sl*MeSR$HxW{#;tyy!gFow^;Z7bll8{Lj-@H$8Ept=*{v?{m{O|&h>qi zP=s41v@Xbyb!%rrSmE?6PsnlC0i2Nf?u*lOebwcT#P1F2L$N}#1(3T83SaPO7b5Irj*hZaSP0TJiE4Phqw zu`Yu{LHaubJbc|#GErWV?7gBVGJL)nNFCcl8lDxi=Y7n1`Ufv3OAN1|i@Ha9RV5!d zhz2w+0;hWy_ix@ibOaodE=6H4o@WNWNwXY26>_hy8~{mg`-HagZol=ZwtG8$m^Lx&Pu&-u->q8%yII ze~!RK3BP?}9Hi;WiRpe2zQ5#2n4ACbP@K1CUo`&hA`n17lfl!A8K87BcF1*EB80#2 zmY?Px@s2q0AhT$@@>ZYLHytPQ5S&JTLWD?gcblZ|AK8~UrtqKv2+6DSdd2qQr^(_i zdsypf)T~>!^v7*cCg;?6f$uc8+|@r z$zo@(bLcV@`5J8j$coWnLb!uj3kNtF$Vm`mz`d+6#n^;H^*9>45VBf&ze37-k8Qrg zV$kV@wmp+0S)Cj1n?wG~Av{D7dw-wCT53*}tgb6%z&M4@VB;|fuw0H_X)YIve|i*k z4;4ueL|mHIMa}wkrOCPi*j~ZIiH7t@w+SR_>h0Q! z9@7Ec`@LU7ju}#FLJ!3CGHJ+}t~uiBzu|Pq-Aj5i^ZYp@I~yt)H^Ev!hQ+=G0oggd zJ_-ae!kcg{Xz4Q`a~rMkMOSdqg`jC+|4p3D!s#atIsIkSl)@I3L!#n zU^2;_6%h59TKFR?v!jybGFCl^(8;)f6abaSHdn$WQ-#P>jEg8>sRTgI1{hh3;O1Cq$^w+D?c|ZgH6Gq& z2a|jN)A1RM=s7V7mQfu;VDZKv!Ho^7xO{;WBnfN{ghQHihN!9(W<0lwtY^dDMaQ+% zJ0@y5vjVGc6i9U(C>QK&;U%$T`Y3?Gb+C}rm;lYZjQVE1ct*%VDN`*yvGhegEMd=a z#@Fnkk!drDP}KIWkg(DqC{#@NjDfF>i8>Qdx*Wc?=A zB}Jvn_Hg0(pHDHdegs0$cDnx+GZoz2MF!UW6^2L=|KZ(LmI!z{;Bi_ZKkE zuF+^m-AebljGy;xX`LAO0s;Dt&fT%D)48j6R3ni&YFWeA&a|0<#@>^aQBt4oLJuXKv z&6$5?3m0Nz-4N}43J&ss_JK_l0s_PcXtTdqayqnORv-*N@Q!YP(He*GiZUzi_f_oh z7KrgRFHLHBHVe78VIe+&Y74~W;vYnJ6LLqDZoBFVw_I?Wa-gs>Z293(WhE8>4aImk zb;Do%)VN=Y#*<~FNMs$Fc?%31O68SsOk6?sDxQx0vL#Moo4ZuQ4Sy3&ar1ank$LLq zC*`coMjABJJYOrCk~TqV3^1te8JR)FN9gnwex)`l&DsY7_%e@pta!e@zai zb2aFe;AYDRupialGld)$bs+dA`@p`ED!a`VE+F`1Y$$~E3T($b6H^w`InzQ$pU(`hQ3j_C zhg*Tyyv0v~?M;H{k0IorSV7A514vA3=@zK3y5eqj$G;sbPAS*$-)*PY@CnCC{-~}iyg_6Z=}ycFf%U3|t4 z+}u+Zy0+9N6g1pk3}DXB9Z@UC+&r;~Ch}mVV#IHkSs<78)tXl_ zpJsRFRdVO`og0p=LA(!@3I#UwE$B%(!fWi_(l;UhMeN4Vn6SGY@=1Vm&maq{1#ed} z)6{z*?D}gH&aM| zX-r5is?zx3QVnwCrJW(vSFnq->06WC0cc9r9QOvvjv=XWfp_Om&$R zG=%c}WAxr7%W|mz22r?={hc!)3UIU11YcYKEwDf!na>3HdT_=cIesf@fWjaT{X{a7 zd~P(BOTn|LymC5SytjXK@gOCS3~KQ)jSxTrwZTqLzPdd6-qAD#s+1arI4}mQqOHal z_{<=yCrB}_>0{N$kq_Krpg_fL>{KzoY_(a^HbaWPTdN9mp8j2{hNWGiZf3cnEw?DA z##kLU0wMxX{>I(}amozQ?if%3JKw1_Tt{dvH;Gm2GTUR*`t0ibfF!0I#+^!|XKNOt zcDIUxw~Gj!GXpU)h@~Eg)!KBvV$J9yj+#?di>N2!Mk*^e%k=u(S6n-Xvnz4$ET~Bw z*T_W>Ew>H$HnqBlE49&y@M`fFjg{=?jz&>hn`Hzvv$S~Y>DXDqYZn!;S=lglFHuv% zU(wpt6tLM`C_*Jq>KmWv(W_Oap!sEY87JnhEpdIf zVUYwdbyvZgfu>R-aSrp!4ze+4o~%}c9V6tLvd2beTpHFjtKt^QZ*)#!MmA}~- z#7v$Mct4*07vo{t`PcON>$_^IrLc%o%_0}A=`4$#;kbnUw|ws_pE#8-^GF?!VP40% zi#`~o4AENuHD@fDHBNuzU-Aq5Vd-4wNIq%6WwcLngc+BE{PsXQSvLi;)F^9PJ$2bs zCGHxKNkws7tJZ^EX)H${DW+eCdob275aPO#tXPK&D4$86-Bd$AC+}207m6PIj$Iq2 zGFJ@`N|Z4dZ3LMT2c9R-{IzW~SmNhYJhu`z)>FT+?ufJ@{o*-cZJYZY5!{Mi8hmH~ zJh?0|OFC?+uAj2jv7Z<-*mwq(n{`$P?DsWXl|-wY3ZZ187#0 zZSVH6nJDvwpLESz#Q5eTnXZ(Ui@h)4p!g33j5z6#{?ZgqETkkKmIF>WdFWxKwwck> zuMw=qEqSnGx3hywX0F-XTon}xe_M}#Aq|332<3q2cB-WlY4IwO1TbM?!p%tU7Lowe zkaCAW)e*XY0Y;ee^-e)r`1>OJ8Rozex>;vri;?sV3i`;cZmbfW&vKyn<-=7#HSG!# zbjZA&-pEmgF&>Xx>QOuKbQ0_c+bWw8QN2qu)Z2ikN#kc2Jt$wl5isi}5|qSX`K(AP zhdlL^(?tohk?tc!v_++WUr5;v92lz2aMTzL$An}_5=*1PbI*P9HiuN>?qrhiZo14w zbRar<*nOvyJGqp<#TZhR1{yX%b~Sy&>;~!l4VVVXwmuF?wk%gMSMtsTTeh)PH{JeR z@@prHNwEyKo2(I)i-oX&yF=nQJKM)IkwPT+MYb2`9kc-fXijunnb0K^Emm5Yaia8K zYEa{O<^W7|e^qkY7A6C9o~(5;E!-Ahz9wkhv1rbTlnB#KLb{d;o~R2*e5y~`-Uh|g zN_*^OB^=!*UNt=@x@f%Dymh`3MPs*OPf?^mK07S(In_7rL^Qzp6L+Iv?whvvq4IdP z{9;iqN#A{|PwJt6{zk}GoQt?b;)!8$UDQl)1?=0Cr+YZ;V*dukHHDZ|)ikarITsWE zjpa2-gJ0BrKRGt8qyGfJIwDZy@x{MV{TCq^n<8UHoCATcJ}+BYqEa5)`#Zroirg;& zpG4VV5VeY9Pg=!cFb%Y4h&2$uz@OlVYEp(Kbi$JEhxq8gOjl=xF{aL~Fh}u1xNPi% zTNXU$h(B#kON&W3WJvXq6#Yh_fdg6?xklKBJf_UMz8!~_gL)O9uJx-}Q%4%|3@P1l z0puM84B`o>Jh!WO;LmOx+>1^+?Y3QqjQ}mV&b@As2F7FW-~T5A<>S@4far`S04LHbxh4 zubmPn?vRWJJd67+(_6|J;y8ISZuARQg%*Z#=wWU-fDS}yAGoPG&aIgD#62i~;LPxE z1*rQ?gr#mkv3USDfvUD@>hi^>_K6Yobv16Ovk#0uO=GDlNGXUs)*GW*fU;YeW}A61 z#&W0MwUM@F)s#ts!mhzZ!w#>6bxyy#{$jq2VD&j69eNgh6BOdo{WNx2fyR6jG27$^ zkrt47v~VJ&EV%;av=?-7OkqkHc%XLw_WgI&-v|xBl9u9)cPB!XhsjrrX45Yk`{0Zh z!xcHkyBSvwKd4xzC}wvaIG!|i8WQdXZzeyT4hf)!zh>_UaPHXI*IeFWVu2LOK%Rr{ z9A2oDmYOc%y|B~>X6r}AF~%l(*!LmDbaXE25oCQFFg#o=VI>;TZ+`Cqc;fnCOdHR- zN0u#skJIc{*^!!N-y_$C4Qkeu=Z}UJIHc?ZoN8`oLFm5_ByO$T79eS&1Y)~-r#+zU zUs!|t`kSI2ix}^o)Rf+Pm~#t==$mtLR7cy%8rfC8LMoNxBsE%Poj-7N=~=d;)DF zzZ5ok_6O_E9;4clP5X-1>_B^sElTL`nj@Rb)Yfxb$&aiOf6Z>k`>i&gb@sxi`sjN`zGUdHQ3dzvFuPA>rR4F@7`JiHyP#T9mrzXh`qS zzo*!B)AJP12yMQ#z*rHNg(2m(0#{-ujFEWExSzM{fb$k+MQS4`+e{f*Ux?D{@1AR_ zX$l%VFLPU1zQorl%eES=M0ZL2DDAlbxXs~~xIV-Iu!pTTBt@%a4E$@z;mZr=G=&&v zqiXw=-uwQQRK*LGC~NyP2#ex0Kz7bMGH?7A1A#`H-6JQ-wOl&2PItWvX{JSsUxxM| zST$+|#wFg`)|=6T!TC@eXpF!WT}Tr?FxlP^+n)4jiV*0u;?KGWSj+of7WcpLkSL@|_Z@OZD(I zP5wvx(lh8(F0&J&0Gz7?XqOu>6F6~9?A0C7oRq<^Q`}~|`wJX)P_*uz Ac-xW1# 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 Q>rd#Eb%7 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 37aef8d3..ac72c34e 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java index 92fe93fb..ef610dd0 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java @@ -11,6 +11,7 @@ import net.minecraft.item.ItemStack; import net.minecraft.item.Items; import net.minecraft.util.Formatting; +import net.minecraft.util.Identifier; public class BackupToast implements Toast { @@ -28,10 +29,11 @@ public class BackupToast implements Toast { private static boolean timeSet = false; public static final ItemStack stack = new ItemStack(Items.PAPER); + private static final Identifier TEXTURE = new Identifier("toast/advancement"); @Override public Visibility draw(DrawContext context, ToastManager manager, long startTime) { - context.drawTexture(TEXTURE, 0, 0, 0, 0, this.getWidth(), this.getHeight()); + context.drawGuiTexture(TEXTURE, 0, 0, this.getWidth(), this.getHeight()); context.drawItemWithoutEntity(stack, 8, 8);; diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 8eb6c936..3cb4fc40 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -23,7 +23,7 @@ }, "depends": { "fabricloader": ">=0.14.22", - "minecraft": ">=1.20", + "minecraft": ">=1.20.2", "java": ">=17", "fabric-api": "*" } From c78ed5ba8d805c4e61038cf6b5ea9ccf1ef11adc Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 24 Oct 2023 20:43:25 +0100 Subject: [PATCH 366/580] fix serverside crash --- gradle.properties | 6 +++--- .../advancedbackups/client/ClientWrapper.java | 15 +++++++++++++ .../network/PacketBackupStatus.java | 21 ++++++++----------- 3 files changed, 27 insertions(+), 15 deletions(-) create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java diff --git a/gradle.properties b/gradle.properties index cfffcd91..a19b4b35 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,13 +11,13 @@ minecraft_version=1.20.1 # The Minecraft version range can use any release version of Minecraft as bounds. # Snapshots, pre-releases, and release candidates are not guaranteed to sort properly # as they do not follow standard versioning conventions. -minecraft_version_range=[1.20,1.21) +minecraft_version_range=[1.20,1.22) # The Neo version must agree with the Minecraft version to get a valid artifact neo_version=47.1.65 # The Neo version range can use any version of Neo as bounds or match the loader version range -neo_version_range=[47.1,) +neo_version_range=[46,) # The loader version range can only use the major version of Neo/FML as bounds -loader_version_range=[47,) +loader_version_range=[46,) # The mapping channel to use for mappings. # The default set of supported mapping channels are ["official", "snapshot", "snapshot_nodoc", "stable", "stable_nodoc"]. # Additional mapping channels can be registered through the "channelProviders" extension in a Gradle plugin. diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java new file mode 100644 index 00000000..8d0d63ee --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java @@ -0,0 +1,15 @@ +package co.uk.mommyheather.advancedbackups.client; + +import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; +import net.minecraft.client.Minecraft; + +public class ClientWrapper { + + public static void handle(PacketBackupStatus packetBackupStatus) { + if (!BackupToast.exists) { + BackupToast.exists = true; + Minecraft.getInstance().getToasts().addToast(new BackupToast()); + } + } + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java index a7d0f1f5..78f1fe90 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java @@ -3,6 +3,7 @@ import java.util.function.Supplier; import co.uk.mommyheather.advancedbackups.client.BackupToast; +import co.uk.mommyheather.advancedbackups.client.ClientWrapper; import net.minecraft.client.Minecraft; import net.minecraft.network.FriendlyByteBuf; import net.minecraftforge.fml.LogicalSide; @@ -52,20 +53,16 @@ public void toBytes(FriendlyByteBuf buf) { } public boolean handle(Supplier ctx) { + BackupToast.starting = starting; + BackupToast.started = started; + BackupToast.failed = failed; + BackupToast.finished = finished; + + BackupToast.progress = progress; + BackupToast.max = max; ctx.get().enqueueWork(() -> { if (ctx.get().getDirection().getReceptionSide() == LogicalSide.CLIENT) { - BackupToast.starting = starting; - BackupToast.started = started; - BackupToast.failed = failed; - BackupToast.finished = finished; - - BackupToast.progress = progress; - BackupToast.max = max; - - if (!BackupToast.exists) { - BackupToast.exists = true; - Minecraft.getInstance().getToasts().addToast(new BackupToast()); - } + ClientWrapper.handle(this); } }); ctx.get().setPacketHandled(true); From 22507c3cae5e2f60afeea3445114c871f3e5da12 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 24 Oct 2023 21:57:11 +0100 Subject: [PATCH 367/580] support 1.20.2 forge --- build.gradle | 12 +++++------ gradle.properties | 20 +++++++++---------- settings.gradle | 4 ++-- .../advancedbackups/client/BackupToast.java | 10 ++++------ .../advancedbackups/client/ClientWrapper.java | 11 +++++++++- .../network/NetworkHandler.java | 12 ++++------- .../network/PacketBackupStatus.java | 20 +++++++------------ src/main/resources/META-INF/mods.toml | 11 +--------- 8 files changed, 44 insertions(+), 56 deletions(-) diff --git a/build.gradle b/build.gradle index cd978ce7..c33446fa 100644 --- a/build.gradle +++ b/build.gradle @@ -2,7 +2,7 @@ plugins { id 'eclipse' id 'idea' id 'maven-publish' - id 'net.neoforged.gradle' version '[6.0.18,6.2)' + id 'net.minecraftforge.gradle' version '[6.0.14,6.2)' id 'org.spongepowered.mixin' version '0.7.+' } @@ -139,7 +139,7 @@ dependencies { // The "userdev" classifier will be requested and setup by NeoGradle. // If the group id is "net.minecraft" and the artifact id is one of ["client", "server", "joined"], // then special handling is done to allow a setup of a vanilla dependency without the use of an external repository. - minecraft "net.neoforged:forge:${minecraft_version}-${neo_version}" + minecraft "net.minecraftforge:forge:${minecraft_version}-${forge_version}" // Example mod dependency with JEI - using fg.deobf() ensures the dependency is remapped to your development mappings // The JEI API is declared for compile time use, while the full JEI artifact is used at runtime @@ -166,11 +166,11 @@ dependencies { // See https://docs.gradle.org/current/dsl/org.gradle.language.jvm.tasks.ProcessResources.html tasks.withType(ProcessResources).configureEach { var replaceProperties = [ - minecraft_version : minecraft_version, minecraft_version_range: minecraft_version_range, - neo_version : neo_version, neo_version_range: neo_version_range, + minecraft_version: minecraft_version, minecraft_version_range: minecraft_version_range, + forge_version: forge_version, forge_version_range: forge_version_range, loader_version_range: loader_version_range, - mod_id : mod_id, mod_name: mod_name, mod_license: mod_license, mod_version: mod_version, - mod_authors : mod_authors, mod_description: mod_description, pack_format_number: pack_format_number, + mod_id: mod_id, mod_name: mod_name, mod_license: mod_license, mod_version: version, + mod_authors: mod_authors, mod_description: mod_description, ] inputs.properties replaceProperties diff --git a/gradle.properties b/gradle.properties index a19b4b35..e5f82103 100644 --- a/gradle.properties +++ b/gradle.properties @@ -7,17 +7,17 @@ org.gradle.daemon=false ## Environment Properties # The Minecraft version must agree with the Neo version to get a valid artifact -minecraft_version=1.20.1 +minecraft_version=1.20.2 # The Minecraft version range can use any release version of Minecraft as bounds. # Snapshots, pre-releases, and release candidates are not guaranteed to sort properly # as they do not follow standard versioning conventions. -minecraft_version_range=[1.20,1.22) -# The Neo version must agree with the Minecraft version to get a valid artifact -neo_version=47.1.65 -# The Neo version range can use any version of Neo as bounds or match the loader version range -neo_version_range=[46,) -# The loader version range can only use the major version of Neo/FML as bounds -loader_version_range=[46,) +minecraft_version_range=[1.20.2,1.21) +# The Forge version must agree with the Minecraft version to get a valid artifact +forge_version=48.0.31 +# The Forge version range can use any version of Forge as bounds or match the loader version range +forge_version_range=[48,) +# The loader version range can only use the major version of Forge/FML as bounds +loader_version_range=[48,) # The mapping channel to use for mappings. # The default set of supported mapping channels are ["official", "snapshot", "snapshot_nodoc", "stable", "stable_nodoc"]. # Additional mapping channels can be registered through the "channelProviders" extension in a Gradle plugin. @@ -35,7 +35,7 @@ loader_version_range=[46,) mapping_channel=official # The mapping version to query from the mapping channel. # This must match the format required by the mapping channel. -mapping_version=1.20.1 +mapping_version=1.20.2 ## Mod Properties @@ -62,4 +62,4 @@ pack_format_number=15 modloaderName =forge -minecraftVersion =1.20 \ No newline at end of file +minecraftVersion =1.20.2 \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 24584e97..291d399d 100644 --- a/settings.gradle +++ b/settings.gradle @@ -2,8 +2,8 @@ pluginManagement { repositories { gradlePluginPortal() maven { - name = 'NeoForged' - url = 'https://maven.neoforged.net/releases' + name = 'MinecraftForge' + url = 'https://maven.minecraftforge.net/' } } } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java index c08baf68..0b02c295 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java @@ -1,15 +1,11 @@ package co.uk.mommyheather.advancedbackups.client; -import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.blaze3d.vertex.PoseStack; - import net.minecraft.ChatFormatting; -import net.minecraft.client.gui.Gui; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.components.toasts.Toast; import net.minecraft.client.gui.components.toasts.ToastComponent; -import net.minecraft.client.renderer.GameRenderer; import net.minecraft.client.resources.language.I18n; +import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; @@ -29,11 +25,13 @@ public class BackupToast implements Toast { private static boolean timeSet = false; public static final ItemStack stack = new ItemStack(Items.PAPER); + private static final ResourceLocation TEXTURE = new ResourceLocation("toast/advancement"); + @Override public Visibility render(GuiGraphics graphics, ToastComponent toastGui, long delta) { - graphics.blit(TEXTURE, 0, 0, 0, 0, this.width(), this.height()); + graphics.blitSprite(TEXTURE, 0, 0, this.width(), this.height()); graphics.renderFakeItem(stack, 8, 8); diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java index 8d0d63ee..990f3f85 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java @@ -5,7 +5,16 @@ public class ClientWrapper { - public static void handle(PacketBackupStatus packetBackupStatus) { + public static void handle(PacketBackupStatus message) { + + BackupToast.starting = message.starting; + BackupToast.started = message.started; + BackupToast.failed = message.failed; + BackupToast.finished = message.finished; + + BackupToast.progress = message.progress; + BackupToast.max = message.max; + if (!BackupToast.exists) { BackupToast.exists = true; Minecraft.getInstance().getToasts().addToast(new BackupToast()); diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java index 0c856fa0..95145741 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java @@ -2,9 +2,10 @@ import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; +import net.minecraftforge.network.ChannelBuilder; import net.minecraftforge.network.NetworkDirection; import net.minecraftforge.network.NetworkRegistry; -import net.minecraftforge.network.simple.SimpleChannel; +import net.minecraftforge.network.SimpleChannel; public class NetworkHandler { @@ -14,12 +15,7 @@ private static int id() { return id++; } - public static final SimpleChannel INSTANCE = NetworkRegistry.newSimpleChannel( - new ResourceLocation("advancedbackups", "main"), - () -> PROTOCOL_VERSION, - (version) -> true, - (version) -> true - ); + public static final SimpleChannel INSTANCE = ChannelBuilder.named(new ResourceLocation("advancedbackups", "main")).clientAcceptedVersions((status, version) -> true).simpleChannel(); public static void register() { @@ -31,7 +27,7 @@ public static void register() { } public static void sendToClient(ServerPlayer player, Object packet) { - INSTANCE.sendTo(packet, player.connection.connection, NetworkDirection.PLAY_TO_CLIENT); + INSTANCE.send(packet, player.connection.getConnection()); } } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java index 78f1fe90..c5baad0e 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java @@ -6,8 +6,9 @@ import co.uk.mommyheather.advancedbackups.client.ClientWrapper; import net.minecraft.client.Minecraft; import net.minecraft.network.FriendlyByteBuf; +import net.minecraftforge.event.network.CustomPayloadEvent; import net.minecraftforge.fml.LogicalSide; -import net.minecraftforge.network.NetworkEvent; +import net.minecraftforge.network.NetworkContext; public class PacketBackupStatus { @@ -52,20 +53,13 @@ public void toBytes(FriendlyByteBuf buf) { buf.writeInt(max); } - public boolean handle(Supplier ctx) { - BackupToast.starting = starting; - BackupToast.started = started; - BackupToast.failed = failed; - BackupToast.finished = finished; - - BackupToast.progress = progress; - BackupToast.max = max; - ctx.get().enqueueWork(() -> { - if (ctx.get().getDirection().getReceptionSide() == LogicalSide.CLIENT) { - ClientWrapper.handle(this); + public static boolean handle(PacketBackupStatus message, CustomPayloadEvent.Context ctx) { + ctx.enqueueWork(() -> { + if (ctx.getDirection().getReceptionSide() == LogicalSide.CLIENT) { + ClientWrapper.handle(message); } }); - ctx.get().setPacketHandled(true); + ctx.setPacketHandled(true); return true; } diff --git a/src/main/resources/META-INF/mods.toml b/src/main/resources/META-INF/mods.toml index c9e2c40c..450de68c 100644 --- a/src/main/resources/META-INF/mods.toml +++ b/src/main/resources/META-INF/mods.toml @@ -47,22 +47,13 @@ description='''${mod_description}''' # Does this dependency have to exist - if not, ordering below must be specified mandatory=true #mandatory # The version range of the dependency - versionRange="${neo_version_range}" #mandatory + versionRange="${forge_version_range}" #mandatory # An ordering relationship for the dependency - BEFORE or AFTER required if the dependency is not mandatory # BEFORE - This mod is loaded BEFORE the dependency # AFTER - This mod is loaded AFTER the dependency ordering="NONE" # Side this dependency is applied on - BOTH, CLIENT, or SERVER side="BOTH" -# Here's another dependency -[[dependencies.${mod_id}]] - modId="minecraft" - mandatory=true - # This version range declares a minimum of the current minecraft version up to but not including the next major version - versionRange="${minecraft_version_range}" - ordering="NONE" - side="BOTH" - # Features are specific properties of the game environment, that you may want to declare you require. This example declares # that your mod requires GL version 3.2 or higher. Other features will be added. They are side aware so declaring this won't # stop your mod loading on the server for example. From 392fe358829c21297a0229c1ea03b1e256cdc648 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 24 Oct 2023 23:47:39 +0100 Subject: [PATCH 368/580] Revert jar name change --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 9850ca29..d170e8aa 100644 --- a/gradle.properties +++ b/gradle.properties @@ -14,7 +14,7 @@ mod_version=2.0 maven_group=co.uk.mommyheather.advancedbackups archives_base_name=advancedbackups modloaderName =fabric -minecraftVersion =1.20.1 +minecraftVersion =1.20 # Dependencies fabric_version=0.83.0+1.20 From ce8231782afd20ffda001a95e130db3771ee35ee Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Wed, 25 Oct 2023 00:26:39 +0100 Subject: [PATCH 369/580] fix typo --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 1289043a..be497eff 100644 --- a/gradle.properties +++ b/gradle.properties @@ -13,7 +13,7 @@ version=2.0 maven_group=co.uk.mommyheather.advancedbackups archives_base_name=advanced-backups modloaderName =fabric -minecraftVersion =1.19.3 +minecraftVersion =1.19.2 # Dependencies fabric_version=0.76.1+1.19.2 From be01b6913f91588bbcd32c8bec3ee550ce6172f1 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Thu, 26 Oct 2023 20:51:33 +0100 Subject: [PATCH 370/580] fix activity issue, on right branch this time --- .../uk/mommyheather/advancedbackups/AdvancedBackups.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 7c52f2cc..78e4e71a 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -3,6 +3,7 @@ import net.minecraft.command.server.CommandSaveAll; import net.minecraft.init.Blocks; import net.minecraft.server.MinecraftServer; +import net.minecraft.server.management.ServerConfigurationManager; import net.minecraft.util.IProgressUpdate; import net.minecraft.world.MinecraftException; import net.minecraft.world.WorldServer; @@ -118,7 +119,7 @@ public void onServerStopping(FMLServerStoppingEvent event) { @SubscribeEvent public void onPlayerConnected(PlayerEvent.PlayerLoggedInEvent event) { - ABCore.activity = true; + ABCore.setActivity(true); } @SubscribeEvent @@ -192,4 +193,10 @@ public static void saveOnce(boolean unused) { //flush doesn't seem to be an opti } } + + public static void resetActivity() { + ServerConfigurationManager configurationManager = server.getConfigurationManager(); + ABCore.setActivity(!configurationManager.playerEntityList.isEmpty()); + } + } From 891d1805e124aad070e870778f56e7eeb2e6e285 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Thu, 26 Oct 2023 21:11:30 +0100 Subject: [PATCH 371/580] fix activity requirement issue in 1.12 --- .../advancedbackups/AdvancedBackups.java | 36 +++++++++++-------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index b5ee11bb..8c920f0c 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -1,7 +1,21 @@ package co.uk.mommyheather.advancedbackups; +import java.io.File; +import java.util.List; +import java.util.function.Consumer; + +import org.apache.logging.log4j.Logger; + +import co.uk.mommyheather.advancedbackups.client.ClientContactor; +import co.uk.mommyheather.advancedbackups.core.ABCore; +import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; +import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; +import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; +import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.server.MinecraftServer; import net.minecraft.world.WorldServer; +import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.fml.common.Loader; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod.EventBusSubscriber; @@ -15,19 +29,6 @@ import net.minecraftforge.fml.common.gameevent.TickEvent; import net.minecraftforge.fml.relauncher.Side; -import org.apache.logging.log4j.Logger; - -import co.uk.mommyheather.advancedbackups.client.ClientContactor; -import co.uk.mommyheather.advancedbackups.core.ABCore; -import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; -import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; -import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; -import co.uk.mommyheather.advancedbackups.network.NetworkHandler; -import net.minecraftforge.common.MinecraftForge; - -import java.io.File; -import java.util.function.Consumer; - @Mod(modid = AdvancedBackups.MODID, name = AdvancedBackups.NAME, version = AdvancedBackups.VERSION, acceptableRemoteVersions = "*") @EventBusSubscriber @@ -87,6 +88,8 @@ public void onServerStarting(FMLServerStartingEvent event) ABCore.warningLogger = warningLogger; ABCore.errorLogger = errorLogger; + ABCore.resetActivity = AdvancedBackups::resetActivity; + ABCore.clientContactor = new ClientContactor(); ABCore.modJar = Loader.instance().getIndexedModList().get("advancedbackups").getSource(); @@ -112,7 +115,7 @@ public void onServerStopping(FMLServerStoppingEvent event) { @SubscribeEvent public void onPlayerConnect(PlayerEvent.PlayerLoggedInEvent event) { - ABCore.activity = true; + ABCore.setActivity(true); } @SubscribeEvent @@ -154,4 +157,9 @@ public static void saveOnce(boolean unused) { //no flush bool in 1.12 either warningLogger.accept(saveCompleteMessage); } + public static void resetActivity() { + List players = server.getPlayerList().getPlayers(); + ABCore.setActivity(!players.isEmpty()); + } + } From 922bb3f2e77f2b6e187a0531c5b1b43e009373f8 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Thu, 26 Oct 2023 21:25:32 +0100 Subject: [PATCH 372/580] fix activity issue in 1.16 --- .../advancedbackups/AdvancedBackups.java | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index c82e18b0..92cdc856 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -1,12 +1,19 @@ package co.uk.mommyheather.advancedbackups; +import java.util.List; +import java.util.function.Consumer; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + import co.uk.mommyheather.advancedbackups.client.ClientContactor; import co.uk.mommyheather.advancedbackups.core.ABCore; import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; import co.uk.mommyheather.advancedbackups.network.NetworkHandler; +import net.minecraft.entity.player.ServerPlayerEntity; import net.minecraft.server.MinecraftServer; import net.minecraft.world.server.ServerWorld; import net.minecraft.world.storage.FolderName; @@ -22,10 +29,6 @@ import net.minecraftforge.fml.event.server.FMLServerStoppingEvent; import net.minecraftforge.fml.server.ServerLifecycleHooks; -import java.util.function.Consumer; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - @Mod("advancedbackups") public class AdvancedBackups { @@ -60,6 +63,8 @@ public void onServerStarting(FMLServerStartingEvent event) ABCore.warningLogger = warningLogger; ABCore.errorLogger = errorLogger; + ABCore.resetActivity = AdvancedBackups::resetActivity; + ABCore.clientContactor = new ClientContactor(); ABCore.modJar = ModList.get().getModFileById("advancedbackups").getFile().getFilePath().toFile(); @@ -131,4 +136,10 @@ public static void saveOnce(boolean flush) { warningLogger.accept(saveCompleteMessage); } + public static void resetActivity() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + ABCore.setActivity(!players.isEmpty()); + } + } From bd77670989984e40317e7d53b69950730c9aeae7 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Thu, 26 Oct 2023 21:41:57 +0100 Subject: [PATCH 373/580] fix activity issue on 1.18 fabric --- .../advancedbackups/AdvancedBackups.java | 31 ++++++++++++------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 33d899c0..b662a727 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -1,16 +1,7 @@ package co.uk.mommyheather.advancedbackups; -import net.fabricmc.api.ModInitializer; -import net.fabricmc.fabric.api.command.v1.CommandRegistrationCallback; -import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; -import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; -import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; -import net.fabricmc.loader.impl.FabricLoaderImpl; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.world.ServerWorld; -import net.minecraft.util.WorldSavePath; - import java.io.File; +import java.util.List; import java.util.function.Consumer; import org.slf4j.Logger; @@ -21,7 +12,16 @@ import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; -import co.uk.mommyheather.advancedbackups.network.NetworkHandler; +import net.fabricmc.api.ModInitializer; +import net.fabricmc.fabric.api.command.v1.CommandRegistrationCallback; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; +import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; +import net.fabricmc.loader.impl.FabricLoaderImpl; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.WorldSavePath; public class AdvancedBackups implements ModInitializer { // This logger is used to write text to the console and the log file. @@ -53,6 +53,8 @@ public void onInitialize() { ABCore.warningLogger = warningLogger; ABCore.errorLogger = errorLogger; + ABCore.resetActivity = AdvancedBackups::resetActivity; + ABCore.clientContactor = new ClientContactor(); ABCore.modJar = new File(FabricLoaderImpl.INSTANCE.getModContainer("advancedbackups").get().getOrigin().toString()); @@ -70,7 +72,7 @@ public void onInitialize() { }); ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> { - ABCore.setActivity(); + ABCore.setActivity(true); }); CommandRegistrationCallback.EVENT.register((dispatcher, isDedicated) -> { @@ -136,4 +138,9 @@ public static void saveOnce(boolean flush) { if (ConfigManager.silent.get()) return; warningLogger.accept(saveCompleteMessage); } + + public static void resetActivity() { + List players = server.getPlayerManager().getPlayerList(); + ABCore.setActivity(!players.isEmpty()); + } } From ca432e95d65e0345d746213d15fc04d7b31bfa11 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Thu, 26 Oct 2023 21:47:23 +0100 Subject: [PATCH 374/580] fix the activity issue in 1.18 forged --- .../advancedbackups/AdvancedBackups.java | 30 ++++++++++++------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 56d222a4..db563808 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -1,5 +1,10 @@ package co.uk.mommyheather.advancedbackups; +import java.util.List; +import java.util.function.Consumer; + +import org.slf4j.Logger; + import com.mojang.logging.LogUtils; import co.uk.mommyheather.advancedbackups.client.ClientContactor; @@ -10,22 +15,19 @@ import co.uk.mommyheather.advancedbackups.network.NetworkHandler; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.level.storage.LevelResource; import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.ModList; -import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.server.ServerLifecycleHooks; import net.minecraftforge.event.RegisterCommandsEvent; import net.minecraftforge.event.TickEvent; import net.minecraftforge.event.entity.player.PlayerEvent; import net.minecraftforge.event.server.ServerStartedEvent; import net.minecraftforge.event.server.ServerStartingEvent; import net.minecraftforge.event.server.ServerStoppingEvent; - -import java.util.function.Consumer; - -import org.slf4j.Logger; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.ModList; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.server.ServerLifecycleHooks; @Mod("advancedbackups") public class AdvancedBackups @@ -61,6 +63,8 @@ public void onServerStarting(ServerStartingEvent event) ABCore.warningLogger = warningLogger; ABCore.errorLogger = errorLogger; + ABCore.resetActivity = AdvancedBackups::resetActivity; + ABCore.clientContactor = new ClientContactor(); ABCore.modJar = ModList.get().getModFileById("advancedbackups").getFile().getFilePath().toFile(); @@ -85,7 +89,7 @@ public void onServerStopping(ServerStoppingEvent event) { @SubscribeEvent public void onPlayerJoined(PlayerEvent.PlayerLoggedInEvent event) { - ABCore.activity = true; + ABCore.setActivity(true); } @SubscribeEvent @@ -145,11 +149,17 @@ public static void enableSaving() { warningLogger.accept(savesEnabledMessage); } - public static void saveOnce(boolean flush) { + public static void saveOnce(Boolean flush) { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); server.saveEverything(true, flush, true); if (ConfigManager.silent.get()) return; warningLogger.accept(saveCompleteMessage); } + public static void resetActivity() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + ABCore.setActivity(!players.isEmpty()); + } + } From f583e7077908000ee4bb072a59ea290339f775dc Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Thu, 26 Oct 2023 22:12:36 +0100 Subject: [PATCH 375/580] fix activity issue on fabric 1.19.2 --- .../advancedbackups/AdvancedBackups.java | 31 ++++++++++++------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 6cc17b4e..01192b2b 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -1,16 +1,7 @@ package co.uk.mommyheather.advancedbackups; -import net.fabricmc.api.ModInitializer; -import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; -import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; -import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; -import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; -import net.fabricmc.loader.impl.FabricLoaderImpl; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.world.ServerWorld; -import net.minecraft.util.WorldSavePath; - import java.io.File; +import java.util.List; import java.util.function.Consumer; import org.slf4j.Logger; @@ -21,7 +12,16 @@ import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; -import co.uk.mommyheather.advancedbackups.network.NetworkHandler; +import net.fabricmc.api.ModInitializer; +import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; +import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; +import net.fabricmc.loader.impl.FabricLoaderImpl; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.WorldSavePath; public class AdvancedBackups implements ModInitializer { // This logger is used to write text to the console and the log file. @@ -52,6 +52,8 @@ public void onInitialize() { ABCore.warningLogger = warningLogger; ABCore.errorLogger = errorLogger; + ABCore.resetActivity = AdvancedBackups::resetActivity; + ABCore.clientContactor = new ClientContactor(); ABCore.modJar = new File(FabricLoaderImpl.INSTANCE.getModContainer("advancedbackups").get().getOrigin().toString()); @@ -68,7 +70,7 @@ public void onInitialize() { }); ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> { - ABCore.setActivity(); + ABCore.setActivity(true); }); CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> { @@ -134,4 +136,9 @@ public static void saveOnce(boolean flush) { if (ConfigManager.silent.get()) return; warningLogger.accept(saveCompleteMessage); } + + public static void resetActivity() { + List players = server.getPlayerManager().getPlayerList(); + ABCore.setActivity(!players.isEmpty()); + } } From fea70b0fa2167cd4da915ed05bcd92428f9032ce Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Thu, 26 Oct 2023 22:45:05 +0100 Subject: [PATCH 376/580] fix the activity bug in 1.19.2 forge --- .../advancedbackups/AdvancedBackups.java | 28 +++++++++++++------ 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 78fcb797..9b1739a0 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -1,5 +1,10 @@ package co.uk.mommyheather.advancedbackups; +import java.util.List; +import java.util.function.Consumer; + +import org.slf4j.Logger; + import com.mojang.logging.LogUtils; import co.uk.mommyheather.advancedbackups.client.ClientContactor; @@ -10,12 +15,9 @@ import co.uk.mommyheather.advancedbackups.network.NetworkHandler; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.level.storage.LevelResource; import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.ModList; -import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.server.ServerLifecycleHooks; import net.minecraftforge.event.RegisterCommandsEvent; import net.minecraftforge.event.TickEvent; import net.minecraftforge.event.TickEvent.Phase; @@ -23,10 +25,10 @@ import net.minecraftforge.event.server.ServerStartedEvent; import net.minecraftforge.event.server.ServerStartingEvent; import net.minecraftforge.event.server.ServerStoppingEvent; - -import java.util.function.Consumer; - -import org.slf4j.Logger; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.ModList; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.server.ServerLifecycleHooks; @Mod("advancedbackups") public class AdvancedBackups @@ -67,6 +69,8 @@ public void onServerStarting(ServerStartingEvent event) ABCore.warningLogger = warningLogger; ABCore.errorLogger = errorLogger; + ABCore.resetActivity = AdvancedBackups::resetActivity; + ABCore.clientContactor = new ClientContactor(); ABCore.modJar = ModList.get().getModFileById("advancedbackups").getFile().getFilePath().toFile(); @@ -89,7 +93,7 @@ public void onServerStopping(ServerStoppingEvent event) { @SubscribeEvent public void onPlayerJoined(PlayerEvent.PlayerLoggedInEvent event) { - ABCore.setActivity(); + ABCore.setActivity(true); } @SubscribeEvent @@ -150,4 +154,10 @@ public static void saveOnce(boolean flush) { warningLogger.accept(saveCompleteMessage); } + public static void resetActivity() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + ABCore.setActivity(!players.isEmpty()); + } + } From ec12b9079b2f55ce7a087de7e3f9bdc270b9862a Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Thu, 26 Oct 2023 22:55:51 +0100 Subject: [PATCH 377/580] fix activity issue on 1.19.3 fabric --- .../advancedbackups/AdvancedBackups.java | 31 ++++++++++++------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 6cc17b4e..01192b2b 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -1,16 +1,7 @@ package co.uk.mommyheather.advancedbackups; -import net.fabricmc.api.ModInitializer; -import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; -import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; -import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; -import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; -import net.fabricmc.loader.impl.FabricLoaderImpl; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.world.ServerWorld; -import net.minecraft.util.WorldSavePath; - import java.io.File; +import java.util.List; import java.util.function.Consumer; import org.slf4j.Logger; @@ -21,7 +12,16 @@ import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; -import co.uk.mommyheather.advancedbackups.network.NetworkHandler; +import net.fabricmc.api.ModInitializer; +import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; +import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; +import net.fabricmc.loader.impl.FabricLoaderImpl; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.WorldSavePath; public class AdvancedBackups implements ModInitializer { // This logger is used to write text to the console and the log file. @@ -52,6 +52,8 @@ public void onInitialize() { ABCore.warningLogger = warningLogger; ABCore.errorLogger = errorLogger; + ABCore.resetActivity = AdvancedBackups::resetActivity; + ABCore.clientContactor = new ClientContactor(); ABCore.modJar = new File(FabricLoaderImpl.INSTANCE.getModContainer("advancedbackups").get().getOrigin().toString()); @@ -68,7 +70,7 @@ public void onInitialize() { }); ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> { - ABCore.setActivity(); + ABCore.setActivity(true); }); CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> { @@ -134,4 +136,9 @@ public static void saveOnce(boolean flush) { if (ConfigManager.silent.get()) return; warningLogger.accept(saveCompleteMessage); } + + public static void resetActivity() { + List players = server.getPlayerManager().getPlayerList(); + ABCore.setActivity(!players.isEmpty()); + } } From 444a6bd0fb1bd6ac95b6b7031763e0674209b54a Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Thu, 26 Oct 2023 23:16:50 +0100 Subject: [PATCH 378/580] fix activity issue, 1.19.3 forge --- .../advancedbackups/AdvancedBackups.java | 29 +++++++++++++------ 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 78fcb797..0d1d2d9e 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -1,5 +1,10 @@ package co.uk.mommyheather.advancedbackups; +import java.util.List; +import java.util.function.Consumer; + +import org.slf4j.Logger; + import com.mojang.logging.LogUtils; import co.uk.mommyheather.advancedbackups.client.ClientContactor; @@ -10,12 +15,9 @@ import co.uk.mommyheather.advancedbackups.network.NetworkHandler; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.level.storage.LevelResource; import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.ModList; -import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.server.ServerLifecycleHooks; import net.minecraftforge.event.RegisterCommandsEvent; import net.minecraftforge.event.TickEvent; import net.minecraftforge.event.TickEvent.Phase; @@ -23,10 +25,10 @@ import net.minecraftforge.event.server.ServerStartedEvent; import net.minecraftforge.event.server.ServerStartingEvent; import net.minecraftforge.event.server.ServerStoppingEvent; - -import java.util.function.Consumer; - -import org.slf4j.Logger; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.ModList; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.server.ServerLifecycleHooks; @Mod("advancedbackups") public class AdvancedBackups @@ -67,6 +69,8 @@ public void onServerStarting(ServerStartingEvent event) ABCore.warningLogger = warningLogger; ABCore.errorLogger = errorLogger; + ABCore.resetActivity = AdvancedBackups::resetActivity; + ABCore.clientContactor = new ClientContactor(); ABCore.modJar = ModList.get().getModFileById("advancedbackups").getFile().getFilePath().toFile(); @@ -89,7 +93,7 @@ public void onServerStopping(ServerStoppingEvent event) { @SubscribeEvent public void onPlayerJoined(PlayerEvent.PlayerLoggedInEvent event) { - ABCore.setActivity(); + ABCore.setActivity(true); } @SubscribeEvent @@ -150,4 +154,11 @@ public static void saveOnce(boolean flush) { warningLogger.accept(saveCompleteMessage); } + + public static void resetActivity() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + ABCore.setActivity(!players.isEmpty()); + } + } From b39ae5a016a37b9703bacc477280d854397b60e2 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Thu, 26 Oct 2023 23:37:17 +0100 Subject: [PATCH 379/580] fix the activity bug, fabric 1.20.s --- .../advancedbackups/AdvancedBackups.java | 31 ++++++++++++------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 7c82168d..a441e2fe 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -1,16 +1,7 @@ package co.uk.mommyheather.advancedbackups; -import net.fabricmc.api.ModInitializer; -import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; -import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; -import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; -import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; -import net.fabricmc.loader.impl.FabricLoaderImpl; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.world.ServerWorld; -import net.minecraft.util.WorldSavePath; - import java.io.File; +import java.util.List; import java.util.function.Consumer; import org.slf4j.Logger; @@ -21,7 +12,16 @@ import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; -import co.uk.mommyheather.advancedbackups.network.NetworkHandler; +import net.fabricmc.api.ModInitializer; +import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; +import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; +import net.fabricmc.loader.impl.FabricLoaderImpl; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.WorldSavePath; public class AdvancedBackups implements ModInitializer { // This logger is used to write text to the console and the log file. @@ -52,6 +52,8 @@ public void onInitialize() { ABCore.warningLogger = warningLogger; ABCore.errorLogger = errorLogger; + ABCore.resetActivity = AdvancedBackups::resetActivity; + ABCore.clientContactor = new ClientContactor(); ABCore.modJar = new File(FabricLoaderImpl.INSTANCE.getModContainer("advancedbackups").get().getOrigin().toString()); @@ -68,7 +70,7 @@ public void onInitialize() { }); ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> { - ABCore.setActivity(); + ABCore.setActivity(true); }); CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> { @@ -135,4 +137,9 @@ public static void saveOnce(boolean flush) { if (ConfigManager.silent.get()) return; warningLogger.accept(saveCompleteMessage); } + + public static void resetActivity() { + List players = server.getPlayerManager().getPlayerList(); + ABCore.setActivity(!players.isEmpty()); + } } From c69e2d94d329e27caf39dd5a128fc2090217126b Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Fri, 27 Oct 2023 01:42:51 +0100 Subject: [PATCH 380/580] fix activity bug --- .../advancedbackups/AdvancedBackups.java | 29 +++++++++++++------ 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index e5af7713..681f3c26 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -1,5 +1,10 @@ package co.uk.mommyheather.advancedbackups; +import java.util.List; +import java.util.function.Consumer; + +import org.slf4j.Logger; + import com.mojang.logging.LogUtils; import co.uk.mommyheather.advancedbackups.client.ClientContactor; @@ -10,22 +15,19 @@ import co.uk.mommyheather.advancedbackups.network.NetworkHandler; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.level.storage.LevelResource; import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.ModList; -import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.server.ServerLifecycleHooks; import net.minecraftforge.event.RegisterCommandsEvent; import net.minecraftforge.event.TickEvent; import net.minecraftforge.event.entity.player.PlayerEvent; import net.minecraftforge.event.server.ServerStartedEvent; import net.minecraftforge.event.server.ServerStartingEvent; import net.minecraftforge.event.server.ServerStoppingEvent; - -import java.util.function.Consumer; - -import org.slf4j.Logger; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.ModList; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.server.ServerLifecycleHooks; @Mod("advancedbackups") public class AdvancedBackups @@ -60,6 +62,9 @@ public void onServerStarting(ServerStartingEvent event) ABCore.warningLogger = warningLogger; ABCore.errorLogger = errorLogger; + ABCore.resetActivity = AdvancedBackups::resetActivity; + + ABCore.clientContactor = new ClientContactor(); ABCore.modJar = ModList.get().getModFileById("advancedbackups").getFile().getFilePath().toFile(); @@ -82,7 +87,7 @@ public void onServerStopping(ServerStoppingEvent event) { @SubscribeEvent public void onPlayerJoined(PlayerEvent.PlayerLoggedInEvent event) { - ABCore.setActivity(); + ABCore.setActivity(true); } @SubscribeEvent @@ -150,4 +155,10 @@ public static void saveOnce(boolean flush) { warningLogger.accept(saveCompleteMessage); } + public static void resetActivity() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + ABCore.setActivity(!players.isEmpty()); + } + } From bce93a2ff0f69b458664d17f14498ae1dacbdedf Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Fri, 27 Oct 2023 01:48:05 +0100 Subject: [PATCH 381/580] fix activity bug --- .../advancedbackups/AdvancedBackups.java | 31 ++++++++++++------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 7c82168d..a441e2fe 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -1,16 +1,7 @@ package co.uk.mommyheather.advancedbackups; -import net.fabricmc.api.ModInitializer; -import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; -import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; -import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; -import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; -import net.fabricmc.loader.impl.FabricLoaderImpl; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.world.ServerWorld; -import net.minecraft.util.WorldSavePath; - import java.io.File; +import java.util.List; import java.util.function.Consumer; import org.slf4j.Logger; @@ -21,7 +12,16 @@ import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; -import co.uk.mommyheather.advancedbackups.network.NetworkHandler; +import net.fabricmc.api.ModInitializer; +import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; +import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; +import net.fabricmc.loader.impl.FabricLoaderImpl; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.WorldSavePath; public class AdvancedBackups implements ModInitializer { // This logger is used to write text to the console and the log file. @@ -52,6 +52,8 @@ public void onInitialize() { ABCore.warningLogger = warningLogger; ABCore.errorLogger = errorLogger; + ABCore.resetActivity = AdvancedBackups::resetActivity; + ABCore.clientContactor = new ClientContactor(); ABCore.modJar = new File(FabricLoaderImpl.INSTANCE.getModContainer("advancedbackups").get().getOrigin().toString()); @@ -68,7 +70,7 @@ public void onInitialize() { }); ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> { - ABCore.setActivity(); + ABCore.setActivity(true); }); CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> { @@ -135,4 +137,9 @@ public static void saveOnce(boolean flush) { if (ConfigManager.silent.get()) return; warningLogger.accept(saveCompleteMessage); } + + public static void resetActivity() { + List players = server.getPlayerManager().getPlayerList(); + ABCore.setActivity(!players.isEmpty()); + } } From ba69b710bd396c1a19cd4db66252a1ab9b04e040 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Fri, 27 Oct 2023 01:54:28 +0100 Subject: [PATCH 382/580] fix activity bug --- .../advancedbackups/AdvancedBackups.java | 29 +++++++++++++------ 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index e5af7713..9ee90eda 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -1,5 +1,10 @@ package co.uk.mommyheather.advancedbackups; +import java.util.List; +import java.util.function.Consumer; + +import org.slf4j.Logger; + import com.mojang.logging.LogUtils; import co.uk.mommyheather.advancedbackups.client.ClientContactor; @@ -10,22 +15,19 @@ import co.uk.mommyheather.advancedbackups.network.NetworkHandler; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.level.storage.LevelResource; import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.ModList; -import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.server.ServerLifecycleHooks; import net.minecraftforge.event.RegisterCommandsEvent; import net.minecraftforge.event.TickEvent; import net.minecraftforge.event.entity.player.PlayerEvent; import net.minecraftforge.event.server.ServerStartedEvent; import net.minecraftforge.event.server.ServerStartingEvent; import net.minecraftforge.event.server.ServerStoppingEvent; - -import java.util.function.Consumer; - -import org.slf4j.Logger; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.ModList; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.server.ServerLifecycleHooks; @Mod("advancedbackups") public class AdvancedBackups @@ -60,6 +62,8 @@ public void onServerStarting(ServerStartingEvent event) ABCore.warningLogger = warningLogger; ABCore.errorLogger = errorLogger; + ABCore.resetActivity = AdvancedBackups::resetActivity; + ABCore.clientContactor = new ClientContactor(); ABCore.modJar = ModList.get().getModFileById("advancedbackups").getFile().getFilePath().toFile(); @@ -82,7 +86,7 @@ public void onServerStopping(ServerStoppingEvent event) { @SubscribeEvent public void onPlayerJoined(PlayerEvent.PlayerLoggedInEvent event) { - ABCore.setActivity(); + ABCore.setActivity(true); } @SubscribeEvent @@ -150,4 +154,11 @@ public static void saveOnce(boolean flush) { warningLogger.accept(saveCompleteMessage); } + + public static void resetActivity() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + ABCore.setActivity(!players.isEmpty()); + } + } From 95af92128f0544b0efab2b8f2e3d57cec399e205 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sat, 28 Oct 2023 20:25:18 +0100 Subject: [PATCH 383/580] Fix crash on quilt --- .../co/uk/mommyheather/advancedbackups/AdvancedBackups.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 01192b2b..9165ba19 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -55,7 +55,7 @@ public void onInitialize() { ABCore.resetActivity = AdvancedBackups::resetActivity; ABCore.clientContactor = new ClientContactor(); - ABCore.modJar = new File(FabricLoaderImpl.INSTANCE.getModContainer("advancedbackups").get().getOrigin().toString()); + ABCore.modJar = new File(FabricLoaderImpl.INSTANCE.getModContainer("advancedbackups").get().getOrigin().getPaths().get(0).toAbsolutePath().toString()); ConfigManager.loadOrCreateConfig(); From 1119ab484c43ca8e063f675ea785e541d06422ef Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sat, 28 Oct 2023 21:39:53 +0100 Subject: [PATCH 384/580] fix quilt crash --- .../co/uk/mommyheather/advancedbackups/AdvancedBackups.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index b662a727..a2f2eb97 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -57,7 +57,7 @@ public void onInitialize() { ABCore.clientContactor = new ClientContactor(); - ABCore.modJar = new File(FabricLoaderImpl.INSTANCE.getModContainer("advancedbackups").get().getOrigin().toString()); + ABCore.modJar = new File(FabricLoaderImpl.INSTANCE.getModContainer("advancedbackups").get().getOrigin().getPaths().get(0).toAbsolutePath().toString()); ConfigManager.loadOrCreateConfig(); From ac52b1d536be200d26a0994bb50a050f6ee78f13 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sat, 28 Oct 2023 21:43:46 +0100 Subject: [PATCH 385/580] fix quilt crash --- .../co/uk/mommyheather/advancedbackups/AdvancedBackups.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 01192b2b..9165ba19 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -55,7 +55,7 @@ public void onInitialize() { ABCore.resetActivity = AdvancedBackups::resetActivity; ABCore.clientContactor = new ClientContactor(); - ABCore.modJar = new File(FabricLoaderImpl.INSTANCE.getModContainer("advancedbackups").get().getOrigin().toString()); + ABCore.modJar = new File(FabricLoaderImpl.INSTANCE.getModContainer("advancedbackups").get().getOrigin().getPaths().get(0).toAbsolutePath().toString()); ConfigManager.loadOrCreateConfig(); From e578328be784c2d60bea86b76ad58d6fc52cfa3b Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sat, 28 Oct 2023 21:54:01 +0100 Subject: [PATCH 386/580] fix quilt crash --- .../co/uk/mommyheather/advancedbackups/AdvancedBackups.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index a441e2fe..b5f0e257 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -55,7 +55,7 @@ public void onInitialize() { ABCore.resetActivity = AdvancedBackups::resetActivity; ABCore.clientContactor = new ClientContactor(); - ABCore.modJar = new File(FabricLoaderImpl.INSTANCE.getModContainer("advancedbackups").get().getOrigin().toString()); + ABCore.modJar = new File(FabricLoaderImpl.INSTANCE.getModContainer("advancedbackups").get().getOrigin().getPaths().get(0).toAbsolutePath().toString()); ConfigManager.loadOrCreateConfig(); From 518612904c94a00bf9a3311c2c044382b036fcb7 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sat, 28 Oct 2023 22:00:17 +0100 Subject: [PATCH 387/580] fix quilt crash --- .../co/uk/mommyheather/advancedbackups/AdvancedBackups.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index a441e2fe..b5f0e257 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -55,7 +55,7 @@ public void onInitialize() { ABCore.resetActivity = AdvancedBackups::resetActivity; ABCore.clientContactor = new ClientContactor(); - ABCore.modJar = new File(FabricLoaderImpl.INSTANCE.getModContainer("advancedbackups").get().getOrigin().toString()); + ABCore.modJar = new File(FabricLoaderImpl.INSTANCE.getModContainer("advancedbackups").get().getOrigin().getPaths().get(0).toAbsolutePath().toString()); ConfigManager.loadOrCreateConfig(); From 883bab994eccfe50220fe8c873a89222170405c0 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Fri, 10 Nov 2023 06:04:23 +0000 Subject: [PATCH 388/580] neo 1.20.2 port! --- build.gradle | 208 +++++++----------- gradle.properties | 18 +- .../advancedbackups/AdvancedBackups.java | 24 +- .../advancedbackups/client/BackupToast.java | 9 +- .../client/ClientContactor.java | 2 +- .../network/NetworkHandler.java | 8 +- .../network/PacketBackupStatus.java | 28 ++- src/main/resources/META-INF/mods.toml | 2 +- 8 files changed, 121 insertions(+), 178 deletions(-) diff --git a/build.gradle b/build.gradle index cd978ce7..792aba25 100644 --- a/build.gradle +++ b/build.gradle @@ -1,159 +1,114 @@ plugins { + id 'java-library' id 'eclipse' id 'idea' id 'maven-publish' - id 'net.neoforged.gradle' version '[6.0.18,6.2)' - id 'org.spongepowered.mixin' version '0.7.+' + id 'net.neoforged.gradle.userdev' version '7.0.26' } group = mod_group_id +version = "${version != 'unspecified' ? version : '0.1-dev'}" //debuggins sake +configurations { + // configuration that holds jars to include in the jar + extraLibs +} + +repositories { + mavenLocal() +} + base { archivesName = 'AdvancedBackups-' + modloaderName + "-" + minecraftVersion } -task copyVSCodeResources (dependsOn: 'processResources', type: Copy) { - from 'build/resources' - into 'bin/' -} + // Mojang ships Java 17 to end users in 1.18+, so your mod should target Java 17. java.toolchain.languageVersion = JavaLanguageVersion.of(17) -println "Java: ${System.getProperty 'java.version'}, JVM: ${System.getProperty 'java.vm.version'} (${System.getProperty 'java.vendor'}), Arch: ${System.getProperty 'os.arch'}" -minecraft { - // The mappings can be changed at any time and must be in the following format. - // Channel: Version: - // official MCVersion Official field/method names from Mojang mapping files - // parchment YYYY.MM.DD-MCVersion Open community-sourced parameter names and javadocs layered on top of official - // - // You must be aware of the Mojang license when using the 'official' or 'parchment' mappings. - // See more information here: https://github.com/NeoForged/NeoForm/blob/main/Mojang.md - // - // Parchment is an unofficial project maintained by ParchmentMC, separate from MinecraftForge - // Additional setup is needed to use their mappings: https://parchmentmc.org/docs/getting-started - // - // Use non-default mappings at your own risk. They may not always work. - // Simply re-run your setup task after changing the mappings to update your workspace. - mappings channel: mapping_channel, version: mapping_version - - // When true, this property will have all Eclipse/IntelliJ IDEA run configurations run the "prepareX" task for the given run configuration before launching the game. - // In most cases, it is not necessary to enable. - // enableEclipsePrepareRuns = true - // enableIdeaPrepareRuns = true - - // This property allows configuring Gradle's ProcessResources task(s) to run on IDE output locations before launching the game. - // It is REQUIRED to be set to true for this template to function. - // See https://docs.gradle.org/current/dsl/org.gradle.language.jvm.tasks.ProcessResources.html - copyIdeResources = true - - // When true, this property will add the folder name of all declared run configurations to generated IDE run configurations. - // The folder name can be set on a run configuration using the "folderName" property. - // By default, the folder name of a run configuration is the name of the Gradle project containing it. - // generateRunFolders = true - - // This property enables access transformers for use in development. - // They will be applied to the Minecraft artifact. - // The access transformer file can be anywhere in the project. - // However, it must be at "META-INF/accesstransformer.cfg" in the final mod jar to be loaded by Forge. - // This default location is a best practice to automatically put the file in the right place in the final jar. - // See https://docs.neoforged.net/docs/1.20.x/advanced/accesstransformers/ for more information. - - // accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg') - - // Default run configurations. - // These can be tweaked, removed, or duplicated as needed. - runs { - // applies to all the run configs below - configureEach { - workingDirectory project.file("run/${it.name}") - - // Recommended logging data for a userdev environment - // The markers can be added/remove as needed separated by commas. - // "SCAN": For mods scan. - // "REGISTRIES": For firing of registry events. - // "REGISTRYDUMP": For getting the contents of all registries. - property 'forge.logging.markers', 'REGISTRIES' - - // Recommended logging level for the console - // You can set various levels here. - // Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels - property 'forge.logging.console.level', 'debug' - - mods { - "${mod_id}" { - source sourceSets.main - } - } - } +//minecraft.accessTransformers.file rootProject.file('src/main/resources/META-INF/accesstransformer.cfg') +//minecraft.accessTransformers.entry public net.minecraft.client.Minecraft textureManager # textureManager + +// Default run configurations. +// These can be tweaked, removed, or duplicated as needed. +runs { + // applies to all the run configs below + configureEach { + // Recommended logging data for a userdev environment + // The markers can be added/remove as needed separated by commas. + // "SCAN": For mods scan. + // "REGISTRIES": For firing of registry events. + // "REGISTRYDUMP": For getting the contents of all registries. + systemProperty 'forge.logging.markers', 'REGISTRIES' + + // Recommended logging level for the console + // You can set various levels here. + // Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels + systemProperty 'forge.logging.console.level', 'debug' + + modSource project.sourceSets.main + } - client { - // Comma-separated list of namespaces to load gametests from. Empty = all namespaces. - property 'forge.enabledGameTestNamespaces', mod_id - } + client { + // Comma-separated list of namespaces to load gametests from. Empty = all namespaces. + systemProperty 'forge.enabledGameTestNamespaces', project.mod_id + } - server { - property 'forge.enabledGameTestNamespaces', mod_id - args '--nogui' - } + server { + systemProperty 'forge.enabledGameTestNamespaces', project.mod_id + programArgument '--nogui' + } - // This run config launches GameTestServer and runs all registered gametests, then exits. - // By default, the server will crash when no gametests are provided. - // The gametest system is also enabled by default for other run configs under the /test command. - gameTestServer { - property 'forge.enabledGameTestNamespaces', mod_id - } + // This run config launches GameTestServer and runs all registered gametests, then exits. + // By default, the server will crash when no gametests are provided. + // The gametest system is also enabled by default for other run configs under the /test command. + gameTestServer { + systemProperty 'forge.enabledGameTestNamespaces', project.mod_id + } - data { - // example of overriding the workingDirectory set in configureEach above, uncomment if you want to use it - // workingDirectory project.file('run-data') + data { + // example of overriding the workingDirectory set in configureEach above, uncomment if you want to use it + // workingDirectory project.file('run-data') - // Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources. - args '--mod', mod_id, '--all', '--output', file('src/generated/resources/'), '--existing', file('src/main/resources/') - } + // Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources. + programArguments.addAll '--mod', project.mod_id, '--all', '--output', file('src/generated/resources/').getAbsolutePath(), '--existing', file('src/main/resources/').getAbsolutePath() } } // Include resources generated by data generators. sourceSets.main.resources { srcDir 'src/generated/resources' } -configurations { - // configuration that holds jars to include in the jar - extraLibs -} - -repositories { - // Put repositories for dependencies here - // NeoGradle automatically adds the Forge maven and Maven Central for you - - // If you have mod jar dependencies in ./libs, you can declare them as a repository like so. - // See https://docs.gradle.org/current/userguide/declaring_repositories.html#sub:flat_dir_resolver - // flatDir { - // dir 'libs' - // } -} dependencies { // Specify the version of Minecraft to use. - // Any artifact can be supplied so long as it has a "userdev" classifier artifact and is a compatible patcher artifact. - // The "userdev" classifier will be requested and setup by NeoGradle. - // If the group id is "net.minecraft" and the artifact id is one of ["client", "server", "joined"], - // then special handling is done to allow a setup of a vanilla dependency without the use of an external repository. - minecraft "net.neoforged:forge:${minecraft_version}-${neo_version}" + // Depending on the plugin applied there are several options. We will assume you applied the userdev plugin as shown above. + // The group for userdev is net.neoforged, the module name is neoforge, and the version is the same as the neoforge version. + // You can however also use the vanilla plugin (net.neoforged.gradle.vanilla) to use a version of Minecraft without the neoforge loader. + // And its provides the option to then use net.minecraft as the group, and one of; client, server or joined as the module name, plus the game version as version. + // For all intends and purposes: You can treat this dependency as if it is a normal library you would use. + implementation "net.neoforged:neoforge:${neo_version}" + + + implementation files ('advancedbackups-corelib.jar') + extraLibs files ('advancedbackups-corelib.jar') - // Example mod dependency with JEI - using fg.deobf() ensures the dependency is remapped to your development mappings + // Example mod dependency with JEI // The JEI API is declared for compile time use, while the full JEI artifact is used at runtime - // compileOnly fg.deobf("mezz.jei:jei-${mc_version}-common-api:${jei_version}") - // compileOnly fg.deobf("mezz.jei:jei-${mc_version}-forge-api:${jei_version}") - // runtimeOnly fg.deobf("mezz.jei:jei-${mc_version}-forge:${jei_version}") + // compileOnly "mezz.jei:jei-${mc_version}-common-api:${jei_version}" + // compileOnly "mezz.jei:jei-${mc_version}-forge-api:${jei_version}" + // runtimeOnly "mezz.jei:jei-${mc_version}-forge:${jei_version}" // Example mod dependency using a mod jar from ./libs with a flat dir repository // This maps to ./libs/coolmod-${mc_version}-${coolmod_version}.jar // The group id is ignored when searching -- in this case, it is "blank" - // implementation fg.deobf("blank:coolmod-${mc_version}:${coolmod_version}") + // implementation "blank:coolmod-${mc_version}:${coolmod_version}" - minecraftLibrary files ('advancedbackups-corelib.jar') - extraLibs files ('advancedbackups-corelib.jar') + // Example mod dependency using a file as dependency + // implementation files("libs/coolmod-${mc_version}-${coolmod_version}.jar") + + // Example project dependency using a sister or child project: + // implementation project(":myproject") // For more info: // http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html @@ -169,7 +124,7 @@ tasks.withType(ProcessResources).configureEach { minecraft_version : minecraft_version, minecraft_version_range: minecraft_version_range, neo_version : neo_version, neo_version_range: neo_version_range, loader_version_range: loader_version_range, - mod_id : mod_id, mod_name: mod_name, mod_license: mod_license, mod_version: mod_version, + mod_id : mod_id, mod_name: mod_name, mod_license: mod_license, mod_version: version, mod_authors : mod_authors, mod_description: mod_description, pack_format_number: pack_format_number, ] inputs.properties replaceProperties @@ -196,29 +151,22 @@ tasks.named('jar', Jar).configure { from { configurations.extraLibs.collect { it.isDirectory() ? it : zipTree(it) } } - // This is the preferred method to reobfuscate your jar file - finalizedBy 'reobfJar' } -// However if you are in a multi-project build, dev time needs unobfed jar files, so you can delay the obfuscation until publishing by doing: -// tasks.named('publish').configure { -// dependsOn 'reobfJar' -// } - // Example configuration to allow publishing using the maven-publish plugin publishing { publications { register('mavenJava', MavenPublication) { - artifact jar + from components.java } } repositories { maven { - url "file://${project.projectDir}/mcmodsrepo" + url "file://${project.projectDir}/repo" } } } tasks.withType(JavaCompile).configureEach { options.encoding = 'UTF-8' // Use the UTF-8 charset for Java compilation -} +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index a19b4b35..ba912535 100644 --- a/gradle.properties +++ b/gradle.properties @@ -7,17 +7,17 @@ org.gradle.daemon=false ## Environment Properties # The Minecraft version must agree with the Neo version to get a valid artifact -minecraft_version=1.20.1 +minecraft_version=1.20.2 # The Minecraft version range can use any release version of Minecraft as bounds. # Snapshots, pre-releases, and release candidates are not guaranteed to sort properly # as they do not follow standard versioning conventions. -minecraft_version_range=[1.20,1.22) +minecraft_version_range=[1.20.2,1.21) # The Neo version must agree with the Minecraft version to get a valid artifact -neo_version=47.1.65 +neo_version=20.2.35-beta # The Neo version range can use any version of Neo as bounds or match the loader version range -neo_version_range=[46,) +neo_version_range=[20.2,) # The loader version range can only use the major version of Neo/FML as bounds -loader_version_range=[46,) +loader_version_range=[1,) # The mapping channel to use for mappings. # The default set of supported mapping channels are ["official", "snapshot", "snapshot_nodoc", "stable", "stable_nodoc"]. # Additional mapping channels can be registered through the "channelProviders" extension in a Gradle plugin. @@ -35,7 +35,7 @@ loader_version_range=[46,) mapping_channel=official # The mapping version to query from the mapping channel. # This must match the format required by the mapping channel. -mapping_version=1.20.1 +mapping_version=1.20.2 ## Mod Properties @@ -58,8 +58,8 @@ mod_authors=Heather White # The description of the mod. This is a simple multiline text string that is used for display purposes in the mod list. mod_description=A highly advanced and configurable backup mod.\Github contains documentation. # Pack version - this changes each minecraft release, in general. -pack_format_number=15 +pack_format_number=18 -modloaderName =forge -minecraftVersion =1.20 \ No newline at end of file +modloaderName =neoforge +minecraftVersion =1.20.2 \ No newline at end of file diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 9ee90eda..60b7cd90 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -17,17 +17,17 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.level.storage.LevelResource; -import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.event.RegisterCommandsEvent; -import net.minecraftforge.event.TickEvent; -import net.minecraftforge.event.entity.player.PlayerEvent; -import net.minecraftforge.event.server.ServerStartedEvent; -import net.minecraftforge.event.server.ServerStartingEvent; -import net.minecraftforge.event.server.ServerStoppingEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.ModList; -import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.server.ServerLifecycleHooks; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.ModList; +import net.neoforged.fml.common.Mod; +import net.neoforged.neoforge.common.NeoForge; +import net.neoforged.neoforge.event.RegisterCommandsEvent; +import net.neoforged.neoforge.event.TickEvent; +import net.neoforged.neoforge.event.entity.player.PlayerEvent; +import net.neoforged.neoforge.event.server.ServerStartedEvent; +import net.neoforged.neoforge.event.server.ServerStartingEvent; +import net.neoforged.neoforge.event.server.ServerStoppingEvent; +import net.neoforged.neoforge.server.ServerLifecycleHooks; @Mod("advancedbackups") public class AdvancedBackups @@ -43,7 +43,7 @@ public class AdvancedBackups public AdvancedBackups() { // Register ourselves for server and other game events we are interested in - MinecraftForge.EVENT_BUS.register(this); + NeoForge.EVENT_BUS.register(this); NetworkHandler.register(); } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java index c08baf68..b355ca6d 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java @@ -1,15 +1,11 @@ package co.uk.mommyheather.advancedbackups.client; -import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.blaze3d.vertex.PoseStack; - import net.minecraft.ChatFormatting; -import net.minecraft.client.gui.Gui; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.components.toasts.Toast; import net.minecraft.client.gui.components.toasts.ToastComponent; -import net.minecraft.client.renderer.GameRenderer; import net.minecraft.client.resources.language.I18n; +import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; @@ -29,11 +25,12 @@ public class BackupToast implements Toast { private static boolean timeSet = false; public static final ItemStack stack = new ItemStack(Items.PAPER); + private static final ResourceLocation TEXTURE = new ResourceLocation("toast/advancement"); @Override public Visibility render(GuiGraphics graphics, ToastComponent toastGui, long delta) { - graphics.blit(TEXTURE, 0, 0, 0, 0, this.width(), this.height()); + graphics.blitSprite(TEXTURE, 0, 0, this.width(), this.height()); graphics.renderFakeItem(stack, 8, 8); diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java index ffa8bf23..de9dc73d 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java @@ -7,7 +7,7 @@ import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; -import net.minecraftforge.server.ServerLifecycleHooks; +import net.neoforged.neoforge.server.ServerLifecycleHooks; public class ClientContactor implements IClientContactor { diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java index 0c856fa0..2f754cab 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java @@ -2,9 +2,9 @@ import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; -import net.minecraftforge.network.NetworkDirection; -import net.minecraftforge.network.NetworkRegistry; -import net.minecraftforge.network.simple.SimpleChannel; +import net.neoforged.neoforge.network.NetworkRegistry; +import net.neoforged.neoforge.network.PlayNetworkDirection; +import net.neoforged.neoforge.network.simple.SimpleChannel; public class NetworkHandler { @@ -31,7 +31,7 @@ public static void register() { } public static void sendToClient(ServerPlayer player, Object packet) { - INSTANCE.sendTo(packet, player.connection.connection, NetworkDirection.PLAY_TO_CLIENT); + INSTANCE.sendTo(packet, player.connection.connection, PlayNetworkDirection.PLAY_TO_CLIENT); } } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java index 78f1fe90..1b520851 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java @@ -1,13 +1,11 @@ package co.uk.mommyheather.advancedbackups.network; -import java.util.function.Supplier; import co.uk.mommyheather.advancedbackups.client.BackupToast; import co.uk.mommyheather.advancedbackups.client.ClientWrapper; -import net.minecraft.client.Minecraft; import net.minecraft.network.FriendlyByteBuf; -import net.minecraftforge.fml.LogicalSide; -import net.minecraftforge.network.NetworkEvent; +import net.neoforged.fml.LogicalSide; +import net.neoforged.neoforge.network.NetworkEvent; public class PacketBackupStatus { @@ -52,20 +50,20 @@ public void toBytes(FriendlyByteBuf buf) { buf.writeInt(max); } - public boolean handle(Supplier ctx) { - BackupToast.starting = starting; - BackupToast.started = started; - BackupToast.failed = failed; - BackupToast.finished = finished; + public static boolean handle(PacketBackupStatus packet, NetworkEvent.Context ctx) { + BackupToast.starting = packet.starting; + BackupToast.started = packet.started; + BackupToast.failed = packet.failed; + BackupToast.finished = packet.finished; - BackupToast.progress = progress; - BackupToast.max = max; - ctx.get().enqueueWork(() -> { - if (ctx.get().getDirection().getReceptionSide() == LogicalSide.CLIENT) { - ClientWrapper.handle(this); + BackupToast.progress = packet.progress; + BackupToast.max = packet.max; + ctx.enqueueWork(() -> { + if (ctx.getDirection().getReceptionSide() == LogicalSide.CLIENT) { + ClientWrapper.handle(packet); } }); - ctx.get().setPacketHandled(true); + ctx.setPacketHandled(true); return true; } diff --git a/src/main/resources/META-INF/mods.toml b/src/main/resources/META-INF/mods.toml index c9e2c40c..b0ad9f84 100644 --- a/src/main/resources/META-INF/mods.toml +++ b/src/main/resources/META-INF/mods.toml @@ -43,7 +43,7 @@ description='''${mod_description}''' # A dependency - use the . to indicate dependency for a specific modid. Dependencies are optional. [[dependencies.${mod_id}]] #optional # the modid of the dependency - modId="forge" #mandatory + modId="neoforge" #mandatory # Does this dependency have to exist - if not, ordering below must be specified mandatory=true #mandatory # The version range of the dependency From 62abcd2bbd8cdc7eb50682f4708847567ca1b4dc Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Mon, 20 Nov 2023 20:18:35 +0000 Subject: [PATCH 389/580] Allow running commands when in singleplayer with cheats off. ( #47 ) --- .../advancedbackups/AdvancedBackupsCommand.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index 1788e5f4..bca69d50 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -36,6 +36,13 @@ public String getCommandUsage(ICommandSender icommandsender) return "/backup (start|reload-config|reset-chain|snapshot)"; } + @Override + public boolean canCommandSenderUseCommand(ICommandSender sender) + { + return !AdvancedBackups.server.isDedicatedServer() || super.canCommandSenderUseCommand(sender); + } + + @Override public void processCommand(ICommandSender sender, String[] args) throws CommandException { From f764347998b81ad5a187ba6293f1f95a19e3772d Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Mon, 20 Nov 2023 20:43:58 +0000 Subject: [PATCH 390/580] fix an NPE and show backup progress in singleplayer with cheats off ( #47 ) --- .../co/uk/mommyheather/advancedbackups/AdvancedBackups.java | 1 + .../mommyheather/advancedbackups/client/ABClientContactor.java | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 78e4e71a..444ff38d 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -96,6 +96,7 @@ public void onServerStarting(FMLServerStartingEvent event) ABCore.errorLogger = errorLogger; ABCore.clientContactor = new ABClientContactor(); + ABCore.resetActivity = AdvancedBackups::resetActivity; event.registerServerCommand(new AdvancedBackupsCommand()); diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ABClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ABClientContactor.java index 94b2e12f..ea350828 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ABClientContactor.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ABClientContactor.java @@ -23,7 +23,8 @@ public void backupComplete() { configurationManager.playerEntityList.forEach((player) -> { if (player instanceof EntityPlayerMP) { EntityPlayerMP playerMP = (EntityPlayerMP) player; - if (playerMP.canCommandSenderUseCommand(3, "advancedbackups")) { //if they can run the command, they should receive info on active backups + //if they can run the command, or are in singleplayer, they should receive info on active backups. + if (playerMP.canCommandSenderUseCommand(3, "advancedbackups") || !AdvancedBackups.server.isDedicatedServer()) { NetworkHandler.HANDLER.sendTo(packet, playerMP); } } From c48ba1e02611ccee648dbb207f1c192010741c3d Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Mon, 20 Nov 2023 20:56:42 +0000 Subject: [PATCH 391/580] remove version statment from AdvancedBackups class (so forge uses the mcmod.info file) --- .../co/uk/mommyheather/advancedbackups/AdvancedBackups.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 444ff38d..5a82eadc 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -36,12 +36,11 @@ import java.lang.reflect.Method; import java.util.function.Consumer; -@Mod(modid = AdvancedBackups.MODID, name = AdvancedBackups.NAME, version = AdvancedBackups.VERSION, acceptableRemoteVersions = "*") +@Mod(modid = AdvancedBackups.MODID, name = AdvancedBackups.NAME, acceptableRemoteVersions = "*") public class AdvancedBackups { public static final String MODID = "advancedbackups"; public static final String NAME = "Advanced Backups"; - public static final String VERSION = "2.0"; private static Logger LOGGER; public static Consumer infoLogger; From a8c1d3edfa851b492c68e1716292aa1e21c7b3c5 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Mon, 20 Nov 2023 21:24:39 +0000 Subject: [PATCH 392/580] remove versioning info from main class. allow command running on local, non-cheat worlds ( #47 ) --- .../advancedbackups/AdvancedBackups.java | 3 +- .../AdvancedBackupsCommand.java | 40 ++++++++++++++++--- 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 8c920f0c..e3f7ac05 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -30,13 +30,12 @@ import net.minecraftforge.fml.relauncher.Side; -@Mod(modid = AdvancedBackups.MODID, name = AdvancedBackups.NAME, version = AdvancedBackups.VERSION, acceptableRemoteVersions = "*") +@Mod(modid = AdvancedBackups.MODID, name = AdvancedBackups.NAME, acceptableRemoteVersions = "*") @EventBusSubscriber public class AdvancedBackups { public static final String MODID = "advancedbackups"; public static final String NAME = "Advanced Backups"; - public static final String VERSION = "0.3"; private static Logger LOGGER; public static Consumer infoLogger; diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index 7e32fc40..fa89e9b5 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -17,26 +17,32 @@ public AdvancedBackupsCommand() addSubcommand(new ResetChain()); addSubcommand(new Snapshot()); } - + @Override public String getName() { return "backup"; } - - + + @Override public int getRequiredPermissionLevel() { return 3; } - + @Override public String getUsage(ICommandSender icommandsender) { return "/backup (check|start|reload-config|snapshot)"; } - + + @Override + public boolean checkPermission(MinecraftServer server, ICommandSender sender) + { + return !AdvancedBackups.server.isDedicatedServer() || super.checkPermission(server, sender); + } + public static class Reload extends CommandTreeBase { public Reload(){} @Override @@ -54,6 +60,12 @@ public String getName() public String getUsage(ICommandSender sender) { return "commands.backup.reload-config.usage"; } + + @Override + public boolean checkPermission(MinecraftServer server, ICommandSender sender) + { + return !AdvancedBackups.server.isDedicatedServer() || super.checkPermission(server, sender); + } } public static class Start extends CommandTreeBase { @@ -73,6 +85,12 @@ public String getName() public String getUsage(ICommandSender sender) { return "commands.backup.start.usage"; } + + @Override + public boolean checkPermission(MinecraftServer server, ICommandSender sender) + { + return !AdvancedBackups.server.isDedicatedServer() || super.checkPermission(server, sender); + } } public static class ResetChain extends CommandTreeBase { @@ -92,6 +110,12 @@ public String getName() public String getUsage(ICommandSender sender) { return "commands.backup.resetchain.usage"; } + + @Override + public boolean checkPermission(MinecraftServer server, ICommandSender sender) + { + return !AdvancedBackups.server.isDedicatedServer() || super.checkPermission(server, sender); + } } public static class Snapshot extends CommandTreeBase { @@ -111,5 +135,11 @@ public String getName() public String getUsage(ICommandSender sender) { return "commands.backup.snapshot.usage"; } + + @Override + public boolean checkPermission(MinecraftServer server, ICommandSender sender) + { + return !AdvancedBackups.server.isDedicatedServer() || super.checkPermission(server, sender); + } } } From b80d470446e186136944108512057a41887befb3 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Mon, 20 Nov 2023 21:33:07 +0000 Subject: [PATCH 393/580] send progress toasts to client on a no-cheat local server ( #47 ) --- .../advancedbackups/client/ClientContactor.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java index 1a5d639e..46cef30d 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java @@ -15,7 +15,7 @@ public void backupComplete() { List players = AdvancedBackups.server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, 0, 0); for (EntityPlayerMP player : players) { - if (player.canUseCommand(3, "backup")) { + if (!AdvancedBackups.server.isDedicatedServer() || player.canUseCommand(3, "backup")) { NetworkHandler.HANDLER.sendTo(packet, player); } } @@ -26,7 +26,7 @@ public void backupFailed() { List players = AdvancedBackups.server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, 0, 0); for (EntityPlayerMP player : players) { - if (player.canUseCommand(3, "backup")) { + if (!AdvancedBackups.server.isDedicatedServer() || player.canUseCommand(3, "backup")) { NetworkHandler.HANDLER.sendTo(packet, player); } } @@ -37,7 +37,7 @@ public void backupProgress(int progress, int max) { List players = AdvancedBackups.server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, progress, max); for (EntityPlayerMP player : players) { - if (player.canUseCommand(3, "backup")) { + if (!AdvancedBackups.server.isDedicatedServer() || player.canUseCommand(3, "backup")) { NetworkHandler.HANDLER.sendTo(packet, player); } } @@ -48,7 +48,7 @@ public void backupStarting() { List players = AdvancedBackups.server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, 0, 0); for (EntityPlayerMP player : players) { - if (player.canUseCommand(3, "backup")) { + if (!AdvancedBackups.server.isDedicatedServer() || player.canUseCommand(3, "backup")) { NetworkHandler.HANDLER.sendTo(packet, player); } } From 5ae5dcc7678b66e311c7800b3647257d9ac60f47 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Mon, 20 Nov 2023 21:57:37 +0000 Subject: [PATCH 394/580] 1.16 - #47 --- .../advancedbackups/AdvancedBackupsCommand.java | 3 ++- .../advancedbackups/client/ClientContactor.java | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index a075fef2..ad98f04d 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -6,11 +6,12 @@ import net.minecraft.command.CommandSource; import net.minecraft.command.Commands; import net.minecraft.util.text.StringTextComponent; +import net.minecraftforge.fml.server.ServerLifecycleHooks; public class AdvancedBackupsCommand { public static void register(CommandDispatcher stack) { stack.register(Commands.literal("backup").requires((runner) -> { - return runner.hasPermission(3); + return !ServerLifecycleHooks.getCurrentServer().isDedicatedServer() || runner.hasPermission(3); }).then(Commands.literal("start").executes((runner) -> { CoreCommandSystem.startBackup((response) -> { runner.getSource().sendSuccess(new StringTextComponent(response), true); diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java index 7589193a..cf1948f9 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java @@ -18,7 +18,7 @@ public void backupComplete() { List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, 0, 0); for (ServerPlayerEntity player : players) { - if (player.hasPermissions(3)) { + if (!server.isDedicatedServer() || player.hasPermissions(3)) { NetworkHandler.sendToClient(player, packet); } } @@ -30,7 +30,7 @@ public void backupFailed() { List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, 0, 0); for (ServerPlayerEntity player : players) { - if (player.hasPermissions(3)) { + if (!server.isDedicatedServer() || player.hasPermissions(3)) { NetworkHandler.sendToClient(player, packet); } } @@ -42,7 +42,7 @@ public void backupProgress(int progress, int max) { List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, progress, max); for (ServerPlayerEntity player : players) { - if (player.hasPermissions(3)) { + if (!server.isDedicatedServer() || player.hasPermissions(3)) { NetworkHandler.sendToClient(player, packet); } } @@ -54,7 +54,7 @@ public void backupStarting() { List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, 0, 0); for (ServerPlayerEntity player : players) { - if (player.hasPermissions(3)) { + if (!server.isDedicatedServer() || player.hasPermissions(3)) { NetworkHandler.sendToClient(player, packet); } } From 078851f98102417e5443e9f6eabe682b92d3a9db Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Mon, 20 Nov 2023 22:21:55 +0000 Subject: [PATCH 395/580] let command run in no-cheat singleplayer ( #47 ) --- .../uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index 8504c006..4f39606a 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -10,7 +10,7 @@ public class AdvancedBackupsCommand { public static void register(CommandDispatcher stack) { stack.register(CommandManager.literal("backup").requires((runner) -> { - return runner.hasPermissionLevel(3); + return !AdvancedBackups.server.isDedicated() || runner.hasPermissionLevel(3); }).then(CommandManager.literal("start").executes((runner) -> { CoreCommandSystem.startBackup((response) -> { runner.getSource().sendFeedback(Text.of(response), true); From c33421c6d802df69f9b82f82e216af238f38f69d Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Mon, 20 Nov 2023 22:31:44 +0000 Subject: [PATCH 396/580] show toast to client on cheatless sp world ( #47 ) --- .../advancedbackups/client/ClientContactor.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java index 7b8e9237..cf5137e9 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java @@ -17,7 +17,7 @@ public void backupComplete() { List players = server.getPlayerManager().getPlayerList(); PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, 0, 0); for (ServerPlayerEntity player : players) { - if (player.hasPermissionLevel(3)) { + if (!server.isDedicated() || player.hasPermissionLevel(3)) { NetworkHandler.sendToClient(player, packet); } } @@ -29,7 +29,7 @@ public void backupFailed() { List players = server.getPlayerManager().getPlayerList(); PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, 0, 0); for (ServerPlayerEntity player : players) { - if (player.hasPermissionLevel(3)) { + if (!server.isDedicated() || player.hasPermissionLevel(3)) { NetworkHandler.sendToClient(player, packet); } } @@ -41,7 +41,7 @@ public void backupProgress(int progress, int max) { List players = server.getPlayerManager().getPlayerList(); PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, progress, max); for (ServerPlayerEntity player : players) { - if (player.hasPermissionLevel(3)) { + if (!server.isDedicated() || player.hasPermissionLevel(3)) { NetworkHandler.sendToClient(player, packet); } } @@ -53,7 +53,7 @@ public void backupStarting() { List players = server.getPlayerManager().getPlayerList(); PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, 0, 0); for (ServerPlayerEntity player : players) { - if (player.hasPermissionLevel(3)) { + if (!server.isDedicated() || player.hasPermissionLevel(3)) { NetworkHandler.sendToClient(player, packet); } } From 566009dd4e460b8eeff1744ec279c8beea11cbc9 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Mon, 20 Nov 2023 22:52:48 +0000 Subject: [PATCH 397/580] support #47, forge 1.18 --- .../advancedbackups/AdvancedBackupsCommand.java | 3 ++- .../advancedbackups/client/ClientContactor.java | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index 142ec783..5ee3460d 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -6,11 +6,12 @@ import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.Commands; import net.minecraft.network.chat.TextComponent; +import net.minecraftforge.server.ServerLifecycleHooks; public class AdvancedBackupsCommand { public static void register(CommandDispatcher stack) { stack.register(Commands.literal("backup").requires((runner) -> { - return runner.hasPermission(3); + return !ServerLifecycleHooks.getCurrentServer().isDedicatedServer() || runner.hasPermission(3); }).then(Commands.literal("start").executes((runner) -> { CoreCommandSystem.startBackup((response) -> { runner.getSource().sendSuccess(new TextComponent(response), true); diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java index ffa8bf23..2c72a8c7 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java @@ -17,7 +17,7 @@ public void backupComplete() { List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, 0, 0); for (ServerPlayer player : players) { - if (player.hasPermissions(3)) { + if (!server.isDedicatedServer() || player.hasPermissions(3)) { NetworkHandler.sendToClient(player, packet); } } @@ -29,7 +29,7 @@ public void backupFailed() { List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, 0, 0); for (ServerPlayer player : players) { - if (player.hasPermissions(3)) { + if (!server.isDedicatedServer() || player.hasPermissions(3)) { NetworkHandler.sendToClient(player, packet); } } @@ -41,7 +41,7 @@ public void backupProgress(int progress, int max) { List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, progress, max); for (ServerPlayer player : players) { - if (player.hasPermissions(3)) { + if (!server.isDedicatedServer() || player.hasPermissions(3)) { NetworkHandler.sendToClient(player, packet); } } @@ -53,7 +53,7 @@ public void backupStarting() { List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, 0, 0); for (ServerPlayer player : players) { - if (player.hasPermissions(3)) { + if (!server.isDedicatedServer() || player.hasPermissions(3)) { NetworkHandler.sendToClient(player, packet); } } From 7d72177b2dae5187c959a8b60fa6e964e1803cd9 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Mon, 20 Nov 2023 23:20:45 +0000 Subject: [PATCH 398/580] support #47, 1.19.2 fabric --- .../advancedbackups/AdvancedBackupsCommand.java | 2 +- .../advancedbackups/client/ClientContactor.java | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index 8504c006..4f39606a 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -10,7 +10,7 @@ public class AdvancedBackupsCommand { public static void register(CommandDispatcher stack) { stack.register(CommandManager.literal("backup").requires((runner) -> { - return runner.hasPermissionLevel(3); + return !AdvancedBackups.server.isDedicated() || runner.hasPermissionLevel(3); }).then(CommandManager.literal("start").executes((runner) -> { CoreCommandSystem.startBackup((response) -> { runner.getSource().sendFeedback(Text.of(response), true); diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java index 7b8e9237..cf5137e9 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java @@ -17,7 +17,7 @@ public void backupComplete() { List players = server.getPlayerManager().getPlayerList(); PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, 0, 0); for (ServerPlayerEntity player : players) { - if (player.hasPermissionLevel(3)) { + if (!server.isDedicated() || player.hasPermissionLevel(3)) { NetworkHandler.sendToClient(player, packet); } } @@ -29,7 +29,7 @@ public void backupFailed() { List players = server.getPlayerManager().getPlayerList(); PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, 0, 0); for (ServerPlayerEntity player : players) { - if (player.hasPermissionLevel(3)) { + if (!server.isDedicated() || player.hasPermissionLevel(3)) { NetworkHandler.sendToClient(player, packet); } } @@ -41,7 +41,7 @@ public void backupProgress(int progress, int max) { List players = server.getPlayerManager().getPlayerList(); PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, progress, max); for (ServerPlayerEntity player : players) { - if (player.hasPermissionLevel(3)) { + if (!server.isDedicated() || player.hasPermissionLevel(3)) { NetworkHandler.sendToClient(player, packet); } } @@ -53,7 +53,7 @@ public void backupStarting() { List players = server.getPlayerManager().getPlayerList(); PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, 0, 0); for (ServerPlayerEntity player : players) { - if (player.hasPermissionLevel(3)) { + if (!server.isDedicated() || player.hasPermissionLevel(3)) { NetworkHandler.sendToClient(player, packet); } } From 5956be8b391ab07e04aec3653a19c89f6009fdd6 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 21 Nov 2023 13:37:10 +0000 Subject: [PATCH 399/580] support #47 on forge 1.19.2 --- .../advancedbackups/AdvancedBackupsCommand.java | 3 ++- .../advancedbackups/client/ClientContactor.java | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index 0ab938e5..e611ccc0 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -6,11 +6,12 @@ import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.Commands; import net.minecraft.network.chat.Component; +import net.minecraftforge.server.ServerLifecycleHooks; public class AdvancedBackupsCommand { public static void register(CommandDispatcher stack) { stack.register(Commands.literal("backup").requires((runner) -> { - return runner.hasPermission(3); + return !ServerLifecycleHooks.getCurrentServer().isDedicatedServer() || runner.hasPermission(3); }).then(Commands.literal("start").executes((runner) -> { CoreCommandSystem.startBackup((response) -> { runner.getSource().sendSuccess(Component.literal(response), true); diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java index ffa8bf23..2c72a8c7 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java @@ -17,7 +17,7 @@ public void backupComplete() { List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, 0, 0); for (ServerPlayer player : players) { - if (player.hasPermissions(3)) { + if (!server.isDedicatedServer() || player.hasPermissions(3)) { NetworkHandler.sendToClient(player, packet); } } @@ -29,7 +29,7 @@ public void backupFailed() { List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, 0, 0); for (ServerPlayer player : players) { - if (player.hasPermissions(3)) { + if (!server.isDedicatedServer() || player.hasPermissions(3)) { NetworkHandler.sendToClient(player, packet); } } @@ -41,7 +41,7 @@ public void backupProgress(int progress, int max) { List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, progress, max); for (ServerPlayer player : players) { - if (player.hasPermissions(3)) { + if (!server.isDedicatedServer() || player.hasPermissions(3)) { NetworkHandler.sendToClient(player, packet); } } @@ -53,7 +53,7 @@ public void backupStarting() { List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, 0, 0); for (ServerPlayer player : players) { - if (player.hasPermissions(3)) { + if (!server.isDedicatedServer() || player.hasPermissions(3)) { NetworkHandler.sendToClient(player, packet); } } From 5e0f93cabc6de9defd6ab6e2b24bb58175beb8d1 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 21 Nov 2023 14:35:58 +0000 Subject: [PATCH 400/580] support #47 on fabric 1.19.3 --- .../advancedbackups/AdvancedBackupsCommand.java | 2 +- .../advancedbackups/client/ClientContactor.java | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index 8504c006..4f39606a 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -10,7 +10,7 @@ public class AdvancedBackupsCommand { public static void register(CommandDispatcher stack) { stack.register(CommandManager.literal("backup").requires((runner) -> { - return runner.hasPermissionLevel(3); + return !AdvancedBackups.server.isDedicated() || runner.hasPermissionLevel(3); }).then(CommandManager.literal("start").executes((runner) -> { CoreCommandSystem.startBackup((response) -> { runner.getSource().sendFeedback(Text.of(response), true); diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java index 7b8e9237..4b125b1a 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java @@ -17,7 +17,7 @@ public void backupComplete() { List players = server.getPlayerManager().getPlayerList(); PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, 0, 0); for (ServerPlayerEntity player : players) { - if (player.hasPermissionLevel(3)) { + if (!AdvancedBackups.server.isDedicated() || player.hasPermissionLevel(3)) { NetworkHandler.sendToClient(player, packet); } } @@ -29,7 +29,7 @@ public void backupFailed() { List players = server.getPlayerManager().getPlayerList(); PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, 0, 0); for (ServerPlayerEntity player : players) { - if (player.hasPermissionLevel(3)) { + if (!AdvancedBackups.server.isDedicated() || player.hasPermissionLevel(3)) { NetworkHandler.sendToClient(player, packet); } } @@ -41,7 +41,7 @@ public void backupProgress(int progress, int max) { List players = server.getPlayerManager().getPlayerList(); PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, progress, max); for (ServerPlayerEntity player : players) { - if (player.hasPermissionLevel(3)) { + if (!AdvancedBackups.server.isDedicated() || player.hasPermissionLevel(3)) { NetworkHandler.sendToClient(player, packet); } } @@ -53,7 +53,7 @@ public void backupStarting() { List players = server.getPlayerManager().getPlayerList(); PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, 0, 0); for (ServerPlayerEntity player : players) { - if (player.hasPermissionLevel(3)) { + if (!AdvancedBackups.server.isDedicated() || player.hasPermissionLevel(3)) { NetworkHandler.sendToClient(player, packet); } } From abf5c1db440db8ee7d55076373c70a5e3860abf1 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 21 Nov 2023 14:52:28 +0000 Subject: [PATCH 401/580] support #47 on forge 1.19.3 --- .../advancedbackups/AdvancedBackupsCommand.java | 3 ++- .../advancedbackups/client/ClientContactor.java | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index 0ab938e5..e611ccc0 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -6,11 +6,12 @@ import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.Commands; import net.minecraft.network.chat.Component; +import net.minecraftforge.server.ServerLifecycleHooks; public class AdvancedBackupsCommand { public static void register(CommandDispatcher stack) { stack.register(Commands.literal("backup").requires((runner) -> { - return runner.hasPermission(3); + return !ServerLifecycleHooks.getCurrentServer().isDedicatedServer() || runner.hasPermission(3); }).then(Commands.literal("start").executes((runner) -> { CoreCommandSystem.startBackup((response) -> { runner.getSource().sendSuccess(Component.literal(response), true); diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java index ffa8bf23..2c72a8c7 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java @@ -17,7 +17,7 @@ public void backupComplete() { List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, 0, 0); for (ServerPlayer player : players) { - if (player.hasPermissions(3)) { + if (!server.isDedicatedServer() || player.hasPermissions(3)) { NetworkHandler.sendToClient(player, packet); } } @@ -29,7 +29,7 @@ public void backupFailed() { List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, 0, 0); for (ServerPlayer player : players) { - if (player.hasPermissions(3)) { + if (!server.isDedicatedServer() || player.hasPermissions(3)) { NetworkHandler.sendToClient(player, packet); } } @@ -41,7 +41,7 @@ public void backupProgress(int progress, int max) { List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, progress, max); for (ServerPlayer player : players) { - if (player.hasPermissions(3)) { + if (!server.isDedicatedServer() || player.hasPermissions(3)) { NetworkHandler.sendToClient(player, packet); } } @@ -53,7 +53,7 @@ public void backupStarting() { List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, 0, 0); for (ServerPlayer player : players) { - if (player.hasPermissions(3)) { + if (!server.isDedicatedServer() || player.hasPermissions(3)) { NetworkHandler.sendToClient(player, packet); } } From c6fd27b6e6dc4f2f09474c3c449ff391afc62bdd Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 21 Nov 2023 15:21:43 +0000 Subject: [PATCH 402/580] support #47 on fabric 1.20.2 --- .../advancedbackups/AdvancedBackupsCommand.java | 2 +- .../advancedbackups/client/ClientContactor.java | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index 4ce0b5f5..78bbdc6f 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -10,7 +10,7 @@ public class AdvancedBackupsCommand { public static void register(CommandDispatcher stack) { stack.register(CommandManager.literal("backup").requires((runner) -> { - return runner.hasPermissionLevel(3); + return !AdvancedBackups.server.isDedicated() || runner.hasPermissionLevel(3); }).then(CommandManager.literal("start").executes((runner) -> { CoreCommandSystem.startBackup((response) -> { runner.getSource().sendFeedback(() -> Text.of(response), true); diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java index 7b8e9237..cf5137e9 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java @@ -17,7 +17,7 @@ public void backupComplete() { List players = server.getPlayerManager().getPlayerList(); PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, 0, 0); for (ServerPlayerEntity player : players) { - if (player.hasPermissionLevel(3)) { + if (!server.isDedicated() || player.hasPermissionLevel(3)) { NetworkHandler.sendToClient(player, packet); } } @@ -29,7 +29,7 @@ public void backupFailed() { List players = server.getPlayerManager().getPlayerList(); PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, 0, 0); for (ServerPlayerEntity player : players) { - if (player.hasPermissionLevel(3)) { + if (!server.isDedicated() || player.hasPermissionLevel(3)) { NetworkHandler.sendToClient(player, packet); } } @@ -41,7 +41,7 @@ public void backupProgress(int progress, int max) { List players = server.getPlayerManager().getPlayerList(); PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, progress, max); for (ServerPlayerEntity player : players) { - if (player.hasPermissionLevel(3)) { + if (!server.isDedicated() || player.hasPermissionLevel(3)) { NetworkHandler.sendToClient(player, packet); } } @@ -53,7 +53,7 @@ public void backupStarting() { List players = server.getPlayerManager().getPlayerList(); PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, 0, 0); for (ServerPlayerEntity player : players) { - if (player.hasPermissionLevel(3)) { + if (!server.isDedicated() || player.hasPermissionLevel(3)) { NetworkHandler.sendToClient(player, packet); } } From e92197aa0e7e9a4145838ae17d143e004a75f926 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Wed, 22 Nov 2023 13:26:36 +0000 Subject: [PATCH 403/580] support #47 on forge 1.20.2 --- .../advancedbackups/AdvancedBackupsCommand.java | 3 ++- .../advancedbackups/client/ClientContactor.java | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index 48919de9..5fa3344e 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -6,11 +6,12 @@ import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.Commands; import net.minecraft.network.chat.Component; +import net.minecraftforge.server.ServerLifecycleHooks; public class AdvancedBackupsCommand { public static void register(CommandDispatcher stack) { stack.register(Commands.literal("backup").requires((runner) -> { - return runner.hasPermission(3); + return !ServerLifecycleHooks.getCurrentServer().isDedicatedServer() || runner.hasPermission(3); }).then(Commands.literal("start").executes((runner) -> { CoreCommandSystem.startBackup((response) -> { runner.getSource().sendSuccess(() -> { diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java index ffa8bf23..2c72a8c7 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java @@ -17,7 +17,7 @@ public void backupComplete() { List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, 0, 0); for (ServerPlayer player : players) { - if (player.hasPermissions(3)) { + if (!server.isDedicatedServer() || player.hasPermissions(3)) { NetworkHandler.sendToClient(player, packet); } } @@ -29,7 +29,7 @@ public void backupFailed() { List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, 0, 0); for (ServerPlayer player : players) { - if (player.hasPermissions(3)) { + if (!server.isDedicatedServer() || player.hasPermissions(3)) { NetworkHandler.sendToClient(player, packet); } } @@ -41,7 +41,7 @@ public void backupProgress(int progress, int max) { List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, progress, max); for (ServerPlayer player : players) { - if (player.hasPermissions(3)) { + if (!server.isDedicatedServer() || player.hasPermissions(3)) { NetworkHandler.sendToClient(player, packet); } } @@ -53,7 +53,7 @@ public void backupStarting() { List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, 0, 0); for (ServerPlayer player : players) { - if (player.hasPermissions(3)) { + if (!server.isDedicatedServer() || player.hasPermissions(3)) { NetworkHandler.sendToClient(player, packet); } } From ed67655d15aa4264076042db66131a955a739e5a Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Wed, 22 Nov 2023 13:48:56 +0000 Subject: [PATCH 404/580] support #47 on neoforge 1.20.2 --- .../advancedbackups/AdvancedBackupsCommand.java | 3 ++- .../advancedbackups/client/ClientContactor.java | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index 48919de9..4a0f1512 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -6,11 +6,12 @@ import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.Commands; import net.minecraft.network.chat.Component; +import net.neoforged.neoforge.server.ServerLifecycleHooks; public class AdvancedBackupsCommand { public static void register(CommandDispatcher stack) { stack.register(Commands.literal("backup").requires((runner) -> { - return runner.hasPermission(3); + return !ServerLifecycleHooks.getCurrentServer().isDedicatedServer() || runner.hasPermission(3); }).then(Commands.literal("start").executes((runner) -> { CoreCommandSystem.startBackup((response) -> { runner.getSource().sendSuccess(() -> { diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java index de9dc73d..f3fd1905 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java @@ -17,7 +17,7 @@ public void backupComplete() { List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, 0, 0); for (ServerPlayer player : players) { - if (player.hasPermissions(3)) { + if (!server.isDedicatedServer() || player.hasPermissions(3)) { NetworkHandler.sendToClient(player, packet); } } @@ -29,7 +29,7 @@ public void backupFailed() { List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, 0, 0); for (ServerPlayer player : players) { - if (player.hasPermissions(3)) { + if (!server.isDedicatedServer() || player.hasPermissions(3)) { NetworkHandler.sendToClient(player, packet); } } @@ -41,7 +41,7 @@ public void backupProgress(int progress, int max) { List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, progress, max); for (ServerPlayer player : players) { - if (player.hasPermissions(3)) { + if (!server.isDedicatedServer() || player.hasPermissions(3)) { NetworkHandler.sendToClient(player, packet); } } @@ -53,7 +53,7 @@ public void backupStarting() { List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, 0, 0); for (ServerPlayer player : players) { - if (player.hasPermissions(3)) { + if (!server.isDedicatedServer() || player.hasPermissions(3)) { NetworkHandler.sendToClient(player, packet); } } From fe6a4689b88fd606179bc19506eaa69447aaf66c Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Wed, 22 Nov 2023 18:31:35 +0000 Subject: [PATCH 405/580] support #47 on fabric 1.20 --- .../advancedbackups/AdvancedBackupsCommand.java | 2 +- .../advancedbackups/client/ClientContactor.java | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index 4ce0b5f5..78bbdc6f 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -10,7 +10,7 @@ public class AdvancedBackupsCommand { public static void register(CommandDispatcher stack) { stack.register(CommandManager.literal("backup").requires((runner) -> { - return runner.hasPermissionLevel(3); + return !AdvancedBackups.server.isDedicated() || runner.hasPermissionLevel(3); }).then(CommandManager.literal("start").executes((runner) -> { CoreCommandSystem.startBackup((response) -> { runner.getSource().sendFeedback(() -> Text.of(response), true); diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java index 7b8e9237..cf5137e9 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java @@ -17,7 +17,7 @@ public void backupComplete() { List players = server.getPlayerManager().getPlayerList(); PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, 0, 0); for (ServerPlayerEntity player : players) { - if (player.hasPermissionLevel(3)) { + if (!server.isDedicated() || player.hasPermissionLevel(3)) { NetworkHandler.sendToClient(player, packet); } } @@ -29,7 +29,7 @@ public void backupFailed() { List players = server.getPlayerManager().getPlayerList(); PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, 0, 0); for (ServerPlayerEntity player : players) { - if (player.hasPermissionLevel(3)) { + if (!server.isDedicated() || player.hasPermissionLevel(3)) { NetworkHandler.sendToClient(player, packet); } } @@ -41,7 +41,7 @@ public void backupProgress(int progress, int max) { List players = server.getPlayerManager().getPlayerList(); PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, progress, max); for (ServerPlayerEntity player : players) { - if (player.hasPermissionLevel(3)) { + if (!server.isDedicated() || player.hasPermissionLevel(3)) { NetworkHandler.sendToClient(player, packet); } } @@ -53,7 +53,7 @@ public void backupStarting() { List players = server.getPlayerManager().getPlayerList(); PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, 0, 0); for (ServerPlayerEntity player : players) { - if (player.hasPermissionLevel(3)) { + if (!server.isDedicated() || player.hasPermissionLevel(3)) { NetworkHandler.sendToClient(player, packet); } } From bba29b1340891016f607f11638d74509deb7b4a9 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Thu, 23 Nov 2023 15:36:12 +0000 Subject: [PATCH 406/580] support #47 in forge 1.20 --- .../advancedbackups/AdvancedBackupsCommand.java | 3 ++- .../advancedbackups/client/ClientContactor.java | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index 48919de9..5fa3344e 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -6,11 +6,12 @@ import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.Commands; import net.minecraft.network.chat.Component; +import net.minecraftforge.server.ServerLifecycleHooks; public class AdvancedBackupsCommand { public static void register(CommandDispatcher stack) { stack.register(Commands.literal("backup").requires((runner) -> { - return runner.hasPermission(3); + return !ServerLifecycleHooks.getCurrentServer().isDedicatedServer() || runner.hasPermission(3); }).then(Commands.literal("start").executes((runner) -> { CoreCommandSystem.startBackup((response) -> { runner.getSource().sendSuccess(() -> { diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java index ffa8bf23..2c72a8c7 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java @@ -17,7 +17,7 @@ public void backupComplete() { List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, 0, 0); for (ServerPlayer player : players) { - if (player.hasPermissions(3)) { + if (!server.isDedicatedServer() || player.hasPermissions(3)) { NetworkHandler.sendToClient(player, packet); } } @@ -29,7 +29,7 @@ public void backupFailed() { List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, 0, 0); for (ServerPlayer player : players) { - if (player.hasPermissions(3)) { + if (!server.isDedicatedServer() || player.hasPermissions(3)) { NetworkHandler.sendToClient(player, packet); } } @@ -41,7 +41,7 @@ public void backupProgress(int progress, int max) { List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, progress, max); for (ServerPlayer player : players) { - if (player.hasPermissions(3)) { + if (!server.isDedicatedServer() || player.hasPermissions(3)) { NetworkHandler.sendToClient(player, packet); } } @@ -53,7 +53,7 @@ public void backupStarting() { List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, 0, 0); for (ServerPlayer player : players) { - if (player.hasPermissions(3)) { + if (!server.isDedicatedServer() || player.hasPermissions(3)) { NetworkHandler.sendToClient(player, packet); } } From 2777d36b592ecc9dc21edd3aa9794fa36939ce56 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Fri, 15 Dec 2023 10:40:58 +0000 Subject: [PATCH 407/580] begin supporting new client config changes! I'm never certain whether this should be a pr or not... relevant to #49. --- .../advancedbackups/AdvancedBackups.java | 17 +++++++++-- .../AdvancedBackupsCommand.java | 5 ++++ .../advancedbackups/client/BackupToast.java | 29 ++++++++++++------- .../advancedbackups/client/ClientWrapper.java | 23 +++++++++++++++ 4 files changed, 61 insertions(+), 13 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 92cdc856..baf40708 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -8,6 +8,7 @@ import org.apache.logging.log4j.Logger; import co.uk.mommyheather.advancedbackups.client.ClientContactor; +import co.uk.mommyheather.advancedbackups.client.ClientWrapper; import co.uk.mommyheather.advancedbackups.core.ABCore; import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; @@ -24,9 +25,11 @@ import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.ModList; import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; import net.minecraftforge.fml.event.server.FMLServerStartedEvent; import net.minecraftforge.fml.event.server.FMLServerStartingEvent; import net.minecraftforge.fml.event.server.FMLServerStoppingEvent; +import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; import net.minecraftforge.fml.server.ServerLifecycleHooks; @Mod("advancedbackups") @@ -44,7 +47,14 @@ public AdvancedBackups() { // Register ourselves for server and other game events we are interested in MinecraftForge.EVENT_BUS.register(this); + + FMLJavaModLoadingContext.get().getModEventBus().addListener(this::clientSetup); NetworkHandler.register(); + + + ABCore.infoLogger = infoLogger; + ABCore.warningLogger = warningLogger; + ABCore.errorLogger = errorLogger; } @SubscribeEvent @@ -59,9 +69,6 @@ public void onServerStarting(FMLServerStartingEvent event) ABCore.enableSaving = AdvancedBackups::enableSaving; ABCore.saveOnce = AdvancedBackups::saveOnce; - ABCore.infoLogger = infoLogger; - ABCore.warningLogger = warningLogger; - ABCore.errorLogger = errorLogger; ABCore.resetActivity = AdvancedBackups::resetActivity; @@ -74,6 +81,10 @@ public void onServerStarting(FMLServerStartingEvent event) } + public void clientSetup(FMLClientSetupEvent e) { + ClientWrapper.init(e); + } + @SubscribeEvent public void onServerStarted(FMLServerStartedEvent event) { BackupWrapper.checkStartupBackups(); diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index ad98f04d..d2f1709f 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -26,6 +26,11 @@ public static void register(CommandDispatcher stack) { return 1; })) + .then(Commands.literal("reload-client-config").executes((runner) -> { + runner.getSource().sendSuccess(new StringTextComponent("This command can only be ran on a client!"), true); + return 1; + })) + .then(Commands.literal("reset-chain").executes((runner) -> { CoreCommandSystem.resetChainLength((response) -> { runner.getSource().sendSuccess(new StringTextComponent(response), true); diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java index ea65b5d0..85dbe908 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java @@ -4,6 +4,7 @@ import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.systems.RenderSystem; +import co.uk.mommyheather.advancedbackups.core.config.ClientConfigManager; import net.minecraft.client.gui.AbstractGui; import net.minecraft.client.gui.toasts.IToast; import net.minecraft.client.gui.toasts.ToastGui; @@ -11,7 +12,7 @@ import net.minecraft.client.resources.I18n; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; -import net.minecraft.util.text.TextFormatting; +import net.minecraft.util.ColorHelper; public class BackupToast implements IToast { @@ -30,23 +31,27 @@ public class BackupToast implements IToast { public static final ItemStack stack = new ItemStack(Items.PAPER); + private int textColour; + @Override public Visibility render(MatrixStack matrix, ToastGui toastGui, long delta) { toastGui.getMinecraft().getTextureManager().bind(TEXTURE); RenderSystem.color3f(1.0F, 1.0F, 1.0F); - toastGui.blit(matrix, 0, 0, 0, 0, this.width(), this.height()); + toastGui.blit(matrix, 0, 0, 0, ClientConfigManager.darkMode.get() ? 0 : this.height(), this.width(), this.height()); toastGui.getMinecraft().getItemRenderer().renderAndDecorateFakeItem(stack, 8, 8); float percent = finished ? 100 : (float) progress / (float) max; - AbstractGui.fill(matrix, 3, 28, 156, 29, -1); + AbstractGui.fill(matrix, 3, 28, 156, 29, ColorHelper.PackedColor.color + (255, (int) ClientConfigManager.progressBackgroundRed.get(), (int) ClientConfigManager.progressBackgroundGreen.get(), (int) ClientConfigManager.progressBackgroundBlue.get())); float f = Math.min(156, ( 156 * percent )); - if (!exists) { - toastGui.getMinecraft().font.draw(matrix, TextFormatting.GREEN + I18n.get("advancedbackups.backup_finished"), 25, 11, -11534256); + if (!exists) { + textColour = ColorHelper.PackedColor.color(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); + toastGui.getMinecraft().font.draw(matrix, I18n.get("advancedbackups.backup_finished"), 25, 11, textColour); AbstractGui.fill(matrix, 3, 28, 156, 29, -10948014); return Visibility.HIDE; } @@ -55,27 +60,31 @@ public Visibility render(MatrixStack matrix, ToastGui toastGui, long delta) { if (starting) { - title = TextFormatting.GREEN + I18n.get("advancedbackups.backup_starting"); + textColour = ColorHelper.PackedColor.color(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); + title = I18n.get("advancedbackups.backup_starting"); } else if (started) { - title = TextFormatting.GREEN + I18n.get("advancedbackups.progress", round(percent * 100)); + textColour = ColorHelper.PackedColor.color(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); + title = I18n.get("advancedbackups.progress", round(percent * 100)); } else if (failed) { - title = TextFormatting.RED + I18n.get("advancedbackups.backup_failed"); + textColour = ColorHelper.PackedColor.color(255, (int) ClientConfigManager.errorTextRed.get(), (int) ClientConfigManager.errorTextGreen.get(), (int) ClientConfigManager.errorTextBlue.get()); + title = I18n.get("advancedbackups.backup_failed"); if (!timeSet) { time = System.currentTimeMillis(); timeSet = true; } } else if (finished) { - title = TextFormatting.GREEN + I18n.get("advancedbackups.backup_finished"); + textColour = ColorHelper.PackedColor.color(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); + title = I18n.get("advancedbackups.backup_finished"); if (!timeSet) { time = System.currentTimeMillis(); timeSet = true; } } - toastGui.getMinecraft().font.draw(matrix, title, 25, 11, -11534256); + toastGui.getMinecraft().font.draw(matrix, title, 25, 11, textColour); if (timeSet && System.currentTimeMillis() >= time + 5000) { starting = false; diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java index a9fd2a4c..2da0d2e4 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java @@ -2,9 +2,17 @@ import java.util.function.Supplier; +import co.uk.mommyheather.advancedbackups.core.CoreCommandSystem; +import co.uk.mommyheather.advancedbackups.core.config.ClientConfigManager; import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; import net.minecraft.client.Minecraft; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.client.event.ClientChatEvent; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.LogicalSide; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; import net.minecraftforge.fml.network.NetworkEvent.Context; public class ClientWrapper { @@ -28,5 +36,20 @@ public static void handle(Supplier ctx, PacketBackupStatus packet) { } }); } + + public static void init(FMLClientSetupEvent e) { + MinecraftForge.EVENT_BUS.addListener(ClientWrapper::onClientChat); + ClientConfigManager.loadOrCreateConfig(); + } + + @SubscribeEvent + public static void onClientChat(ClientChatEvent event) { + if (event.getMessage().equals("/backup reload-client-config")) { + event.setCanceled(true); + + CoreCommandSystem.reloadClientConfig(Minecraft.getInstance().player::chat); + } + + } } From 6680986c988118c4b723ec01ee9798381fac9222 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Fri, 15 Dec 2023 10:45:01 +0000 Subject: [PATCH 408/580] fix this damm 1 pixel error, on 1.16 at least. --- .../co/uk/mommyheather/advancedbackups/client/BackupToast.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java index 85dbe908..cd5f437f 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java @@ -43,7 +43,7 @@ public Visibility render(MatrixStack matrix, ToastGui toastGui, long delta) { float percent = finished ? 100 : (float) progress / (float) max; - AbstractGui.fill(matrix, 3, 28, 156, 29, ColorHelper.PackedColor.color + AbstractGui.fill(matrix, 4, 28, 156, 29, ColorHelper.PackedColor.color (255, (int) ClientConfigManager.progressBackgroundRed.get(), (int) ClientConfigManager.progressBackgroundGreen.get(), (int) ClientConfigManager.progressBackgroundBlue.get())); float f = Math.min(156, ( 156 * percent From 65405d7fc76bb8bf54c56fea292a28376fe642c5 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Fri, 15 Dec 2023 10:46:29 +0000 Subject: [PATCH 409/580] continue wokring on client contact impl --- .../uk/mommyheather/advancedbackups/client/BackupToast.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java index cd5f437f..a4b9ea61 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java @@ -13,6 +13,7 @@ import net.minecraft.item.ItemStack; import net.minecraft.item.Items; import net.minecraft.util.ColorHelper; +import net.minecraft.util.ColorHelper.PackedColor; public class BackupToast implements IToast { @@ -98,7 +99,8 @@ else if (finished) { return Visibility.HIDE; } - AbstractGui.fill(matrix, 3, 28, Math.max(3, (int) f), 29, -10948014); + AbstractGui.fill(matrix, 3, 28, Math.max(3, (int) f), 29, ColorHelper.PackedColor.color + (255, (int) ClientConfigManager.progressBarRed.get(), (int) ClientConfigManager.progressBarGreen.get(), (int) ClientConfigManager.progressBarBlue.get())); return Visibility.SHOW; From 67ee2b834579f80c0e0889eb5f37944b8fdccd90 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Fri, 15 Dec 2023 10:57:39 +0000 Subject: [PATCH 410/580] clean up imports --- .../co/uk/mommyheather/advancedbackups/client/BackupToast.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java index a4b9ea61..7579f2aa 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java @@ -1,19 +1,16 @@ package co.uk.mommyheather.advancedbackups.client; import com.mojang.blaze3d.matrix.MatrixStack; -import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.systems.RenderSystem; import co.uk.mommyheather.advancedbackups.core.config.ClientConfigManager; import net.minecraft.client.gui.AbstractGui; import net.minecraft.client.gui.toasts.IToast; import net.minecraft.client.gui.toasts.ToastGui; -import net.minecraft.client.renderer.RenderHelper; import net.minecraft.client.resources.I18n; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; import net.minecraft.util.ColorHelper; -import net.minecraft.util.ColorHelper.PackedColor; public class BackupToast implements IToast { From e56198638a21bb7af32b81740847f3c9e3afa59c Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Fri, 15 Dec 2023 11:50:44 +0000 Subject: [PATCH 411/580] Clients are now required to "subscribe" to progress updates. ( #49 ) --- .../advancedbackups/AdvancedBackups.java | 3 ++ .../client/ClientContactor.java | 4 ++ .../advancedbackups/client/ClientWrapper.java | 9 +++- .../network/NetworkHandler.java | 10 +++++ .../network/PacketToastSubscribe.java | 41 +++++++++++++++++++ 5 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index baf40708..3fa83351 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -1,6 +1,7 @@ package co.uk.mommyheather.advancedbackups; +import java.util.ArrayList; import java.util.List; import java.util.function.Consumer; @@ -42,6 +43,8 @@ public class AdvancedBackups public static final Consumer warningLogger = LOGGER::warn; public static final Consumer errorLogger = LOGGER::error; + public static final ArrayList players = new ArrayList<>(); + public AdvancedBackups() { diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java index cf1948f9..e20d9700 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java @@ -18,6 +18,7 @@ public void backupComplete() { List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, 0, 0); for (ServerPlayerEntity player : players) { + if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; if (!server.isDedicatedServer() || player.hasPermissions(3)) { NetworkHandler.sendToClient(player, packet); } @@ -30,6 +31,7 @@ public void backupFailed() { List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, 0, 0); for (ServerPlayerEntity player : players) { + if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; if (!server.isDedicatedServer() || player.hasPermissions(3)) { NetworkHandler.sendToClient(player, packet); } @@ -42,6 +44,7 @@ public void backupProgress(int progress, int max) { List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, progress, max); for (ServerPlayerEntity player : players) { + if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; if (!server.isDedicatedServer() || player.hasPermissions(3)) { NetworkHandler.sendToClient(player, packet); } @@ -54,6 +57,7 @@ public void backupStarting() { List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, 0, 0); for (ServerPlayerEntity player : players) { + if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; if (!server.isDedicatedServer() || player.hasPermissions(3)) { NetworkHandler.sendToClient(player, packet); } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java index 2da0d2e4..6b41ae55 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java @@ -4,10 +4,13 @@ import co.uk.mommyheather.advancedbackups.core.CoreCommandSystem; import co.uk.mommyheather.advancedbackups.core.config.ClientConfigManager; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; +import co.uk.mommyheather.advancedbackups.network.PacketToastSubscribe; import net.minecraft.client.Minecraft; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.client.event.ClientChatEvent; +import net.minecraftforge.client.event.ClientPlayerNetworkEvent; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.LogicalSide; @@ -39,10 +42,10 @@ public static void handle(Supplier ctx, PacketBackupStatus packet) { public static void init(FMLClientSetupEvent e) { MinecraftForge.EVENT_BUS.addListener(ClientWrapper::onClientChat); + MinecraftForge.EVENT_BUS.addListener(ClientWrapper::onServerConnected); ClientConfigManager.loadOrCreateConfig(); } - @SubscribeEvent public static void onClientChat(ClientChatEvent event) { if (event.getMessage().equals("/backup reload-client-config")) { event.setCanceled(true); @@ -51,5 +54,9 @@ public static void onClientChat(ClientChatEvent event) { } } + + public static void onServerConnected(ClientPlayerNetworkEvent.LoggedInEvent event) { + NetworkHandler.sendToServer(new PacketToastSubscribe(ClientConfigManager.showProgress.get())); + } } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java index f9107760..6037e8d6 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java @@ -28,10 +28,20 @@ public static void register() { .decoder(buf -> new PacketBackupStatus(buf)) .consumer(PacketBackupStatus::handle) .add(); + + INSTANCE.messageBuilder(PacketToastSubscribe.class, id()) + .encoder(PacketToastSubscribe::toBytes) + .decoder(buf -> new PacketToastSubscribe(buf)) + .consumer(PacketToastSubscribe::handle) + .add(); } public static void sendToClient(ServerPlayerEntity player, Object packet) { INSTANCE.sendTo(packet, player.connection.connection, NetworkDirection.PLAY_TO_CLIENT); } + public static void sendToServer(Object packet) { + INSTANCE.sendToServer(packet); + } + } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java new file mode 100644 index 00000000..e4753921 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java @@ -0,0 +1,41 @@ +package co.uk.mommyheather.advancedbackups.network; + +import java.util.function.Supplier; + +import co.uk.mommyheather.advancedbackups.AdvancedBackups; +import net.minecraft.network.PacketBuffer; +import net.minecraftforge.fml.network.NetworkDirection; +import net.minecraftforge.fml.network.NetworkEvent; + +public class PacketToastSubscribe { + + private boolean enable; + + public PacketToastSubscribe(boolean enable) { + this.enable = enable; + } + + + public PacketToastSubscribe(PacketBuffer buf) { + enable = buf.readBoolean(); + } + + public void toBytes(PacketBuffer buf) { + buf.writeBoolean(enable); + } + + public boolean handle(Supplier ctx) { + ctx.get().enqueueWork(() -> { + if (enable && !AdvancedBackups.players.contains(ctx.get().getSender().getStringUUID())) { + AdvancedBackups.players.add(ctx.get().getSender().getStringUUID()); + } + else if (!enable) { + AdvancedBackups.players.remove(ctx.get().getSender().getStringUUID()); + } + }); + + return true; + + } + +} From 72fa1e7b1abb1c14603b8ff1c48471fded14a450 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sat, 13 Jan 2024 20:58:43 +0000 Subject: [PATCH 412/580] new localisation needed --- src/main/resources/assets/advancedbackups/lang/en_US.lang | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/resources/assets/advancedbackups/lang/en_US.lang b/src/main/resources/assets/advancedbackups/lang/en_US.lang index eeca5f50..d17123fa 100644 --- a/src/main/resources/assets/advancedbackups/lang/en_US.lang +++ b/src/main/resources/assets/advancedbackups/lang/en_US.lang @@ -1,4 +1,5 @@ advancedbackups.backup_starting=Backup starting! advancedbackups.progress=Backup in progress : %s%% advancedbackups.backup_failed=Backup failed : check log for more info. +advancedbackups.backup_cancelled=Backup cancelled! advancedbackups.backup_finished=Backup complete! \ No newline at end of file From 1cb119c805c098d41072152308dff62b21f63623 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sun, 14 Jan 2024 23:46:23 +0000 Subject: [PATCH 413/580] support cancelling render and send subscribe packet --- .../client/ABClientRenderer.java | 42 ++++++++++++++++--- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ABClientRenderer.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ABClientRenderer.java index 5615ebb0..2745dd5b 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ABClientRenderer.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ABClientRenderer.java @@ -2,13 +2,12 @@ import com.mojang.realmsclient.gui.ChatFormatting; -import cpw.mods.fml.common.Mod.EventHandler; +import co.uk.mommyheather.advancedbackups.core.config.ClientConfigManager; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; +import co.uk.mommyheather.advancedbackups.network.PacketToastSubscribe; import cpw.mods.fml.common.eventhandler.SubscribeEvent; -import net.minecraft.client.Minecraft; +import cpw.mods.fml.common.network.FMLNetworkEvent.ClientConnectedToServerEvent; import net.minecraft.client.resources.I18n; -import net.minecraft.init.Items; -import net.minecraft.item.Item; -import net.minecraft.stats.Achievement; import net.minecraftforge.client.event.RenderGameOverlayEvent; public class ABClientRenderer { @@ -18,6 +17,7 @@ public class ABClientRenderer { public static boolean started; public static boolean failed; public static boolean finished; + public static boolean cancelled; public static int progress; public static int max; @@ -27,6 +27,9 @@ public class ABClientRenderer { private static boolean timeSet = false; + public static final ABClientRenderer INSTANCE = new ABClientRenderer(); + + @SubscribeEvent public void onRenderEvent(RenderGameOverlayEvent.Text event) { if (starting) { @@ -50,6 +53,13 @@ else if (finished) { timeSet = true; } } + else if (cancelled) { + event.left.add(ChatFormatting.RED + I18n.format("advancedbackups.backup_cancelled")); + if (!timeSet) { + time = System.currentTimeMillis(); + timeSet = true; + } + } if (timeSet && System.currentTimeMillis() >= time + 5000) { @@ -57,6 +67,7 @@ else if (finished) { started = false; failed = false; finished = false; + cancelled = false; progress = 0; max = 0; timeSet = false; @@ -67,5 +78,26 @@ else if (finished) { private static String round (float value) { return String.format("%.1f", value); } + + + @SubscribeEvent + public void onServerConnected(ClientConnectedToServerEvent event) { + //may aswell just do it here. 1.7 is so horribly documented + ClientConfigManager.loadOrCreateConfig(); + + + //NetworkHandler.HANDLER.sendToServer(new PacketToastSubscribe(ClientConfigManager.showProgress.get())); + + //You serious? If I use the above line, the packet is just never received. + //TODO : rework this in a nicer way. Use something other than a fucking threaded one second delay. + new Thread(() -> { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + + } + NetworkHandler.HANDLER.sendToServer(new PacketToastSubscribe(ClientConfigManager.showProgress.get())); + }).start(); + } } From e2f707c3221470248443e661f7b05f4b88539bf6 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sun, 14 Jan 2024 23:55:16 +0000 Subject: [PATCH 414/580] more clientside config + toast subscription stuff --- .../advancedbackups/AdvancedBackups.java | 8 +-- .../client/ABClientContactor.java | 27 ++++++++-- .../network/NetworkHandler.java | 1 + .../network/PacketBackupStatus.java | 7 ++- .../network/PacketToastSubscribe.java | 53 +++++++++++++++++++ 5 files changed, 88 insertions(+), 8 deletions(-) create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 5a82eadc..c378312d 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -32,8 +32,7 @@ import net.minecraftforge.common.MinecraftForge; import java.io.File; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; +import java.util.ArrayList; import java.util.function.Consumer; @Mod(modid = AdvancedBackups.MODID, name = AdvancedBackups.NAME, acceptableRemoteVersions = "*") @@ -47,6 +46,8 @@ public class AdvancedBackups public static Consumer warningLogger; public static Consumer errorLogger; + public static ArrayList players = new ArrayList<>(); + public static MinecraftServer server; @EventHandler @@ -64,8 +65,9 @@ public AdvancedBackups() { // Register ourselves for server and other game events we are interested in MinecraftForge.EVENT_BUS.register(this); - MinecraftForge.EVENT_BUS.register(new ABClientRenderer()); FMLCommonHandler.instance().bus().register(this); + MinecraftForge.EVENT_BUS.register(ABClientRenderer.INSTANCE); + FMLCommonHandler.instance().bus().register(ABClientRenderer.INSTANCE); NetworkHandler.init(); } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ABClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ABClientContactor.java index ea350828..6f73fd5e 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ABClientContactor.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ABClientContactor.java @@ -19,10 +19,11 @@ public class ABClientContactor implements IClientContactor { @Override public void backupComplete() { ServerConfigurationManager configurationManager = AdvancedBackups.server.getConfigurationManager(); - PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, 0, 0); + PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, false, 0, 0); configurationManager.playerEntityList.forEach((player) -> { if (player instanceof EntityPlayerMP) { EntityPlayerMP playerMP = (EntityPlayerMP) player; + if (!AdvancedBackups.players.contains(playerMP.getGameProfile().getId().toString())) return; //if they can run the command, or are in singleplayer, they should receive info on active backups. if (playerMP.canCommandSenderUseCommand(3, "advancedbackups") || !AdvancedBackups.server.isDedicatedServer()) { NetworkHandler.HANDLER.sendTo(packet, playerMP); @@ -34,10 +35,11 @@ public void backupComplete() { @Override public void backupFailed() { ServerConfigurationManager configurationManager = AdvancedBackups.server.getConfigurationManager(); - PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, 0, 0); + PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, false, 0, 0); configurationManager.playerEntityList.forEach((player) -> { if (player instanceof EntityPlayerMP) { EntityPlayerMP playerMP = (EntityPlayerMP) player; + if (!AdvancedBackups.players.contains(playerMP.getGameProfile().getId().toString())) return; if (playerMP.canCommandSenderUseCommand(3, "advancedbackups")) { //if they can run the command, they should receive info on active backups NetworkHandler.HANDLER.sendTo(packet, playerMP); } @@ -48,10 +50,11 @@ public void backupFailed() { @Override public void backupProgress(int progress, int max) { ServerConfigurationManager configurationManager = AdvancedBackups.server.getConfigurationManager(); - PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, progress, max); + PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, false, progress, max); configurationManager.playerEntityList.forEach((player) -> { if (player instanceof EntityPlayerMP) { EntityPlayerMP playerMP = (EntityPlayerMP) player; + if (!AdvancedBackups.players.contains(playerMP.getGameProfile().getId().toString())) return; if (playerMP.canCommandSenderUseCommand(3, "advancedbackups")) { //if they can run the command, they should receive info on active backups NetworkHandler.HANDLER.sendTo(packet, playerMP); } @@ -62,10 +65,26 @@ public void backupProgress(int progress, int max) { @Override public void backupStarting() { ServerConfigurationManager configurationManager = AdvancedBackups.server.getConfigurationManager(); - PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, 0, 0); + PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, false, 0, 0); configurationManager.playerEntityList.forEach((player) -> { if (player instanceof EntityPlayerMP) { EntityPlayerMP playerMP = (EntityPlayerMP) player; + if (!AdvancedBackups.players.contains(playerMP.getGameProfile().getId().toString())) return; + if (playerMP.canCommandSenderUseCommand(3, "advancedbackups")) { //if they can run the command, they should receive info on active backups + NetworkHandler.HANDLER.sendTo(packet, playerMP); + } + } + }); + } + + @Override + public void backupCancelled() { + ServerConfigurationManager configurationManager = AdvancedBackups.server.getConfigurationManager(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, false, false, true, 0, 0); + configurationManager.playerEntityList.forEach((player) -> { + if (player instanceof EntityPlayerMP) { + EntityPlayerMP playerMP = (EntityPlayerMP) player; + if (!AdvancedBackups.players.contains(playerMP.getGameProfile().getId().toString())) return; if (playerMP.canCommandSenderUseCommand(3, "advancedbackups")) { //if they can run the command, they should receive info on active backups NetworkHandler.HANDLER.sendTo(packet, playerMP); } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java index 3c2a8135..0989d992 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java @@ -11,6 +11,7 @@ public class NetworkHandler { public static void init() { HANDLER.registerMessage(new PacketBackupStatus.Handler(), PacketBackupStatus.class, 1, Side.CLIENT); + HANDLER.registerMessage(new PacketToastSubscribe.Handler(), PacketToastSubscribe.class, 2, Side.SERVER); } } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java index c893993f..d8bd5e94 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java @@ -11,17 +11,19 @@ public class PacketBackupStatus implements IMessage{ public boolean started; public boolean failed; public boolean finished; + public boolean cancelled; public int progress; public int max; - public PacketBackupStatus(boolean starting, boolean started, boolean failed, boolean finished, int progress, + public PacketBackupStatus(boolean starting, boolean started, boolean failed, boolean finished, boolean cancelled, int progress, int max) { this.starting = starting; this.started = started; this.failed = failed; this.finished = finished; + this.cancelled = cancelled; this.progress = progress; this.max = max; } @@ -36,6 +38,7 @@ public void fromBytes(ByteBuf buf) { started = buf.readBoolean(); failed = buf.readBoolean(); finished = buf.readBoolean(); + cancelled = buf.readBoolean(); progress = buf.readInt(); max = buf.readInt(); @@ -47,6 +50,7 @@ public void toBytes(ByteBuf buf) { buf.writeBoolean(started); buf.writeBoolean(failed); buf.writeBoolean(finished); + buf.writeBoolean(cancelled); buf.writeInt(progress); buf.writeInt(max); @@ -63,6 +67,7 @@ public IMessage onMessage(PacketBackupStatus message, MessageContext ctx) { ABClientRenderer.started = message.started; ABClientRenderer.failed = message.failed; ABClientRenderer.finished = message.finished; + ABClientRenderer.cancelled = message.cancelled; ABClientRenderer.progress = message.progress; ABClientRenderer.max = message.max; diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java new file mode 100644 index 00000000..92d0a8a5 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java @@ -0,0 +1,53 @@ +package co.uk.mommyheather.advancedbackups.network; + +import co.uk.mommyheather.advancedbackups.AdvancedBackups; +import cpw.mods.fml.common.network.simpleimpl.IMessage; +import cpw.mods.fml.common.network.simpleimpl.IMessageHandler; +import cpw.mods.fml.common.network.simpleimpl.MessageContext; +import io.netty.buffer.ByteBuf; + +public class PacketToastSubscribe implements IMessage{ + + private boolean enable; + + public PacketToastSubscribe(boolean enable) { + this.enable = enable; + } + + public PacketToastSubscribe () { + + } + + @Override + public void fromBytes(ByteBuf buf) { + enable = buf.readBoolean(); + } + + @Override + public void toBytes(ByteBuf buf) { + buf.writeBoolean(enable); + } + + + public static class Handler implements IMessageHandler { + + @Override + public IMessage onMessage(PacketToastSubscribe message, MessageContext ctx) { + + String uuid = ctx.getServerHandler().playerEntity.getGameProfile().getId().toString(); + + + if (message.enable && !AdvancedBackups.players.contains(uuid)) { + AdvancedBackups.players.add(uuid); + } + else if (!message.enable) { + AdvancedBackups.players.remove(uuid); + } + + return null; + + } + + } + +} From 547b3970a98603720e282b6e2f65d73590098b73 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Mon, 15 Jan 2024 12:33:59 +0000 Subject: [PATCH 415/580] client config reloading. this should finish 1.7.10 v3.5? --- .../AdvancedBackupsCommand.java | 37 ++++++++++++++- .../client/ABClientContactor.java | 5 --- .../network/NetworkHandler.java | 1 + .../network/PacketClientReload.java | 45 +++++++++++++++++++ 4 files changed, 82 insertions(+), 6 deletions(-) create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/network/PacketClientReload.java diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index bca69d50..09138844 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -1,11 +1,14 @@ package co.uk.mommyheather.advancedbackups; import co.uk.mommyheather.advancedbackups.core.CoreCommandSystem; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; +import co.uk.mommyheather.advancedbackups.network.PacketClientReload; import net.minecraft.command.CommandBase; import net.minecraft.command.CommandException; import net.minecraft.command.ICommandSender; import net.minecraft.command.WrongUsageException; +import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.util.ChatComponentText; public class AdvancedBackupsCommand extends CommandBase @@ -33,7 +36,7 @@ public int getRequiredPermissionLevel() public String getCommandUsage(ICommandSender icommandsender) { - return "/backup (start|reload-config|reset-chain|snapshot)"; + return "/backup (start|reload-config|reload-client-config|reset-chain|snapshot|cancel)"; } @Override @@ -58,12 +61,19 @@ else if ("reload-config".equals(args[0])) { Reload.execute(sender); } + else if ("reload-client-config".equals(args[0])) + { + ReloadClient.execute(sender); + } else if ("reset-chain".equals(args[0])) { ResetChain.execute(sender); } else if ("snapshot".equals(args[0])) { Snapshot.execute(sender); } + else if ("cancel".equals(args[0])) { + Cancel.execute(sender); + } else { throw new WrongUsageException(getCommandUsage(sender)); @@ -76,6 +86,22 @@ public static void execute(ICommandSender sender) { sender.addChatMessage(new ChatComponentText(response)); }); } + } + + public static class ReloadClient { + public static void execute(ICommandSender sender) { + if (sender instanceof EntityPlayerMP) { + EntityPlayerMP player = (EntityPlayerMP) sender; + NetworkHandler.HANDLER.sendTo(new PacketClientReload(), player); + return; + } + sender.addChatMessage(new ChatComponentText("This can only be ran on the client!")); + /* + CoreCommandSystem.reloadClientConfig((response) -> { + sender.addChatMessage(new ChatComponentText(response)); + }); + */ + } } public static class Start { @@ -103,5 +129,14 @@ public static void execute(ICommandSender sender) { } + public static class Cancel { + public static void execute(ICommandSender sender) { + CoreCommandSystem.cancelBackup((response) -> { + sender.addChatMessage(new ChatComponentText(response)); + }); + } + + } + } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ABClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ABClientContactor.java index 6f73fd5e..9c922b95 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ABClientContactor.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ABClientContactor.java @@ -1,17 +1,12 @@ package co.uk.mommyheather.advancedbackups.client; -import java.util.HashMap; - -import com.mojang.authlib.GameProfile; import co.uk.mommyheather.advancedbackups.AdvancedBackups; -import co.uk.mommyheather.advancedbackups.AdvancedBackupsCommand; import co.uk.mommyheather.advancedbackups.interfaces.IClientContactor; import co.uk.mommyheather.advancedbackups.network.NetworkHandler; import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.server.management.ServerConfigurationManager; -import net.minecraft.world.WorldServer; @SuppressWarnings("unchecked") public class ABClientContactor implements IClientContactor { diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java index 0989d992..d44e1877 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java @@ -12,6 +12,7 @@ public static void init() { HANDLER.registerMessage(new PacketBackupStatus.Handler(), PacketBackupStatus.class, 1, Side.CLIENT); HANDLER.registerMessage(new PacketToastSubscribe.Handler(), PacketToastSubscribe.class, 2, Side.SERVER); + HANDLER.registerMessage(new PacketClientReload.Handler(), PacketClientReload.class, 3, Side.CLIENT); } } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketClientReload.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketClientReload.java new file mode 100644 index 00000000..6afbb2c8 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketClientReload.java @@ -0,0 +1,45 @@ +package co.uk.mommyheather.advancedbackups.network; + +import co.uk.mommyheather.advancedbackups.core.CoreCommandSystem; +import cpw.mods.fml.common.network.simpleimpl.IMessage; +import cpw.mods.fml.common.network.simpleimpl.IMessageHandler; +import cpw.mods.fml.common.network.simpleimpl.MessageContext; +import io.netty.buffer.ByteBuf; +import net.minecraft.client.Minecraft; + +//I hate this. +public class PacketClientReload implements IMessage{ + + + public PacketClientReload(boolean enable) { + + } + + public PacketClientReload () { + + } + + @Override + public void fromBytes(ByteBuf buf) { + + } + + @Override + public void toBytes(ByteBuf buf) { + + } + + + public static class Handler implements IMessageHandler { + + @Override + public IMessage onMessage(PacketClientReload message, MessageContext ctx) { + + CoreCommandSystem.reloadClientConfig(Minecraft.getMinecraft().thePlayer::sendChatMessage); + return null; + + } + + } + +} From 711851de5bd1749db273d8d44fc85187787663af Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Mon, 15 Jan 2024 12:59:19 +0000 Subject: [PATCH 416/580] Support + localise cancel command --- .../AdvancedBackupsCommand.java | 28 ++++++++++++++++++- .../advancedbackups/client/BackupToast.java | 8 ++++++ .../advancedbackups/client/ClientBridge.java | 1 + .../client/ClientContactor.java | 19 ++++++++++--- .../network/PacketBackupStatus.java | 6 +++- .../assets/advancedbackups/lang/en_us.lang | 1 + 6 files changed, 57 insertions(+), 6 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index fa89e9b5..5aef3e65 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -16,6 +16,7 @@ public AdvancedBackupsCommand() addSubcommand(new Reload()); addSubcommand(new ResetChain()); addSubcommand(new Snapshot()); + addSubcommand(new Cancel()); } @Override @@ -34,7 +35,7 @@ public int getRequiredPermissionLevel() @Override public String getUsage(ICommandSender icommandsender) { - return "/backup (check|start|reload-config|snapshot)"; + return "/backup (check|start|reload-config|snapshot|cancel)"; } @Override @@ -142,4 +143,29 @@ public boolean checkPermission(MinecraftServer server, ICommandSender sender) return !AdvancedBackups.server.isDedicatedServer() || super.checkPermission(server, sender); } } + + public static class Cancel extends CommandTreeBase { + public Cancel(){} + @Override + public void execute(MinecraftServer server, ICommandSender sender, String[] args) throws CommandException { + CoreCommandSystem.cancelBackup((response) -> { + sender.sendMessage(new TextComponentString(response)); + }); + } + @Override + public String getName() + { + return "cancel"; + } + @Override + public String getUsage(ICommandSender sender) { + return "commands.backup.cancel.usage"; + } + + @Override + public boolean checkPermission(MinecraftServer server, ICommandSender sender) + { + return !AdvancedBackups.server.isDedicatedServer() || super.checkPermission(server, sender); + } + } } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java index 70a90bcb..b73667f0 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java @@ -19,6 +19,7 @@ public class BackupToast implements IToast{ public static boolean started; public static boolean failed; public static boolean finished; + public static boolean cancelled; public static int progress; public static int max; @@ -69,6 +70,13 @@ else if (failed) { timeSet = true; } } + else if (cancelled) { + title = ChatFormatting.RED + I18n.format("advancedbackups.backup_cancelled"); + if (!timeSet) { + time = System.currentTimeMillis(); + timeSet = true; + } + } else if (finished) { title = ChatFormatting.GREEN + I18n.format("advancedbackups.backup_finished"); if (!timeSet) { diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientBridge.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientBridge.java index eb248361..1969cfa4 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientBridge.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientBridge.java @@ -12,6 +12,7 @@ public static void handle(PacketBackupStatus message) { BackupToast.started = message.started; BackupToast.failed = message.failed; BackupToast.finished = message.finished; + BackupToast.cancelled = message.cancelled; BackupToast.progress = message.progress; BackupToast.max = message.max; diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java index 46cef30d..2d65392a 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java @@ -13,7 +13,7 @@ public class ClientContactor implements IClientContactor { @Override public void backupComplete() { List players = AdvancedBackups.server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, 0, 0); + PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, false, 0, 0); for (EntityPlayerMP player : players) { if (!AdvancedBackups.server.isDedicatedServer() || player.canUseCommand(3, "backup")) { NetworkHandler.HANDLER.sendTo(packet, player); @@ -24,7 +24,7 @@ public void backupComplete() { @Override public void backupFailed() { List players = AdvancedBackups.server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, 0, 0); + PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, false, 0, 0); for (EntityPlayerMP player : players) { if (!AdvancedBackups.server.isDedicatedServer() || player.canUseCommand(3, "backup")) { NetworkHandler.HANDLER.sendTo(packet, player); @@ -35,7 +35,7 @@ public void backupFailed() { @Override public void backupProgress(int progress, int max) { List players = AdvancedBackups.server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, progress, max); + PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, false, progress, max); for (EntityPlayerMP player : players) { if (!AdvancedBackups.server.isDedicatedServer() || player.canUseCommand(3, "backup")) { NetworkHandler.HANDLER.sendTo(packet, player); @@ -46,7 +46,18 @@ public void backupProgress(int progress, int max) { @Override public void backupStarting() { List players = AdvancedBackups.server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, 0, 0); + PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, false, 0, 0); + for (EntityPlayerMP player : players) { + if (!AdvancedBackups.server.isDedicatedServer() || player.canUseCommand(3, "backup")) { + NetworkHandler.HANDLER.sendTo(packet, player); + } + } + } + + @Override + public void backupCancelled() { + List players = AdvancedBackups.server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, false, false, true, 0, 0); for (EntityPlayerMP player : players) { if (!AdvancedBackups.server.isDedicatedServer() || player.canUseCommand(3, "backup")) { NetworkHandler.HANDLER.sendTo(packet, player); diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java index af0d22d0..8600293e 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java @@ -11,17 +11,19 @@ public class PacketBackupStatus implements IMessage{ public boolean started; public boolean failed; public boolean finished; + public boolean cancelled; public int progress; public int max; - public PacketBackupStatus(boolean starting, boolean started, boolean failed, boolean finished, int progress, + public PacketBackupStatus(boolean starting, boolean started, boolean failed, boolean finished, boolean cancelled, int progress, int max) { this.starting = starting; this.started = started; this.failed = failed; this.finished = finished; + this.cancelled = cancelled; this.progress = progress; this.max = max; } @@ -36,6 +38,7 @@ public void fromBytes(ByteBuf buf) { started = buf.readBoolean(); failed = buf.readBoolean(); finished = buf.readBoolean(); + cancelled = buf.readBoolean(); progress = buf.readInt(); max = buf.readInt(); @@ -47,6 +50,7 @@ public void toBytes(ByteBuf buf) { buf.writeBoolean(started); buf.writeBoolean(failed); buf.writeBoolean(finished); + buf.writeBoolean(cancelled); buf.writeInt(progress); buf.writeInt(max); diff --git a/src/main/resources/assets/advancedbackups/lang/en_us.lang b/src/main/resources/assets/advancedbackups/lang/en_us.lang index 3fc16b27..37f62bc9 100644 --- a/src/main/resources/assets/advancedbackups/lang/en_us.lang +++ b/src/main/resources/assets/advancedbackups/lang/en_us.lang @@ -1,4 +1,5 @@ advancedbackups.backup_starting=Backup starting! advancedbackups.progress=Backup ongoing: %s%% advancedbackups.backup_failed=Backup failed!\nCheck log for more info. +advancedbackups.backup_cancelled=Backup cancelled! advancedbackups.backup_finished=Backup complete! \ No newline at end of file From 5426d711ad2ccd4ebdc9171c96ba5be25f0a57b1 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Mon, 15 Jan 2024 14:46:17 +0000 Subject: [PATCH 417/580] toast subscription shit --- .../advancedbackups/AdvancedBackups.java | 27 +++++++++ .../advancedbackups/client/BackupToast.java | 2 +- .../client/ClientContactor.java | 5 ++ .../network/NetworkHandler.java | 1 + .../network/PacketToastSubscribe.java | 58 +++++++++++++++++++ 5 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index e3f7ac05..f986fa42 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -1,17 +1,21 @@ package co.uk.mommyheather.advancedbackups; import java.io.File; +import java.util.ArrayList; import java.util.List; import java.util.function.Consumer; import org.apache.logging.log4j.Logger; +import co.uk.mommyheather.advancedbackups.client.ClientBridge; import co.uk.mommyheather.advancedbackups.client.ClientContactor; import co.uk.mommyheather.advancedbackups.core.ABCore; import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; +import co.uk.mommyheather.advancedbackups.core.config.ClientConfigManager; import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; import co.uk.mommyheather.advancedbackups.network.NetworkHandler; +import co.uk.mommyheather.advancedbackups.network.PacketToastSubscribe; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.server.MinecraftServer; import net.minecraft.world.WorldServer; @@ -27,6 +31,7 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.gameevent.PlayerEvent; import net.minecraftforge.fml.common.gameevent.TickEvent; +import net.minecraftforge.fml.common.network.FMLNetworkEvent.ClientConnectedToServerEvent; import net.minecraftforge.fml.relauncher.Side; @@ -42,6 +47,8 @@ public class AdvancedBackups public static Consumer warningLogger; public static Consumer errorLogger; + public static final ArrayList players = new ArrayList<>(); + public static MinecraftServer server; @EventHandler @@ -123,6 +130,26 @@ public void onTickEnd(TickEvent.ServerTickEvent event) { BackupTimer.check(); } + @SubscribeEvent + public void onConnectedToServer(ClientConnectedToServerEvent event) { + ClientConfigManager.loadOrCreateConfig(); + + + //NetworkHandler.HANDLER.sendToServer(new PacketToastSubscribe(ClientConfigManager.showProgress.get())); + + + //You serious? If I use the above line, the packet is just never received. + //TODO : rework this in a nicer way. Use something other than a fucking threaded five second delay. + new Thread(() -> { + try { + Thread.sleep(5000); + } catch (InterruptedException e) { + + } + NetworkHandler.HANDLER.sendToServer(new PacketToastSubscribe(ClientConfigManager.showProgress.get())); + }).start(); + } + public static final String savesDisabledMessage = "\n\n\n***************************************\nSAVING DISABLED - PREPARING FOR BACKUP!\n***************************************"; diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java index b73667f0..223bb781 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java @@ -10,7 +10,6 @@ import net.minecraft.client.resources.I18n; import net.minecraft.init.Items; import net.minecraft.item.ItemStack; -import net.minecraft.util.math.MathHelper; public class BackupToast implements IToast{ @@ -92,6 +91,7 @@ else if (finished) { started = false; failed = false; finished = false; + cancelled = false; progress = 0; max = 0; timeSet = false; diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java index 2d65392a..f7d450d2 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java @@ -15,6 +15,7 @@ public void backupComplete() { List players = AdvancedBackups.server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, false, 0, 0); for (EntityPlayerMP player : players) { + if (!AdvancedBackups.players.contains(player.getGameProfile().getId().toString())) continue; if (!AdvancedBackups.server.isDedicatedServer() || player.canUseCommand(3, "backup")) { NetworkHandler.HANDLER.sendTo(packet, player); } @@ -26,6 +27,7 @@ public void backupFailed() { List players = AdvancedBackups.server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, false, 0, 0); for (EntityPlayerMP player : players) { + if (!AdvancedBackups.players.contains(player.getGameProfile().getId().toString())) continue; if (!AdvancedBackups.server.isDedicatedServer() || player.canUseCommand(3, "backup")) { NetworkHandler.HANDLER.sendTo(packet, player); } @@ -37,6 +39,7 @@ public void backupProgress(int progress, int max) { List players = AdvancedBackups.server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, false, progress, max); for (EntityPlayerMP player : players) { + if (!AdvancedBackups.players.contains(player.getGameProfile().getId().toString())) continue; if (!AdvancedBackups.server.isDedicatedServer() || player.canUseCommand(3, "backup")) { NetworkHandler.HANDLER.sendTo(packet, player); } @@ -48,6 +51,7 @@ public void backupStarting() { List players = AdvancedBackups.server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, false, 0, 0); for (EntityPlayerMP player : players) { + if (!AdvancedBackups.players.contains(player.getGameProfile().getId().toString())) continue; if (!AdvancedBackups.server.isDedicatedServer() || player.canUseCommand(3, "backup")) { NetworkHandler.HANDLER.sendTo(packet, player); } @@ -59,6 +63,7 @@ public void backupCancelled() { List players = AdvancedBackups.server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(false, false, false, false, true, 0, 0); for (EntityPlayerMP player : players) { + if (!AdvancedBackups.players.contains(player.getGameProfile().getId().toString())) continue; if (!AdvancedBackups.server.isDedicatedServer() || player.canUseCommand(3, "backup")) { NetworkHandler.HANDLER.sendTo(packet, player); } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java index 06ba310a..1326c2eb 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java @@ -18,5 +18,6 @@ public static void registerMessages() { HANDLER = NetworkRegistry.INSTANCE.newSimpleChannel(AdvancedBackups.MODID); // Register messages which are sent from the client to the server here: HANDLER.registerMessage(PacketBackupStatus.Handler.class, PacketBackupStatus.class, nextID(), Side.CLIENT); + HANDLER.registerMessage(PacketToastSubscribe.Handler.class, PacketToastSubscribe.class, nextID(), Side.SERVER); } } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java new file mode 100644 index 00000000..6ef4c04b --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java @@ -0,0 +1,58 @@ +package co.uk.mommyheather.advancedbackups.network; + +import co.uk.mommyheather.advancedbackups.AdvancedBackups; +import io.netty.buffer.ByteBuf; +import net.minecraftforge.fml.common.network.simpleimpl.IMessage; +import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; +import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; + +public class PacketToastSubscribe implements IMessage{ + + public boolean enable; + + + public PacketToastSubscribe(boolean enable) { + this.enable = enable; + } + + public PacketToastSubscribe() { + + } + + @Override + public void fromBytes(ByteBuf buf) { + enable = buf.readBoolean(); + } + + @Override + public void toBytes(ByteBuf buf) { + buf.writeBoolean(enable); + } + + + public static class Handler implements IMessageHandler { + + @Override + public IMessage onMessage(PacketToastSubscribe message, MessageContext ctx) { + + String uuid = ctx.getServerHandler().player.getGameProfile().getId().toString(); + + + if (message.enable && !AdvancedBackups.players.contains(uuid)) { + AdvancedBackups.players.add(uuid); + } + else if (!message.enable) { + AdvancedBackups.players.remove(uuid); + } + + + return null; + + } + + } + + + + +} \ No newline at end of file From dc1977623158e0e671d4214b6dfbde17dd5873b4 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Mon, 15 Jan 2024 17:02:17 +0000 Subject: [PATCH 418/580] I'm not happy with this but now toast subscriptions work as intended --- .../advancedbackups/AdvancedBackups.java | 20 ++++++-- .../network/NetworkHandler.java | 1 + .../network/PacketToastTest.java | 50 +++++++++++++++++++ 3 files changed, 67 insertions(+), 4 deletions(-) create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastTest.java diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index f986fa42..b898812d 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -16,6 +16,7 @@ import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; import co.uk.mommyheather.advancedbackups.network.NetworkHandler; import co.uk.mommyheather.advancedbackups.network.PacketToastSubscribe; +import co.uk.mommyheather.advancedbackups.network.PacketToastTest; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.server.MinecraftServer; import net.minecraft.world.WorldServer; @@ -31,7 +32,10 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.gameevent.PlayerEvent; import net.minecraftforge.fml.common.gameevent.TickEvent; +import net.minecraftforge.fml.common.gameevent.PlayerEvent.PlayerChangedDimensionEvent; +import net.minecraftforge.fml.common.gameevent.PlayerEvent.PlayerLoggedInEvent; import net.minecraftforge.fml.common.network.FMLNetworkEvent.ClientConnectedToServerEvent; +import net.minecraftforge.fml.common.network.FMLNetworkEvent.ServerConnectionFromClientEvent; import net.minecraftforge.fml.relauncher.Side; @@ -131,15 +135,23 @@ public void onTickEnd(TickEvent.ServerTickEvent event) { } @SubscribeEvent - public void onConnectedToServer(ClientConnectedToServerEvent event) { - ClientConfigManager.loadOrCreateConfig(); + public void onConnectedToServer(PlayerLoggedInEvent event) { + //Here's our answer. + //Player logs in. Server sends them a packet. Client responds with a different packet to indicate their wish to subscribe to toasts. + //It means a single packet at login is sent to clients without the mod, but it should be dropped fine. + if (event.player instanceof EntityPlayerMP) { + NetworkHandler.HANDLER.sendTo(new PacketToastTest(), (EntityPlayerMP) event.player); + } + + + /*ClientConfigManager.loadOrCreateConfig(); //NetworkHandler.HANDLER.sendToServer(new PacketToastSubscribe(ClientConfigManager.showProgress.get())); //You serious? If I use the above line, the packet is just never received. - //TODO : rework this in a nicer way. Use something other than a fucking threaded five second delay. + //DONE : rework this in a nicer way. Use something other than a fucking threaded five second delay. new Thread(() -> { try { Thread.sleep(5000); @@ -147,7 +159,7 @@ public void onConnectedToServer(ClientConnectedToServerEvent event) { } NetworkHandler.HANDLER.sendToServer(new PacketToastSubscribe(ClientConfigManager.showProgress.get())); - }).start(); + }).start();*/ } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java index 1326c2eb..6c38246a 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java @@ -19,5 +19,6 @@ public static void registerMessages() { // Register messages which are sent from the client to the server here: HANDLER.registerMessage(PacketBackupStatus.Handler.class, PacketBackupStatus.class, nextID(), Side.CLIENT); HANDLER.registerMessage(PacketToastSubscribe.Handler.class, PacketToastSubscribe.class, nextID(), Side.SERVER); + HANDLER.registerMessage(PacketToastTest.Handler.class, PacketToastTest.class, nextID(), Side.CLIENT); } } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastTest.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastTest.java new file mode 100644 index 00000000..92aba1fa --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastTest.java @@ -0,0 +1,50 @@ +package co.uk.mommyheather.advancedbackups.network; + +import co.uk.mommyheather.advancedbackups.AdvancedBackups; +import co.uk.mommyheather.advancedbackups.core.config.ClientConfigManager; +import io.netty.buffer.ByteBuf; +import net.minecraftforge.fml.common.network.simpleimpl.IMessage; +import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; +import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; + +public class PacketToastTest implements IMessage{ + + + + public PacketToastTest(boolean enable) { + + } + + public PacketToastTest() { + + } + + @Override + public void fromBytes(ByteBuf buf) { + + } + + @Override + public void toBytes(ByteBuf buf) { + + } + + + public static class Handler implements IMessageHandler { + + @Override + public IMessage onMessage(PacketToastTest message, MessageContext ctx) { + + ClientConfigManager.loadOrCreateConfig(); + NetworkHandler.HANDLER.sendToServer(new PacketToastSubscribe(ClientConfigManager.showProgress.get())); + + return null; + + } + + } + + + + +} \ No newline at end of file From b9eed67f70daddc05c11571ed4cc8421bacdcb43 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Mon, 15 Jan 2024 17:08:36 +0000 Subject: [PATCH 419/580] cleanup --- .../co/uk/mommyheather/advancedbackups/AdvancedBackups.java | 6 ------ .../advancedbackups/network/PacketToastTest.java | 1 - 2 files changed, 7 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index b898812d..5094ce7c 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -7,15 +7,12 @@ import org.apache.logging.log4j.Logger; -import co.uk.mommyheather.advancedbackups.client.ClientBridge; import co.uk.mommyheather.advancedbackups.client.ClientContactor; import co.uk.mommyheather.advancedbackups.core.ABCore; import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; -import co.uk.mommyheather.advancedbackups.core.config.ClientConfigManager; import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; import co.uk.mommyheather.advancedbackups.network.NetworkHandler; -import co.uk.mommyheather.advancedbackups.network.PacketToastSubscribe; import co.uk.mommyheather.advancedbackups.network.PacketToastTest; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.server.MinecraftServer; @@ -32,10 +29,7 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.gameevent.PlayerEvent; import net.minecraftforge.fml.common.gameevent.TickEvent; -import net.minecraftforge.fml.common.gameevent.PlayerEvent.PlayerChangedDimensionEvent; import net.minecraftforge.fml.common.gameevent.PlayerEvent.PlayerLoggedInEvent; -import net.minecraftforge.fml.common.network.FMLNetworkEvent.ClientConnectedToServerEvent; -import net.minecraftforge.fml.common.network.FMLNetworkEvent.ServerConnectionFromClientEvent; import net.minecraftforge.fml.relauncher.Side; diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastTest.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastTest.java index 92aba1fa..50c298bc 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastTest.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastTest.java @@ -1,6 +1,5 @@ package co.uk.mommyheather.advancedbackups.network; -import co.uk.mommyheather.advancedbackups.AdvancedBackups; import co.uk.mommyheather.advancedbackups.core.config.ClientConfigManager; import io.netty.buffer.ByteBuf; import net.minecraftforge.fml.common.network.simpleimpl.IMessage; From fc5aaf9e053e9595f3c582b66aa2b5005c0bdd87 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 16 Jan 2024 16:36:29 +0000 Subject: [PATCH 420/580] fully support all client config settings. --- .../advancedbackups/client/BackupToast.java | 40 ++++++++++++------- .../advancedbackups/client/ColourHelper.java | 30 ++++++++++++++ 2 files changed, 55 insertions(+), 15 deletions(-) create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/client/ColourHelper.java diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java index 223bb781..ff411cbc 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java @@ -1,7 +1,6 @@ package co.uk.mommyheather.advancedbackups.client; -import com.mojang.realmsclient.gui.ChatFormatting; - +import co.uk.mommyheather.advancedbackups.core.config.ClientConfigManager; import net.minecraft.client.gui.Gui; import net.minecraft.client.gui.toasts.GuiToast; import net.minecraft.client.gui.toasts.IToast; @@ -11,7 +10,7 @@ import net.minecraft.init.Items; import net.minecraft.item.ItemStack; -public class BackupToast implements IToast{ +public class BackupToast implements IToast { public static boolean starting; @@ -30,61 +29,72 @@ public class BackupToast implements IToast{ public static final ItemStack stack = new ItemStack(Items.PAPER); + private int textColour = 0; + private static String title = "You shouldn't see this!"; + + private int progressBarColor = ColourHelper.colour(255, ClientConfigManager.progressBarRed.get(), ClientConfigManager.progressBarGreen.get(), ClientConfigManager.progressBarBlue.get()); + @Override public Visibility draw(GuiToast toastGui, long delta) { toastGui.getMinecraft().getTextureManager().bindTexture(TEXTURE_TOASTS); GlStateManager.color(1.0F, 1.0F, 1.0F); - toastGui.drawTexturedModalRect(0, 0, 0, 0, 160, 32); + toastGui.drawTexturedModalRect(0, 0, 0,ClientConfigManager.darkMode.get() ? 0 : 32, 160, 32); RenderHelper.enableGUIStandardItemLighting(); toastGui.getMinecraft().getRenderItem().renderItemAndEffectIntoGUI(stack, 8, 8); float percent = finished ? 100 : (float) progress / (float) max; - Gui.drawRect(3, 28, 156, 29, -1); + Gui.drawRect(4, 28, 156, 29, ColourHelper.colour + (255, ClientConfigManager.progressBackgroundRed.get(), ClientConfigManager.progressBackgroundGreen.get(), ClientConfigManager.progressBackgroundBlue.get())); float f = Math.min(156, ( 156 * percent )); if (!exists) { - toastGui.getMinecraft().fontRenderer.drawString(ChatFormatting.GREEN + I18n.format("advancedbackups.backup_finished"), 25, 12, -11534256); - Gui.drawRect(3, 28, 156, 29, -10948014); + toastGui.getMinecraft().fontRenderer.drawString(title, 25, 12, textColour); + if (title.equals(I18n.format("advancedbackups.backup_finished"))) Gui.drawRect(4, 28, 156, 29, progressBarColor); return Visibility.HIDE; } - String title = "You shouldn't see this!"; if (starting) { - title = ChatFormatting.GREEN + I18n.format("advancedbackups.backup_starting"); + title = I18n.format("advancedbackups.backup_starting"); + textColour = ColourHelper.colour(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); } else if (started) { - title = ChatFormatting.GREEN + I18n.format("advancedbackups.progress", round(percent * 100)); + title = I18n.format("advancedbackups.progress", round(percent * 100)); + textColour = ColourHelper.colour(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); } else if (failed) { - title = ChatFormatting.RED + I18n.format("advancedbackups.backup_failed"); + title = I18n.format("advancedbackups.backup_failed"); + textColour = ColourHelper.colour(255, (int) ClientConfigManager.errorTextRed.get(), (int) ClientConfigManager.errorTextGreen.get(), (int) ClientConfigManager.errorTextBlue.get()); if (!timeSet) { time = System.currentTimeMillis(); timeSet = true; } } else if (cancelled) { - title = ChatFormatting.RED + I18n.format("advancedbackups.backup_cancelled"); + title = I18n.format("advancedbackups.backup_cancelled"); + textColour = ColourHelper.colour(255, (int) ClientConfigManager.errorTextRed.get(), (int) ClientConfigManager.errorTextGreen.get(), (int) ClientConfigManager.errorTextBlue.get()); if (!timeSet) { time = System.currentTimeMillis(); timeSet = true; } } else if (finished) { - title = ChatFormatting.GREEN + I18n.format("advancedbackups.backup_finished"); + title = I18n.format("advancedbackups.backup_finished"); + textColour = ColourHelper.colour(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); if (!timeSet) { time = System.currentTimeMillis(); timeSet = true; } } + else title = "You shouldn't see this!"; - toastGui.getMinecraft().fontRenderer.drawString(title, 25, 12, -11534256); + toastGui.getMinecraft().fontRenderer.drawString(title, 25, 12, textColour); if (timeSet && System.currentTimeMillis() >= time + 5000) { starting = false; @@ -100,7 +110,7 @@ else if (finished) { } - Gui.drawRect(3, 28, (int) f, 29, -10948014); + if (progress > 0 || finished) Gui.drawRect(4, 28, (int) f, 29, progressBarColor); return Visibility.SHOW; diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ColourHelper.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ColourHelper.java new file mode 100644 index 00000000..a02d0c68 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ColourHelper.java @@ -0,0 +1,30 @@ +package co.uk.mommyheather.advancedbackups.client; + +//A colour helper, loosely based on that of vanilla 1.16. +public class ColourHelper { + + public static int alpha(int in) { + return in >>> 24; + } + + public static int red(int in) { + return in >> 16 & 255; + } + + public static int green(int in) { + return in >> 8 & 255; + } + + public static int blue(int in) { + return in & 255; + } + + public static int colour(int a, int r, int g, int b) { + return a << 24 | r << 16 | g << 8 | b; + } + + public static int colour(int a, long r, long g, long b) { + return colour(a, (int) r, (int) g, (int) b); + } + +} From 4426cd4ea68a6508a65d0c571ecf5516f2bae398 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 16 Jan 2024 16:56:59 +0000 Subject: [PATCH 421/580] pseudo client config reload command for the sake of tab complete --- .../AdvancedBackupsCommand.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index 5aef3e65..a9786be4 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -14,6 +14,7 @@ public AdvancedBackupsCommand() { addSubcommand(new Start()); addSubcommand(new Reload()); + addSubcommand(new ReloadClient()); addSubcommand(new ResetChain()); addSubcommand(new Snapshot()); addSubcommand(new Cancel()); @@ -62,6 +63,29 @@ public String getUsage(ICommandSender sender) { return "commands.backup.reload-config.usage"; } + @Override + public boolean checkPermission(MinecraftServer server, ICommandSender sender) + { + return !AdvancedBackups.server.isDedicatedServer() || super.checkPermission(server, sender); + } + } + + public static class ReloadClient extends CommandTreeBase { + public ReloadClient(){} + @Override + public void execute(MinecraftServer server, ICommandSender sender, String[] args) throws CommandException { + sender.sendMessage(new TextComponentString("This command can only be executed on a client!")); + } + @Override + public String getName() + { + return "reload-client-config"; + } + @Override + public String getUsage(ICommandSender sender) { + return "commands.backup.reload-client-config.usage"; + } + @Override public boolean checkPermission(MinecraftServer server, ICommandSender sender) { From e1211fe334ed8e12a8dd8555f3e8018006f7d8ec Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 16 Jan 2024 16:57:39 +0000 Subject: [PATCH 422/580] forgot this in last commit --- .../uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index a9786be4..451761be 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -36,7 +36,7 @@ public int getRequiredPermissionLevel() @Override public String getUsage(ICommandSender icommandsender) { - return "/backup (check|start|reload-config|snapshot|cancel)"; + return "/backup (check|start|reload-config|reload-client-config|snapshot|cancel)"; } @Override From dc98d8f0cb80105efe0e1348e51955a25ce64d41 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 16 Jan 2024 17:14:14 +0000 Subject: [PATCH 423/580] and the actual client config reload stuff. --- .../mommyheather/advancedbackups/AdvancedBackups.java | 7 +++++++ .../advancedbackups/client/ClientBridge.java | 10 ++++++++++ 2 files changed, 17 insertions(+) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 5094ce7c..4fb138eb 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -7,6 +7,7 @@ import org.apache.logging.log4j.Logger; +import co.uk.mommyheather.advancedbackups.client.ClientBridge; import co.uk.mommyheather.advancedbackups.client.ClientContactor; import co.uk.mommyheather.advancedbackups.core.ABCore; import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; @@ -17,6 +18,7 @@ import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.server.MinecraftServer; import net.minecraft.world.WorldServer; +import net.minecraftforge.client.event.ClientChatEvent; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.fml.common.Loader; import net.minecraftforge.fml.common.Mod; @@ -156,6 +158,11 @@ public void onConnectedToServer(PlayerLoggedInEvent event) { }).start();*/ } + @SubscribeEvent + public void onClientChat(ClientChatEvent event) { + ClientBridge.onClientChat(event); + } + public static final String savesDisabledMessage = "\n\n\n***************************************\nSAVING DISABLED - PREPARING FOR BACKUP!\n***************************************"; diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientBridge.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientBridge.java index 1969cfa4..05eefc45 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientBridge.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientBridge.java @@ -1,7 +1,9 @@ package co.uk.mommyheather.advancedbackups.client; +import co.uk.mommyheather.advancedbackups.core.CoreCommandSystem; import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; import net.minecraft.client.Minecraft; +import net.minecraftforge.client.event.ClientChatEvent; public class ClientBridge { @@ -25,5 +27,13 @@ public static void handle(PacketBackupStatus message) { }); } + + + public static void onClientChat(ClientChatEvent event) { + if (event.getMessage().equals("/backup reload-client-config")) { + event.setCanceled(true); + CoreCommandSystem.reloadClientConfig(Minecraft.getMinecraft().player::sendChatMessage); + } + } } From 38cd86ab01a30d37cc1e0d935023bbaa80ae0ac3 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 16 Jan 2024 22:25:12 +0000 Subject: [PATCH 424/580] properly use progress bar colour, support cancelling in toast --- .../advancedbackups/client/BackupToast.java | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java index 7579f2aa..65fb5bae 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java @@ -18,6 +18,7 @@ public class BackupToast implements IToast { public static boolean started; public static boolean failed; public static boolean finished; + public static boolean cancelled; public static int progress; public static int max; @@ -30,6 +31,7 @@ public class BackupToast implements IToast { public static final ItemStack stack = new ItemStack(Items.PAPER); private int textColour; + private String title = "You shouldn't see this!"; @Override @@ -50,11 +52,11 @@ public Visibility render(MatrixStack matrix, ToastGui toastGui, long delta) { if (!exists) { textColour = ColorHelper.PackedColor.color(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); toastGui.getMinecraft().font.draw(matrix, I18n.get("advancedbackups.backup_finished"), 25, 11, textColour); - AbstractGui.fill(matrix, 3, 28, 156, 29, -10948014); + if (title.equals(I18n.get("advancedbackups.backup_finished"))) AbstractGui.fill(matrix, 3, 28, 156, 29, ColorHelper.PackedColor.color + (255, (int) ClientConfigManager.progressBarRed.get(), (int) ClientConfigManager.progressBarGreen.get(), (int) ClientConfigManager.progressBarBlue.get())); return Visibility.HIDE; } - String title = "You shouldn't see this!"; if (starting) { @@ -81,6 +83,19 @@ else if (finished) { timeSet = true; } } + else if (cancelled) { + textColour = ColorHelper.PackedColor.color(255, (int) ClientConfigManager.errorTextRed.get(), (int) ClientConfigManager.errorTextGreen.get(), (int) ClientConfigManager.errorTextBlue.get()); + title = I18n.get("advancedbackups.backup_cancelled"); + if (!timeSet) { + time = System.currentTimeMillis(); + timeSet = true; + } + + } + + else { + title = "You shouldn't see this!"; + } toastGui.getMinecraft().font.draw(matrix, title, 25, 11, textColour); From 16cba46c683c7c44120c7503ee5364439a6e1794 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 16 Jan 2024 22:28:09 +0000 Subject: [PATCH 425/580] network cancelled backups --- .../client/ClientContactor.java | 21 +++++++++++++++---- .../advancedbackups/client/ClientWrapper.java | 4 +--- .../network/PacketBackupStatus.java | 7 ++++++- 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java index e20d9700..df18d1e4 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java @@ -16,7 +16,7 @@ public class ClientContactor implements IClientContactor { public void backupComplete() { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); List players = server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, 0, 0); + PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, false, 0, 0); for (ServerPlayerEntity player : players) { if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; if (!server.isDedicatedServer() || player.hasPermissions(3)) { @@ -29,7 +29,7 @@ public void backupComplete() { public void backupFailed() { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); List players = server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, 0, 0); + PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, false, 0, 0); for (ServerPlayerEntity player : players) { if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; if (!server.isDedicatedServer() || player.hasPermissions(3)) { @@ -42,7 +42,7 @@ public void backupFailed() { public void backupProgress(int progress, int max) { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); List players = server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, progress, max); + PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, false, progress, max); for (ServerPlayerEntity player : players) { if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; if (!server.isDedicatedServer() || player.hasPermissions(3)) { @@ -55,7 +55,20 @@ public void backupProgress(int progress, int max) { public void backupStarting() { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); List players = server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, 0, 0); + PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, false, 0, 0); + for (ServerPlayerEntity player : players) { + if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; + if (!server.isDedicatedServer() || player.hasPermissions(3)) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupCancelled() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, false, false, true, 0, 0); for (ServerPlayerEntity player : players) { if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; if (!server.isDedicatedServer() || player.hasPermissions(3)) { diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java index 6b41ae55..e3ec213d 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java @@ -8,13 +8,10 @@ import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; import co.uk.mommyheather.advancedbackups.network.PacketToastSubscribe; import net.minecraft.client.Minecraft; -import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.client.event.ClientChatEvent; import net.minecraftforge.client.event.ClientPlayerNetworkEvent; import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.LogicalSide; -import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; import net.minecraftforge.fml.network.NetworkEvent.Context; @@ -28,6 +25,7 @@ public static void handle(Supplier ctx, PacketBackupStatus packet) { BackupToast.started = packet.started; BackupToast.failed = packet.failed; BackupToast.finished = packet.finished; + BackupToast.cancelled = packet.cancelled; BackupToast.progress = packet.progress; BackupToast.max = packet.max; diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java index c80a6106..5b4b4abb 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java @@ -14,16 +14,19 @@ public class PacketBackupStatus { public boolean failed; public boolean finished; + public boolean cancelled; + public int progress; public int max; - public PacketBackupStatus(boolean starting, boolean started, boolean failed, boolean finished, int progress, + public PacketBackupStatus(boolean starting, boolean started, boolean failed, boolean finished, boolean cancelled, int progress, int max) { this.starting = starting; this.started = started; this.failed = failed; this.finished = finished; + this.cancelled = cancelled; this.progress = progress; this.max = max; } @@ -34,6 +37,7 @@ public PacketBackupStatus(PacketBuffer buf) { started = buf.readBoolean(); failed = buf.readBoolean(); finished = buf.readBoolean(); + cancelled = buf.readBoolean(); progress = buf.readInt(); max = buf.readInt(); @@ -44,6 +48,7 @@ public void toBytes(PacketBuffer buf) { buf.writeBoolean(started); buf.writeBoolean(failed); buf.writeBoolean(finished); + buf.writeBoolean(cancelled); buf.writeInt(progress); buf.writeInt(max); From 81b4fe16a2a10b8a5945ecebb0752f4d39861e84 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 16 Jan 2024 22:28:41 +0000 Subject: [PATCH 426/580] more localisation --- src/main/resources/assets/advancedbackups/lang/en_us.json | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/resources/assets/advancedbackups/lang/en_us.json b/src/main/resources/assets/advancedbackups/lang/en_us.json index cc68dae1..66caf08d 100644 --- a/src/main/resources/assets/advancedbackups/lang/en_us.json +++ b/src/main/resources/assets/advancedbackups/lang/en_us.json @@ -2,5 +2,6 @@ "advancedbackups.backup_starting" : "Backup starting!", "advancedbackups.progress": "Backup ongoing: %1$s%%", "advancedbackups.backup_failed": "Backup failed!\nCheck log for more info.", + "advancedbackups.backup_cancelled": "Backup cancelled!", "advancedbackups.backup_finished": "Backup complete!" } \ No newline at end of file From 47e38a86ad2c0271063276d6611b4cef337cabec Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 16 Jan 2024 22:31:23 +0000 Subject: [PATCH 427/580] aand a cancel command. --- .../advancedbackups/AdvancedBackupsCommand.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index d2f1709f..e68622b4 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -44,6 +44,13 @@ public static void register(CommandDispatcher stack) { }); return 1; })) + + .then(Commands.literal("cancel").executes((runner) -> { + CoreCommandSystem.cancelBackup((response) -> { + runner.getSource().sendSuccess(new StringTextComponent(response), true); + }); + return 1; + })) ); } From 2f87bcf372decd16f3859c983241aa519b13655d Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Wed, 17 Jan 2024 22:36:54 +0000 Subject: [PATCH 428/580] toasts are now opt-in --- .../advancedbackups/AdvancedBackups.java | 11 +++++ .../client/ClientContactor.java | 11 +++++ .../advancedbackups/client/ClientWrapper.java | 27 ++++++++++++ .../network/NetworkHandler.java | 10 +++++ .../network/PacketToastSubscribe.java | 41 +++++++++++++++++++ 5 files changed, 100 insertions(+) create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index db563808..c3a4ba85 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -1,5 +1,6 @@ package co.uk.mommyheather.advancedbackups; +import java.util.ArrayList; import java.util.List; import java.util.function.Consumer; @@ -8,6 +9,7 @@ import com.mojang.logging.LogUtils; import co.uk.mommyheather.advancedbackups.client.ClientContactor; +import co.uk.mommyheather.advancedbackups.client.ClientWrapper; import co.uk.mommyheather.advancedbackups.core.ABCore; import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; @@ -27,6 +29,8 @@ import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.ModList; import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; +import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; import net.minecraftforge.server.ServerLifecycleHooks; @Mod("advancedbackups") @@ -39,11 +43,14 @@ public class AdvancedBackups public static final Consumer warningLogger = LOGGER::warn; public static final Consumer errorLogger = LOGGER::error; + public static final ArrayList players = new ArrayList<>(); + public AdvancedBackups() { // Register ourselves for server and other game events we are interested in MinecraftForge.EVENT_BUS.register(this); + FMLJavaModLoadingContext.get().getModEventBus().addListener(this::clientSetup); NetworkHandler.register(); } @@ -76,6 +83,10 @@ public void onServerStarting(ServerStartingEvent event) } + public void clientSetup(FMLClientSetupEvent e) { + ClientWrapper.init(e); + } + @SubscribeEvent public void onServerStarted(ServerStartedEvent event) { BackupWrapper.checkStartupBackups(); diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java index 2c72a8c7..49335183 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java @@ -2,6 +2,7 @@ import java.util.List; +import co.uk.mommyheather.advancedbackups.AdvancedBackups; import co.uk.mommyheather.advancedbackups.interfaces.IClientContactor; import co.uk.mommyheather.advancedbackups.network.NetworkHandler; import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; @@ -17,6 +18,7 @@ public void backupComplete() { List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, 0, 0); for (ServerPlayer player : players) { + if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; if (!server.isDedicatedServer() || player.hasPermissions(3)) { NetworkHandler.sendToClient(player, packet); } @@ -29,6 +31,7 @@ public void backupFailed() { List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, 0, 0); for (ServerPlayer player : players) { + if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; if (!server.isDedicatedServer() || player.hasPermissions(3)) { NetworkHandler.sendToClient(player, packet); } @@ -41,6 +44,7 @@ public void backupProgress(int progress, int max) { List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, progress, max); for (ServerPlayer player : players) { + if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; if (!server.isDedicatedServer() || player.hasPermissions(3)) { NetworkHandler.sendToClient(player, packet); } @@ -53,9 +57,16 @@ public void backupStarting() { List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, 0, 0); for (ServerPlayer player : players) { + if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; if (!server.isDedicatedServer() || player.hasPermissions(3)) { NetworkHandler.sendToClient(player, packet); } } } + + @Override + public void backupCancelled() { + // temporarily here to let it compile + throw new UnsupportedOperationException("Unimplemented method 'backupCancelled'"); + } } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java index 59709b69..27f6735c 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java @@ -1,7 +1,15 @@ package co.uk.mommyheather.advancedbackups.client; +import co.uk.mommyheather.advancedbackups.core.CoreCommandSystem; +import co.uk.mommyheather.advancedbackups.core.config.ClientConfigManager; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; +import co.uk.mommyheather.advancedbackups.network.PacketToastSubscribe; import net.minecraft.client.Minecraft; +import net.minecraftforge.client.event.ClientChatEvent; +import net.minecraftforge.client.event.ClientPlayerNetworkEvent; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; public class ClientWrapper { @@ -19,5 +27,24 @@ public static void handle(PacketBackupStatus packet) { Minecraft.getInstance().getToasts().addToast(new BackupToast()); } } + + public static void init(FMLClientSetupEvent e) { + MinecraftForge.EVENT_BUS.addListener(ClientWrapper::onClientChat); + MinecraftForge.EVENT_BUS.addListener(ClientWrapper::onServerConnected); + ClientConfigManager.loadOrCreateConfig(); + } + + public static void onClientChat(ClientChatEvent event) { + if (event.getMessage().equals("/backup reload-client-config")) { + event.setCanceled(true); + + CoreCommandSystem.reloadClientConfig(Minecraft.getInstance().player::chat); + } + + } + + public static void onServerConnected(ClientPlayerNetworkEvent.LoggedInEvent event) { + NetworkHandler.sendToServer(new PacketToastSubscribe(ClientConfigManager.showProgress.get())); + } } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java index 69a388a4..3d87e79a 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java @@ -28,10 +28,20 @@ public static void register() { .decoder(buf -> new PacketBackupStatus(buf)) .consumer(PacketBackupStatus::handle) .add(); + + INSTANCE.messageBuilder(PacketToastSubscribe.class, id()) + .encoder(PacketToastSubscribe::toBytes) + .decoder(buf -> new PacketToastSubscribe(buf)) + .consumer(PacketToastSubscribe::handle) + .add(); } public static void sendToClient(ServerPlayer player, Object packet) { INSTANCE.sendTo(packet, player.connection.connection, NetworkDirection.PLAY_TO_CLIENT); } + public static void sendToServer(Object packet) { + INSTANCE.sendToServer(packet); + } + } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java new file mode 100644 index 00000000..49bbcf02 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java @@ -0,0 +1,41 @@ +package co.uk.mommyheather.advancedbackups.network; + +import java.util.function.Supplier; + +import co.uk.mommyheather.advancedbackups.AdvancedBackups; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraftforge.network.NetworkEvent; + +public class PacketToastSubscribe { + + private boolean enable; + + public PacketToastSubscribe(boolean enable) { + this.enable = enable; + } + + + public PacketToastSubscribe(FriendlyByteBuf buf) { + enable = buf.readBoolean(); + } + + public void toBytes(FriendlyByteBuf buf) { + buf.writeBoolean(enable); + } + + public boolean handle(Supplier ctx) { + ctx.get().enqueueWork(() -> { + if (ctx.get().getSender() == null) return; + if (enable && !AdvancedBackups.players.contains(ctx.get().getSender().getStringUUID())) { + AdvancedBackups.players.add(ctx.get().getSender().getStringUUID()); + } + else if (!enable) { + AdvancedBackups.players.remove(ctx.get().getSender().getStringUUID()); + } + }); + + return true; + + } + +} From 0323bd2ef720c42c147359d6c31e67befbc1ff78 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Wed, 17 Jan 2024 22:56:14 +0000 Subject: [PATCH 429/580] configure core loggers earlier --- .../co/uk/mommyheather/advancedbackups/AdvancedBackups.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index c3a4ba85..1a90235a 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -52,6 +52,9 @@ public AdvancedBackups() MinecraftForge.EVENT_BUS.register(this); FMLJavaModLoadingContext.get().getModEventBus().addListener(this::clientSetup); NetworkHandler.register(); + ABCore.infoLogger = infoLogger; + ABCore.warningLogger = warningLogger; + ABCore.errorLogger = errorLogger; } @SubscribeEvent @@ -66,9 +69,6 @@ public void onServerStarting(ServerStartingEvent event) ABCore.enableSaving = AdvancedBackups::enableSaving; ABCore.saveOnce = AdvancedBackups::saveOnce; - ABCore.infoLogger = infoLogger; - ABCore.warningLogger = warningLogger; - ABCore.errorLogger = errorLogger; ABCore.resetActivity = AdvancedBackups::resetActivity; From 85b6b81767457306ce597d6d2f2aa8b17a85707f Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sat, 3 Feb 2024 17:56:31 +0000 Subject: [PATCH 430/580] why did i have no gitignore here --- .gitignore | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..c20b36d1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,27 @@ +# eclipse +bin +*.launch +.settings +.metadata +.classpath +.project + +# idea +out +*.ipr +*.iws +*.iml +.idea + +.vscode +.github + +# gradle +build +.gradle + +advancedbackups-corelib.jar + +# other +eclipse +run \ No newline at end of file From 99439c2379939cc00d37997a89f74f4a14305e07 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sat, 3 Feb 2024 19:59:09 +0000 Subject: [PATCH 431/580] fix incorrect display when toast closes after error or cancel --- .../advancedbackups/client/BackupToast.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java index 65fb5bae..2bad4a8f 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java @@ -50,10 +50,16 @@ public Visibility render(MatrixStack matrix, ToastGui toastGui, long delta) { )); if (!exists) { - textColour = ColorHelper.PackedColor.color(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); - toastGui.getMinecraft().font.draw(matrix, I18n.get("advancedbackups.backup_finished"), 25, 11, textColour); - if (title.equals(I18n.get("advancedbackups.backup_finished"))) AbstractGui.fill(matrix, 3, 28, 156, 29, ColorHelper.PackedColor.color - (255, (int) ClientConfigManager.progressBarRed.get(), (int) ClientConfigManager.progressBarGreen.get(), (int) ClientConfigManager.progressBarBlue.get())); + if (title.equals(I18n.get("advancedbackups.backup_finished"))){ + textColour = ColorHelper.PackedColor.color(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); + toastGui.getMinecraft().font.draw(matrix, I18n.get(title), 25, 11, textColour); + AbstractGui.fill(matrix, 3, 28, 156, 29, ColorHelper.PackedColor.color + (255, (int) ClientConfigManager.progressBarRed.get(), (int) ClientConfigManager.progressBarGreen.get(), (int) ClientConfigManager.progressBarBlue.get())); + } + else { + textColour = ColorHelper.PackedColor.color(255, (int) ClientConfigManager.errorTextRed.get(), (int) ClientConfigManager.errorTextGreen.get(), (int) ClientConfigManager.errorTextBlue.get()); + toastGui.getMinecraft().font.draw(matrix, I18n.get(title), 25, 11, textColour); + } return Visibility.HIDE; } From ba878c92e53f38f494bd4e121e4029fd12f861d2 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sat, 3 Feb 2024 20:20:53 +0000 Subject: [PATCH 432/580] refix the one pixel bug --- .../co/uk/mommyheather/advancedbackups/client/BackupToast.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java index 2bad4a8f..658d7c87 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java @@ -117,7 +117,7 @@ else if (cancelled) { return Visibility.HIDE; } - AbstractGui.fill(matrix, 3, 28, Math.max(3, (int) f), 29, ColorHelper.PackedColor.color + AbstractGui.fill(matrix, 4, 28, Math.max(3, (int) f), 29, ColorHelper.PackedColor.color (255, (int) ClientConfigManager.progressBarRed.get(), (int) ClientConfigManager.progressBarGreen.get(), (int) ClientConfigManager.progressBarBlue.get())); return Visibility.SHOW; From 11bbc79ae4413251584edd53d0547faf6ff45273 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sat, 3 Feb 2024 20:22:25 +0000 Subject: [PATCH 433/580] fully implement support for cancel toast, and toast customisation --- .../advancedbackups/client/BackupToast.java | 49 ++++++++++++++----- .../client/ClientContactor.java | 20 ++++++-- .../advancedbackups/client/ClientWrapper.java | 1 + .../advancedbackups/client/ColourHelper.java | 31 ++++++++++++ .../network/PacketBackupStatus.java | 6 ++- 5 files changed, 91 insertions(+), 16 deletions(-) create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/client/ColourHelper.java diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java index 6b0c5579..0ef1a2ac 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java @@ -2,6 +2,7 @@ import com.mojang.blaze3d.systems.RenderSystem; +import co.uk.mommyheather.advancedbackups.core.config.ClientConfigManager; import net.minecraft.client.gui.DrawableHelper; import net.minecraft.client.render.GameRenderer; import net.minecraft.client.resource.language.I18n; @@ -18,6 +19,7 @@ public class BackupToast implements Toast { public static boolean started; public static boolean failed; public static boolean finished; + public static boolean cancelled; public static int progress; public static int max; @@ -29,25 +31,37 @@ public class BackupToast implements Toast { public static final ItemStack stack = new ItemStack(Items.PAPER); + private int textColour; + private String title = "You shouldn't see this!"; + @Override public Visibility draw(MatrixStack matrix, ToastManager manager, long startTime) { RenderSystem.setShader(GameRenderer::getPositionTexShader); RenderSystem.setShaderTexture(0, TEXTURE); RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); - manager.drawTexture(matrix, 0, 0, 0, 0, this.getWidth(), this.getHeight()); + manager.drawTexture(matrix, 0, 0, 0, ClientConfigManager.darkMode.get() ? 0 : this.getHeight(), this.getWidth(), this.getHeight()); manager.getClient().getItemRenderer().renderGuiItemIcon(stack, 8, 8); float percent = finished ? 100 : (float) progress / (float) max; - DrawableHelper.fill(matrix, 3, 28, 156, 29, -1); + DrawableHelper.fill(matrix, 4, 28, 156, 29, ColourHelper.colour + (255, (int) ClientConfigManager.progressBackgroundRed.get(), (int) ClientConfigManager.progressBackgroundGreen.get(), (int) ClientConfigManager.progressBackgroundBlue.get())); float f = Math.min(156, ( 156 * percent )); - if (!exists) { - manager.getClient().textRenderer.draw(matrix, Formatting.GREEN + I18n.translate("advancedbackups.backup_finished"), 25, 11, -11534256); - DrawableHelper.fill(matrix, 3, 28, 156, 29, -10948014); + if (!exists) { + if (title.equals(I18n.translate("advancedbackups.backup_finished"))){ + textColour = ColourHelper.colour(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); + manager.getClient().textRenderer.draw(matrix, I18n.translate(title), 25, 11, textColour); + DrawableHelper.fill(matrix, 3, 28, 156, 29, ColourHelper.colour + (255, (int) ClientConfigManager.progressBarRed.get(), (int) ClientConfigManager.progressBarGreen.get(), (int) ClientConfigManager.progressBarBlue.get())); + } + else { + textColour = ColourHelper.colour(255, (int) ClientConfigManager.errorTextRed.get(), (int) ClientConfigManager.errorTextGreen.get(), (int) ClientConfigManager.errorTextBlue.get()); + manager.getClient().textRenderer.draw(matrix, I18n.translate(title), 25, 11, textColour); + } return Visibility.HIDE; } @@ -55,27 +69,39 @@ public Visibility draw(MatrixStack matrix, ToastManager manager, long startTime) if (starting) { - title = Formatting.GREEN + I18n.translate("advancedbackups.backup_starting"); + textColour = ColourHelper.colour(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); + title = I18n.translate("advancedbackups.backup_starting"); } else if (started) { - title = Formatting.GREEN + I18n.translate("advancedbackups.progress", round(percent * 100)); + textColour = ColourHelper.colour(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); + title = I18n.translate("advancedbackups.progress", round(percent * 100)); } else if (failed) { - title = Formatting.RED + I18n.translate("advancedbackups.backup_failed"); + textColour = ColourHelper.colour(255, (int) ClientConfigManager.errorTextRed.get(), (int) ClientConfigManager.errorTextGreen.get(), (int) ClientConfigManager.errorTextBlue.get()); + title = I18n.translate("advancedbackups.backup_failed"); if (!timeSet) { time = System.currentTimeMillis(); timeSet = true; } } else if (finished) { - title = Formatting.GREEN + I18n.translate("advancedbackups.backup_finished"); + textColour = ColourHelper.colour(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); + title = I18n.translate("advancedbackups.backup_finished"); + if (!timeSet) { + time = System.currentTimeMillis(); + timeSet = true; + } + } + else if (cancelled) { + textColour = ColourHelper.colour(255, (int) ClientConfigManager.errorTextRed.get(), (int) ClientConfigManager.errorTextGreen.get(), (int) ClientConfigManager.errorTextBlue.get()); + title = I18n.translate("advancedbackups.backup_cancelled"); if (!timeSet) { time = System.currentTimeMillis(); timeSet = true; } } - manager.getClient().textRenderer.draw(matrix, title, 25, 11, -11534256); + manager.getClient().textRenderer.draw(matrix, title, 25, 11, textColour); if (timeSet && System.currentTimeMillis() >= time + 5000) { starting = false; @@ -89,7 +115,8 @@ else if (finished) { return Visibility.HIDE; } - DrawableHelper.fill(matrix, 3, 28, Math.max(3, (int) f), 29, -10948014); + DrawableHelper.fill(matrix, 3, 28, Math.max(3, (int) f), 29, ColourHelper.colour + (255, (int) ClientConfigManager.progressBarRed.get(), (int) ClientConfigManager.progressBarGreen.get(), (int) ClientConfigManager.progressBarBlue.get())); return Visibility.SHOW; } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java index cf5137e9..e441a772 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java @@ -15,7 +15,7 @@ public class ClientContactor implements IClientContactor { public void backupComplete() { MinecraftServer server = AdvancedBackups.server; List players = server.getPlayerManager().getPlayerList(); - PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, 0, 0); + PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, false, 0, 0); for (ServerPlayerEntity player : players) { if (!server.isDedicated() || player.hasPermissionLevel(3)) { NetworkHandler.sendToClient(player, packet); @@ -27,7 +27,7 @@ public void backupComplete() { public void backupFailed() { MinecraftServer server = AdvancedBackups.server; List players = server.getPlayerManager().getPlayerList(); - PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, 0, 0); + PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, false, 0, 0); for (ServerPlayerEntity player : players) { if (!server.isDedicated() || player.hasPermissionLevel(3)) { NetworkHandler.sendToClient(player, packet); @@ -39,7 +39,7 @@ public void backupFailed() { public void backupProgress(int progress, int max) { MinecraftServer server = AdvancedBackups.server; List players = server.getPlayerManager().getPlayerList(); - PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, progress, max); + PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, false, progress, max); for (ServerPlayerEntity player : players) { if (!server.isDedicated() || player.hasPermissionLevel(3)) { NetworkHandler.sendToClient(player, packet); @@ -51,7 +51,19 @@ public void backupProgress(int progress, int max) { public void backupStarting() { MinecraftServer server = AdvancedBackups.server; List players = server.getPlayerManager().getPlayerList(); - PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, 0, 0); + PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, false, 0, 0); + for (ServerPlayerEntity player : players) { + if (!server.isDedicated() || player.hasPermissionLevel(3)) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupCancelled() { + MinecraftServer server = AdvancedBackups.server; + List players = server.getPlayerManager().getPlayerList(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, false, false, true, 0, 0); for (ServerPlayerEntity player : players) { if (!server.isDedicated() || player.hasPermissionLevel(3)) { NetworkHandler.sendToClient(player, packet); diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java index 2f0b4f8f..ab6e7512 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java @@ -15,6 +15,7 @@ public static void handle(MinecraftClient client, PacketBackupStatus message) { BackupToast.started = message.started; BackupToast.failed = message.failed; BackupToast.finished = message.finished; + BackupToast.cancelled = message.cancelled; BackupToast.progress = message.progress; BackupToast.max = message.max; diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ColourHelper.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ColourHelper.java new file mode 100644 index 00000000..2527a3e9 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ColourHelper.java @@ -0,0 +1,31 @@ +package co.uk.mommyheather.advancedbackups.client; + +//A colour helper, loosely based on that of vanilla 1.16. +//What is the fabric 1.18 equivalent..? +public class ColourHelper { + + public static int alpha(int in) { + return in >>> 24; + } + + public static int red(int in) { + return in >> 16 & 255; + } + + public static int green(int in) { + return in >> 8 & 255; + } + + public static int blue(int in) { + return in & 255; + } + + public static int colour(int a, int r, int g, int b) { + return a << 24 | r << 16 | g << 8 | b; + } + + public static int colour(int a, long r, long g, long b) { + return colour(a, (int) r, (int) g, (int) b); + } + +} \ No newline at end of file diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java index a2064dde..b663f688 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java @@ -12,17 +12,19 @@ public class PacketBackupStatus { public boolean started; public boolean failed; public boolean finished; + public boolean cancelled; public int progress; public int max; - public PacketBackupStatus(boolean starting, boolean started, boolean failed, boolean finished, int progress, + public PacketBackupStatus(boolean starting, boolean started, boolean failed, boolean finished, boolean cancelled, int progress, int max) { this.starting = starting; this.started = started; this.failed = failed; this.finished = finished; + this.cancelled = cancelled; this.progress = progress; this.max = max; } @@ -36,6 +38,7 @@ public void read(PacketByteBuf buf) { started = buf.readBoolean(); failed = buf.readBoolean(); finished = buf.readBoolean(); + cancelled = buf.readBoolean(); progress = buf.readInt(); max = buf.readInt(); @@ -46,6 +49,7 @@ public PacketByteBuf write(PacketByteBuf buf) { buf.writeBoolean(started); buf.writeBoolean(failed); buf.writeBoolean(finished); + buf.writeBoolean(cancelled); buf.writeInt(progress); buf.writeInt(max); From 4e9456da8d5961ac1d0901f5e0d083ed4b6e72e6 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sat, 3 Feb 2024 20:44:54 +0000 Subject: [PATCH 434/580] contactor now requires clients to "subscribe" to toasts --- .../co/uk/mommyheather/advancedbackups/AdvancedBackups.java | 3 +++ .../mommyheather/advancedbackups/client/ClientContactor.java | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index a2f2eb97..a4cb71c5 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -1,6 +1,7 @@ package co.uk.mommyheather.advancedbackups; import java.io.File; +import java.util.ArrayList; import java.util.List; import java.util.function.Consumer; @@ -35,6 +36,8 @@ public class AdvancedBackups implements ModInitializer { public static final Consumer errorLogger = LOGGER::error; public static MinecraftServer server; + + public static final ArrayList players = new ArrayList<>(); @Override public void onInitialize() { diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java index e441a772..d2072cdd 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java @@ -17,6 +17,7 @@ public void backupComplete() { List players = server.getPlayerManager().getPlayerList(); PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, false, 0, 0); for (ServerPlayerEntity player : players) { + if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; if (!server.isDedicated() || player.hasPermissionLevel(3)) { NetworkHandler.sendToClient(player, packet); } @@ -29,6 +30,7 @@ public void backupFailed() { List players = server.getPlayerManager().getPlayerList(); PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, false, 0, 0); for (ServerPlayerEntity player : players) { + if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; if (!server.isDedicated() || player.hasPermissionLevel(3)) { NetworkHandler.sendToClient(player, packet); } @@ -41,6 +43,7 @@ public void backupProgress(int progress, int max) { List players = server.getPlayerManager().getPlayerList(); PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, false, progress, max); for (ServerPlayerEntity player : players) { + if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; if (!server.isDedicated() || player.hasPermissionLevel(3)) { NetworkHandler.sendToClient(player, packet); } @@ -53,6 +56,7 @@ public void backupStarting() { List players = server.getPlayerManager().getPlayerList(); PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, false, 0, 0); for (ServerPlayerEntity player : players) { + if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; if (!server.isDedicated() || player.hasPermissionLevel(3)) { NetworkHandler.sendToClient(player, packet); } @@ -65,6 +69,7 @@ public void backupCancelled() { List players = server.getPlayerManager().getPlayerList(); PacketBackupStatus packet = new PacketBackupStatus(false, false, false, false, true, 0, 0); for (ServerPlayerEntity player : players) { + if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; if (!server.isDedicated() || player.hasPermissionLevel(3)) { NetworkHandler.sendToClient(player, packet); } From 523c039e17bc312b8945f39229f84c958ddeff6c Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sat, 3 Feb 2024 20:48:33 +0000 Subject: [PATCH 435/580] cancel command and serverside impl of client reload command --- .../advancedbackups/AdvancedBackupsCommand.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index 4f39606a..38bd25ef 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -38,6 +38,18 @@ public static void register(CommandDispatcher stack) { }); return 1; })) + + .then(CommandManager.literal("cancel").executes((runner) -> { + CoreCommandSystem.cancelBackup((response) -> { + runner.getSource().sendFeedback(Text.of(response), true); + }); + return 1; + })) + + .then(CommandManager.literal("reload-client-config").executes((runner) -> { + runner.getSource().sendFeedback(Text.of("This command can only be ran on the client!"), true); + return 1; + })) ); } From 04507e7d97fe72f7ee3346bbe6edbcfd7f1871d9 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sun, 4 Feb 2024 06:21:16 +0000 Subject: [PATCH 436/580] full client config support --- .../advancedbackups/AdvancedBackups.java | 6 ++ .../client/AdvancedBackupsClientCommand.java | 50 ++++++++++++++++ .../advancedbackups/client/BackupToast.java | 7 +-- .../advancedbackups/client/ClientWrapper.java | 23 ++++++++ .../network/NetworkHandler.java | 3 +- .../network/PacketToastSubscribe.java | 59 +++++++++++++++++++ 6 files changed, 143 insertions(+), 5 deletions(-) create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index a4cb71c5..5b157202 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -13,11 +13,14 @@ import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; +import co.uk.mommyheather.advancedbackups.network.PacketToastSubscribe; import net.fabricmc.api.ModInitializer; import net.fabricmc.fabric.api.command.v1.CommandRegistrationCallback; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; +import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; import net.fabricmc.loader.impl.FabricLoaderImpl; import net.minecraft.server.MinecraftServer; import net.minecraft.server.network.ServerPlayerEntity; @@ -86,6 +89,9 @@ public void onInitialize() { ServerTickEvents.END_SERVER_TICK.register((server) -> { BackupTimer.check(); }); + + + ServerPlayNetworking.registerGlobalReceiver(NetworkHandler.TOAST_SUBSCRIBE_ID, PacketToastSubscribe::handle); } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java new file mode 100644 index 00000000..0a5ad252 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java @@ -0,0 +1,50 @@ +package co.uk.mommyheather.advancedbackups.client; + + +import co.uk.mommyheather.advancedbackups.core.CoreCommandSystem; +import net.fabricmc.fabric.api.client.command.v1.ClientCommandManager; +import net.minecraft.client.MinecraftClient; +import net.minecraft.network.packet.c2s.play.ChatMessageC2SPacket; +import net.minecraft.text.Text; + +public class AdvancedBackupsClientCommand { + public static void register() { + ClientCommandManager.DISPATCHER.register(ClientCommandManager.literal("backup").requires((runner) -> { + return runner.hasPermissionLevel(0); + }).then(ClientCommandManager.literal("start").executes((runner) -> { + MinecraftClient.getInstance().player.networkHandler.sendPacket(new ChatMessageC2SPacket("/backup start")); + return 1; + })) + + .then(ClientCommandManager.literal("reload-config").executes((runner) -> { + MinecraftClient.getInstance().player.networkHandler.sendPacket(new ChatMessageC2SPacket("/backup reload-config")); + return 1; + })) + + .then(ClientCommandManager.literal("reset-chain").executes((runner) -> { + MinecraftClient.getInstance().player.networkHandler.sendPacket(new ChatMessageC2SPacket("/backup reset-chain")); + return 1; + })) + + .then(ClientCommandManager.literal("snapshot").executes((runner) -> { + MinecraftClient.getInstance().player.networkHandler.sendPacket(new ChatMessageC2SPacket("/backup snapshot")); + return 1; + })) + + .then(ClientCommandManager.literal("cancel").executes((runner) -> { + MinecraftClient.getInstance().player.networkHandler.sendPacket(new ChatMessageC2SPacket("/backup cancel")); + return 1; + })) + + .then(ClientCommandManager.literal("reload-client-config").executes((runner) -> { + CoreCommandSystem.reloadClientConfig((response) -> { + runner.getSource().sendFeedback(Text.of(response)); + }); + return 1; + })) + + ); + } + + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java index 0ef1a2ac..c3fc669c 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java @@ -11,7 +11,6 @@ import net.minecraft.client.util.math.MatrixStack; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; -import net.minecraft.util.Formatting; public class BackupToast implements Toast { @@ -65,7 +64,7 @@ public Visibility draw(MatrixStack matrix, ToastManager manager, long startTime) return Visibility.HIDE; } - String title = "You shouldn't see this!"; + title = "You shouldn't see this!"; if (starting) { @@ -115,8 +114,8 @@ else if (cancelled) { return Visibility.HIDE; } - DrawableHelper.fill(matrix, 3, 28, Math.max(3, (int) f), 29, ColourHelper.colour - (255, (int) ClientConfigManager.progressBarRed.get(), (int) ClientConfigManager.progressBarGreen.get(), (int) ClientConfigManager.progressBarBlue.get())); + DrawableHelper.fill(matrix, 4, 28, Math.max(3, (int) f), 29, ColourHelper.colour + (255, (int) ClientConfigManager.progressBarRed.get(), (int) ClientConfigManager.progressBarGreen.get(), (int) ClientConfigManager.progressBarBlue.get())); return Visibility.SHOW; } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java index ab6e7512..7dd8f303 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java @@ -1,9 +1,17 @@ package co.uk.mommyheather.advancedbackups.client; +import co.uk.mommyheather.advancedbackups.core.ABCore; +import co.uk.mommyheather.advancedbackups.AdvancedBackups; +import co.uk.mommyheather.advancedbackups.core.config.ClientConfigManager; import co.uk.mommyheather.advancedbackups.network.NetworkHandler; import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; +import co.uk.mommyheather.advancedbackups.network.PacketToastSubscribe; import net.fabricmc.api.ClientModInitializer; +import net.fabricmc.fabric.api.client.command.v1.ClientCommandManager; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents; +import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; +import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; import net.minecraft.client.MinecraftClient; public class ClientWrapper implements ClientModInitializer { @@ -31,7 +39,22 @@ public static void handle(MinecraftClient client, PacketBackupStatus message) { @Override public void onInitializeClient() { + + ABCore.infoLogger = AdvancedBackups.infoLogger; + ABCore.warningLogger = AdvancedBackups.warningLogger; + ABCore.errorLogger = AdvancedBackups.errorLogger; + ClientPlayNetworking.registerGlobalReceiver(NetworkHandler.STATUS_PACKET_ID, PacketBackupStatus::handle); + ClientLifecycleEvents.CLIENT_STARTED.register((client) -> { + ClientConfigManager.loadOrCreateConfig(); + }); + ClientPlayConnectionEvents.JOIN.register((handler, sender, client) -> { + PacketToastSubscribe packet = new PacketToastSubscribe(ClientConfigManager.showProgress.get()); + sender.sendPacket(NetworkHandler.TOAST_SUBSCRIBE_ID, packet.write(PacketByteBufs.create())); + }); + + AdvancedBackupsClientCommand.register(); + } } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java index 0930a159..6ff65483 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java @@ -1,5 +1,6 @@ package co.uk.mommyheather.advancedbackups.network; +import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; import net.minecraft.server.network.ServerPlayerEntity; @@ -8,6 +9,7 @@ public class NetworkHandler { public static final Identifier STATUS_PACKET_ID = new Identifier("advancedbackups", "backup_status"); + public static final Identifier TOAST_SUBSCRIBE_ID = new Identifier("advancedbackups", "toast_subscribe"); public static void sendToClient(ServerPlayerEntity player, PacketBackupStatus packet) { @@ -17,5 +19,4 @@ public static void sendToClient(ServerPlayerEntity player, PacketBackupStatus pa } - } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java new file mode 100644 index 00000000..78362a93 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java @@ -0,0 +1,59 @@ +package co.uk.mommyheather.advancedbackups.network; + +import co.uk.mommyheather.advancedbackups.AdvancedBackups; +import net.fabricmc.fabric.api.networking.v1.PacketSender; +import net.minecraft.network.PacketByteBuf; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.network.ServerPlayNetworkHandler; +import net.minecraft.server.network.ServerPlayerEntity; + +public class PacketToastSubscribe { + + public boolean enable; + + + public PacketToastSubscribe(boolean enable) { + this.enable = enable; + } + + public PacketToastSubscribe() { + + } + + public void read(PacketByteBuf buf) { + enable = buf.readBoolean(); + } + + public PacketByteBuf write(PacketByteBuf buf) { + buf.writeBoolean(enable); + + return buf; + + } + + + public static void handle(MinecraftServer server, ServerPlayerEntity player, ServerPlayNetworkHandler handler, PacketByteBuf buf, PacketSender responseSender) { + + PacketToastSubscribe message = new PacketToastSubscribe(); + message.read(buf); + + + server.execute(() -> { + if (message.enable && !AdvancedBackups.players.contains(player.getUuidAsString())) { + AdvancedBackups.players.add(player.getUuidAsString()); + } + else if (!message.enable) { + AdvancedBackups.players.remove(player.getUuidAsString()); + } + + }); + + + + + + } + + + +} From 3a8c58c5436df037808558ba50fea61c6e28e5e0 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sun, 4 Feb 2024 06:39:58 +0000 Subject: [PATCH 437/580] fully support cancelling + client config in toast --- .../advancedbackups/client/BackupToast.java | 60 +++++++++++++------ .../advancedbackups/client/ColourHelper.java | 31 ++++++++++ 2 files changed, 73 insertions(+), 18 deletions(-) create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/client/ColourHelper.java diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java index aacaba27..67cd7b73 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java @@ -3,14 +3,13 @@ import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; +import co.uk.mommyheather.advancedbackups.core.config.ClientConfigManager; import net.minecraft.ChatFormatting; import net.minecraft.client.gui.Gui; import net.minecraft.client.gui.components.toasts.Toast; import net.minecraft.client.gui.components.toasts.ToastComponent; import net.minecraft.client.renderer.GameRenderer; import net.minecraft.client.resources.language.I18n; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.TranslatableComponent; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; @@ -20,6 +19,7 @@ public class BackupToast implements Toast { public static boolean started; public static boolean failed; public static boolean finished; + public static boolean cancelled; public static int progress; public static int max; @@ -31,55 +31,78 @@ public class BackupToast implements Toast { public static final ItemStack stack = new ItemStack(Items.PAPER); + private int textColour; + private String title = "You shouldn't see this!"; + @Override public Visibility render(PoseStack matrix, ToastComponent toastGui, long delta) { RenderSystem.setShader(GameRenderer::getPositionTexShader); RenderSystem.setShaderTexture(0, TEXTURE); RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); - toastGui.blit(matrix, 0, 0, 0, 0, this.width(), this.height()); - toastGui.getMinecraft().getItemRenderer().renderAndDecorateFakeItem(stack, 8, 8); - + toastGui.blit(matrix, 0, 0, 0, ClientConfigManager.darkMode.get() ? 0 : this.height(), this.width(), this.height()); + toastGui.getMinecraft().getItemRenderer().renderGuiItem(stack, 8, 8); float percent = finished ? 100 : (float) progress / (float) max; - Gui.fill(matrix, 3, 28, 156, 29, -1); + Gui.fill(matrix, 4, 28, 156, 29, ColourHelper.colour + (255, (int) ClientConfigManager.progressBackgroundRed.get(), (int) ClientConfigManager.progressBackgroundGreen.get(), (int) ClientConfigManager.progressBackgroundBlue.get())); + float f = Math.min(156, ( 156 * percent )); - - if (!exists) { - toastGui.getMinecraft().font.draw(matrix, ChatFormatting.GREEN + I18n.get("advancedbackups.backup_finished"), 25, 11, -11534256); - Gui.fill(matrix, 3, 28, 156, 29, -10948014); + if (!exists) { + if (title.equals(I18n.get("advancedbackups.backup_finished"))){ + textColour = ColourHelper.colour(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); + toastGui.getMinecraft().font.draw(matrix, I18n.get(title), 25, 11, textColour); + Gui.fill(matrix, 3, 28, 156, 29, ColourHelper.colour + (255, (int) ClientConfigManager.progressBarRed.get(), (int) ClientConfigManager.progressBarGreen.get(), (int) ClientConfigManager.progressBarBlue.get())); + } + else { + textColour = ColourHelper.colour(255, (int) ClientConfigManager.errorTextRed.get(), (int) ClientConfigManager.errorTextGreen.get(), (int) ClientConfigManager.errorTextBlue.get()); + toastGui.getMinecraft().font.draw(matrix, I18n.get(title), 25, 11, textColour); + } return Visibility.HIDE; } - String title = "You shouldn't see this!"; + title = "You shouldn't see this!"; if (starting) { - title = ChatFormatting.GREEN + I18n.get("advancedbackups.backup_starting"); + textColour = ColourHelper.colour(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); + title = I18n.get("advancedbackups.backup_starting"); } else if (started) { - title = ChatFormatting.GREEN + I18n.get("advancedbackups.progress", round(percent * 100)); + textColour = ColourHelper.colour(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); + title = I18n.get("advancedbackups.progress", round(percent * 100)); } else if (failed) { - title = ChatFormatting.RED + I18n.get("advancedbackups.backup_failed"); + textColour = ColourHelper.colour(255, (int) ClientConfigManager.errorTextRed.get(), (int) ClientConfigManager.errorTextGreen.get(), (int) ClientConfigManager.errorTextBlue.get()); + title = I18n.get("advancedbackups.backup_failed"); if (!timeSet) { time = System.currentTimeMillis(); timeSet = true; } } else if (finished) { - title = ChatFormatting.GREEN + I18n.get("advancedbackups.backup_finished"); + textColour = ColourHelper.colour(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); + title = I18n.get("advancedbackups.backup_finished"); + if (!timeSet) { + time = System.currentTimeMillis(); + timeSet = true; + } + } + else if (cancelled) { + textColour = ColourHelper.colour(255, (int) ClientConfigManager.errorTextRed.get(), (int) ClientConfigManager.errorTextGreen.get(), (int) ClientConfigManager.errorTextBlue.get()); + title = I18n.get("advancedbackups.backup_cancelled"); if (!timeSet) { time = System.currentTimeMillis(); timeSet = true; } } - toastGui.getMinecraft().font.draw(matrix, title, 25, 11, -11534256); + toastGui.getMinecraft().font.draw(matrix, title, 25, 11, textColour); if (timeSet && System.currentTimeMillis() >= time + 5000) { starting = false; @@ -92,8 +115,9 @@ else if (finished) { exists = false; return Visibility.HIDE; } - - Gui.fill(matrix, 3, 28, Math.max(3, (int) f), 29, -10948014); + + Gui.fill(matrix, 4, 28, Math.max(3, (int) f), 29, ColourHelper.colour + (255, (int) ClientConfigManager.progressBarRed.get(), (int) ClientConfigManager.progressBarGreen.get(), (int) ClientConfigManager.progressBarBlue.get())); return Visibility.SHOW; diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ColourHelper.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ColourHelper.java new file mode 100644 index 00000000..0eff6bc3 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ColourHelper.java @@ -0,0 +1,31 @@ +package co.uk.mommyheather.advancedbackups.client; + +//A colour helper, loosely based on that of vanilla 1.16. +//Where is it in 1.18? +public class ColourHelper { + + public static int alpha(int in) { + return in >>> 24; + } + + public static int red(int in) { + return in >> 16 & 255; + } + + public static int green(int in) { + return in >> 8 & 255; + } + + public static int blue(int in) { + return in & 255; + } + + public static int colour(int a, int r, int g, int b) { + return a << 24 | r << 16 | g << 8 | b; + } + + public static int colour(int a, long r, long g, long b) { + return colour(a, (int) r, (int) g, (int) b); + } + +} \ No newline at end of file From 8319fdf3fb343167d9e49b5fb89749ec2868e06b Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sun, 4 Feb 2024 06:40:11 +0000 Subject: [PATCH 438/580] cancel command, autocomplete for client reload --- .../advancedbackups/AdvancedBackupsCommand.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index 5ee3460d..c5fb94d6 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -39,6 +39,18 @@ public static void register(CommandDispatcher stack) { }); return 1; })) + + .then(Commands.literal("cancel").executes((runner) -> { + CoreCommandSystem.cancelBackup((response) -> { + runner.getSource().sendSuccess(new TextComponent(response), true); + }); + return 1; + })) + + .then(Commands.literal("reload-client-config").executes((runner) -> { + runner.getSource().sendSuccess(new TextComponent("This command can only be ran on the client!"), true); + return 1; + })) ); } From 3dec25adc786017c8e8a9a5a4723188a13c34f27 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sun, 4 Feb 2024 07:01:45 +0000 Subject: [PATCH 439/580] network a cancelled backup --- .../client/ClientContactor.java | 19 +++++++++++++------ .../advancedbackups/client/ClientWrapper.java | 1 + .../network/PacketBackupStatus.java | 6 +++++- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java index 49335183..3c25b3e7 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java @@ -16,7 +16,7 @@ public class ClientContactor implements IClientContactor { public void backupComplete() { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); List players = server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, 0, 0); + PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, false, 0, 0); for (ServerPlayer player : players) { if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; if (!server.isDedicatedServer() || player.hasPermissions(3)) { @@ -29,7 +29,7 @@ public void backupComplete() { public void backupFailed() { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); List players = server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, 0, 0); + PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, false, 0, 0); for (ServerPlayer player : players) { if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; if (!server.isDedicatedServer() || player.hasPermissions(3)) { @@ -42,7 +42,7 @@ public void backupFailed() { public void backupProgress(int progress, int max) { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); List players = server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, progress, max); + PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, false, progress, max); for (ServerPlayer player : players) { if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; if (!server.isDedicatedServer() || player.hasPermissions(3)) { @@ -55,7 +55,7 @@ public void backupProgress(int progress, int max) { public void backupStarting() { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); List players = server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, 0, 0); + PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, false, 0, 0); for (ServerPlayer player : players) { if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; if (!server.isDedicatedServer() || player.hasPermissions(3)) { @@ -66,7 +66,14 @@ public void backupStarting() { @Override public void backupCancelled() { - // temporarily here to let it compile - throw new UnsupportedOperationException("Unimplemented method 'backupCancelled'"); + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, false, false, true, 0, 0); + for (ServerPlayer player : players) { + if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; + if (!server.isDedicatedServer() || player.hasPermissions(3)) { + NetworkHandler.sendToClient(player, packet); + } + } } } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java index 27f6735c..e16307ad 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java @@ -18,6 +18,7 @@ public static void handle(PacketBackupStatus packet) { BackupToast.started = packet.started; BackupToast.failed = packet.failed; BackupToast.finished = packet.finished; + BackupToast.cancelled = packet.cancelled; BackupToast.progress = packet.progress; BackupToast.max = packet.max; diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java index 2de6fbac..4bc03330 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java @@ -14,17 +14,19 @@ public class PacketBackupStatus { public boolean failed; public boolean finished; + public boolean cancelled; public int progress; public int max; - public PacketBackupStatus(boolean starting, boolean started, boolean failed, boolean finished, int progress, + public PacketBackupStatus(boolean starting, boolean started, boolean failed, boolean finished, boolean cancelled, int progress, int max) { this.starting = starting; this.started = started; this.failed = failed; this.finished = finished; + this.cancelled = cancelled; this.progress = progress; this.max = max; } @@ -35,6 +37,7 @@ public PacketBackupStatus(FriendlyByteBuf buf) { started = buf.readBoolean(); failed = buf.readBoolean(); finished = buf.readBoolean(); + cancelled = buf.readBoolean(); progress = buf.readInt(); max = buf.readInt(); @@ -45,6 +48,7 @@ public void toBytes(FriendlyByteBuf buf) { buf.writeBoolean(started); buf.writeBoolean(failed); buf.writeBoolean(finished); + buf.writeBoolean(cancelled); buf.writeInt(progress); buf.writeInt(max); From 043b5f906056b6bbfbc5c65e9614bdb637b53f92 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sun, 4 Feb 2024 07:38:48 +0000 Subject: [PATCH 440/580] fix the 1 pixel bug --- .../co/uk/mommyheather/advancedbackups/client/BackupToast.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java index 67cd7b73..e4a485f2 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java @@ -116,7 +116,7 @@ else if (cancelled) { return Visibility.HIDE; } - Gui.fill(matrix, 4, 28, Math.max(3, (int) f), 29, ColourHelper.colour + Gui.fill(matrix, 4, 28, Math.max(4, (int) f), 29, ColourHelper.colour (255, (int) ClientConfigManager.progressBarRed.get(), (int) ClientConfigManager.progressBarGreen.get(), (int) ClientConfigManager.progressBarBlue.get())); return Visibility.SHOW; From 726afa062c39c02264c7b8a60e1079a52216d7b0 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sun, 4 Feb 2024 07:39:05 +0000 Subject: [PATCH 441/580] localise cancel text --- src/main/resources/assets/advancedbackups/lang/en_us.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/resources/assets/advancedbackups/lang/en_us.json b/src/main/resources/assets/advancedbackups/lang/en_us.json index cc68dae1..474ea8d6 100644 --- a/src/main/resources/assets/advancedbackups/lang/en_us.json +++ b/src/main/resources/assets/advancedbackups/lang/en_us.json @@ -2,5 +2,6 @@ "advancedbackups.backup_starting" : "Backup starting!", "advancedbackups.progress": "Backup ongoing: %1$s%%", "advancedbackups.backup_failed": "Backup failed!\nCheck log for more info.", - "advancedbackups.backup_finished": "Backup complete!" + "advancedbackups.backup_finished": "Backup complete!", + "advancedbackups.backup_cancelled": "Backup cancelled!" } \ No newline at end of file From fb4404286d483616fdfc0153fee84dfbb10dde43 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sun, 4 Feb 2024 07:40:04 +0000 Subject: [PATCH 442/580] localise cancel text --- src/main/resources/assets/advancedbackups/lang/en_us.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/resources/assets/advancedbackups/lang/en_us.json b/src/main/resources/assets/advancedbackups/lang/en_us.json index cc68dae1..0a1fdf4b 100644 --- a/src/main/resources/assets/advancedbackups/lang/en_us.json +++ b/src/main/resources/assets/advancedbackups/lang/en_us.json @@ -2,5 +2,6 @@ "advancedbackups.backup_starting" : "Backup starting!", "advancedbackups.progress": "Backup ongoing: %1$s%%", "advancedbackups.backup_failed": "Backup failed!\nCheck log for more info.", - "advancedbackups.backup_finished": "Backup complete!" -} \ No newline at end of file + "advancedbackups.backup_finished": "Backup complete!", + "advancedbackups.backup_cancelled": "Backup cancelled!" +} From 8741458ee28e6efded48f0996a7b7ff97682459b Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sun, 4 Feb 2024 10:57:15 +0000 Subject: [PATCH 443/580] full support of client config and cancel command! --- .../advancedbackups/AdvancedBackups.java | 9 +++ .../AdvancedBackupsCommand.java | 12 ++++ .../client/AdvancedBackupsClientCommand.java | 62 +++++++++++++++++++ .../advancedbackups/client/BackupToast.java | 52 ++++++++++++---- .../client/ClientContactor.java | 25 ++++++-- .../advancedbackups/client/ClientWrapper.java | 31 +++++++++- .../advancedbackups/client/ColourHelper.java | 31 ++++++++++ .../network/NetworkHandler.java | 1 + .../network/PacketBackupStatus.java | 10 +-- .../network/PacketToastSubscribe.java | 59 ++++++++++++++++++ 10 files changed, 269 insertions(+), 23 deletions(-) create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/client/ColourHelper.java create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 9165ba19..ca750b99 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -1,6 +1,7 @@ package co.uk.mommyheather.advancedbackups; import java.io.File; +import java.util.ArrayList; import java.util.List; import java.util.function.Consumer; @@ -12,11 +13,14 @@ import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; +import co.uk.mommyheather.advancedbackups.network.PacketToastSubscribe; import net.fabricmc.api.ModInitializer; import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; +import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; import net.fabricmc.loader.impl.FabricLoaderImpl; import net.minecraft.server.MinecraftServer; import net.minecraft.server.network.ServerPlayerEntity; @@ -33,6 +37,8 @@ public class AdvancedBackups implements ModInitializer { public static final Consumer infoLogger = LOGGER::info; public static final Consumer warningLogger = LOGGER::warn; public static final Consumer errorLogger = LOGGER::error; + + public static final ArrayList players = new ArrayList<>(); public static MinecraftServer server; @@ -82,6 +88,9 @@ public void onInitialize() { }); + ServerPlayNetworking.registerGlobalReceiver(NetworkHandler.TOAST_SUBSCRIBE_ID, PacketToastSubscribe::handle); + + } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index 4f39606a..38bd25ef 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -38,6 +38,18 @@ public static void register(CommandDispatcher stack) { }); return 1; })) + + .then(CommandManager.literal("cancel").executes((runner) -> { + CoreCommandSystem.cancelBackup((response) -> { + runner.getSource().sendFeedback(Text.of(response), true); + }); + return 1; + })) + + .then(CommandManager.literal("reload-client-config").executes((runner) -> { + runner.getSource().sendFeedback(Text.of("This command can only be ran on the client!"), true); + return 1; + })) ); } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java new file mode 100644 index 00000000..75d758d0 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java @@ -0,0 +1,62 @@ +package co.uk.mommyheather.advancedbackups.client; + + +import java.time.Instant; + +import com.mojang.brigadier.CommandDispatcher; + +import co.uk.mommyheather.advancedbackups.core.CoreCommandSystem; +import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; +import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; +import net.minecraft.client.MinecraftClient; +import net.minecraft.network.message.ArgumentSignatureDataMap; +import net.minecraft.network.message.LastSeenMessageList.Acknowledgment; +import net.minecraft.network.packet.c2s.play.CommandExecutionC2SPacket; +import net.minecraft.text.Text; + +public class AdvancedBackupsClientCommand { + public static void register(CommandDispatcher dispatcher) { + dispatcher.register(ClientCommandManager.literal("backup").requires((runner) -> { + return runner.hasPermissionLevel(0); + }).then(ClientCommandManager.literal("start").executes((runner) -> { + Acknowledgment acknowledgment = MinecraftClient.getInstance().player.networkHandler.consumeAcknowledgment(); + MinecraftClient.getInstance().player.networkHandler.sendPacket(new CommandExecutionC2SPacket("backup start", Instant.now(), 0L, ArgumentSignatureDataMap.EMPTY, false, acknowledgment)); + return 1; + })) + + .then(ClientCommandManager.literal("reload-config").executes((runner) -> { + Acknowledgment acknowledgment = MinecraftClient.getInstance().player.networkHandler.consumeAcknowledgment(); + MinecraftClient.getInstance().player.networkHandler.sendPacket(new CommandExecutionC2SPacket("backup reload-config", Instant.now(), 0L, ArgumentSignatureDataMap.EMPTY, false, acknowledgment)); + return 1; + })) + + .then(ClientCommandManager.literal("reset-chain").executes((runner) -> { + Acknowledgment acknowledgment = MinecraftClient.getInstance().player.networkHandler.consumeAcknowledgment(); + MinecraftClient.getInstance().player.networkHandler.sendPacket(new CommandExecutionC2SPacket("backup reset-chain", Instant.now(), 0L, ArgumentSignatureDataMap.EMPTY, false, acknowledgment)); + return 1; + })) + + .then(ClientCommandManager.literal("snapshot").executes((runner) -> { + Acknowledgment acknowledgment = MinecraftClient.getInstance().player.networkHandler.consumeAcknowledgment(); + MinecraftClient.getInstance().player.networkHandler.sendPacket(new CommandExecutionC2SPacket("backup snapshot", Instant.now(), 0L, ArgumentSignatureDataMap.EMPTY, false, acknowledgment)); + return 1; + })) + + .then(ClientCommandManager.literal("cancel").executes((runner) -> { + Acknowledgment acknowledgment = MinecraftClient.getInstance().player.networkHandler.consumeAcknowledgment(); + MinecraftClient.getInstance().player.networkHandler.sendPacket(new CommandExecutionC2SPacket("backup cancel", Instant.now(), 0L, ArgumentSignatureDataMap.EMPTY, false, acknowledgment)); + return 1; + })) + + .then(ClientCommandManager.literal("reload-client-config").executes((runner) -> { + CoreCommandSystem.reloadClientConfig((response) -> { + runner.getSource().sendFeedback(Text.of(response)); + }); + return 1; + })) + + ); + } + + +} \ No newline at end of file diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java index 6b0c5579..2a21d4c0 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java @@ -2,6 +2,7 @@ import com.mojang.blaze3d.systems.RenderSystem; +import co.uk.mommyheather.advancedbackups.core.config.ClientConfigManager; import net.minecraft.client.gui.DrawableHelper; import net.minecraft.client.render.GameRenderer; import net.minecraft.client.resource.language.I18n; @@ -10,7 +11,6 @@ import net.minecraft.client.util.math.MatrixStack; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; -import net.minecraft.util.Formatting; public class BackupToast implements Toast { @@ -18,6 +18,7 @@ public class BackupToast implements Toast { public static boolean started; public static boolean failed; public static boolean finished; + public static boolean cancelled; public static int progress; public static int max; @@ -29,53 +30,77 @@ public class BackupToast implements Toast { public static final ItemStack stack = new ItemStack(Items.PAPER); + public static String title = "You shouldn't see this!"; + public static int textColour = 0; + @Override public Visibility draw(MatrixStack matrix, ToastManager manager, long startTime) { RenderSystem.setShader(GameRenderer::getPositionTexShader); RenderSystem.setShaderTexture(0, TEXTURE); RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); - manager.drawTexture(matrix, 0, 0, 0, 0, this.getWidth(), this.getHeight()); + manager.drawTexture(matrix, 0, 0, 0, ClientConfigManager.darkMode.get() ? 0 : this.getHeight(), this.getWidth(), this.getHeight()); manager.getClient().getItemRenderer().renderGuiItemIcon(stack, 8, 8); float percent = finished ? 100 : (float) progress / (float) max; - DrawableHelper.fill(matrix, 3, 28, 156, 29, -1); + DrawableHelper.fill(matrix, 4, 28, 156, 29, ColourHelper.colour + (255, (int) ClientConfigManager.progressBackgroundRed.get(), (int) ClientConfigManager.progressBackgroundGreen.get(), (int) ClientConfigManager.progressBackgroundBlue.get())); float f = Math.min(156, ( 156 * percent )); - if (!exists) { - manager.getClient().textRenderer.draw(matrix, Formatting.GREEN + I18n.translate("advancedbackups.backup_finished"), 25, 11, -11534256); - DrawableHelper.fill(matrix, 3, 28, 156, 29, -10948014); + if (!exists) { + if (title.equals(I18n.translate("advancedbackups.backup_finished"))){ + textColour = ColourHelper.colour(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); + manager.getClient().textRenderer.draw(matrix, I18n.translate(title), 25, 11, textColour); + DrawableHelper.fill(matrix, 4, 28, 156, 29, ColourHelper.colour + (255, (int) ClientConfigManager.progressBarRed.get(), (int) ClientConfigManager.progressBarGreen.get(), (int) ClientConfigManager.progressBarBlue.get())); + } + else { + textColour = ColourHelper.colour(255, (int) ClientConfigManager.errorTextRed.get(), (int) ClientConfigManager.errorTextGreen.get(), (int) ClientConfigManager.errorTextBlue.get()); + manager.getClient().textRenderer.draw(matrix, I18n.translate(title), 25, 11, textColour); + } return Visibility.HIDE; } - String title = "You shouldn't see this!"; + title = "You shouldn't see this!"; if (starting) { - title = Formatting.GREEN + I18n.translate("advancedbackups.backup_starting"); + textColour = ColourHelper.colour(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); + title = I18n.translate("advancedbackups.backup_starting"); } else if (started) { - title = Formatting.GREEN + I18n.translate("advancedbackups.progress", round(percent * 100)); + textColour = ColourHelper.colour(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); + title = I18n.translate("advancedbackups.progress", round(percent * 100)); } else if (failed) { - title = Formatting.RED + I18n.translate("advancedbackups.backup_failed"); + textColour = ColourHelper.colour(255, (int) ClientConfigManager.errorTextRed.get(), (int) ClientConfigManager.errorTextGreen.get(), (int) ClientConfigManager.errorTextBlue.get()); + title = I18n.translate("advancedbackups.backup_failed"); if (!timeSet) { time = System.currentTimeMillis(); timeSet = true; } } else if (finished) { - title = Formatting.GREEN + I18n.translate("advancedbackups.backup_finished"); + textColour = ColourHelper.colour(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); + title = I18n.translate("advancedbackups.backup_finished"); + if (!timeSet) { + time = System.currentTimeMillis(); + timeSet = true; + } + } + else if (cancelled) { + textColour = ColourHelper.colour(255, (int) ClientConfigManager.errorTextRed.get(), (int) ClientConfigManager.errorTextGreen.get(), (int) ClientConfigManager.errorTextBlue.get()); + title = I18n.translate("advancedbackups.backup_cancelled"); if (!timeSet) { time = System.currentTimeMillis(); timeSet = true; } } - manager.getClient().textRenderer.draw(matrix, title, 25, 11, -11534256); + manager.getClient().textRenderer.draw(matrix, title, 25, 11, textColour); if (timeSet && System.currentTimeMillis() >= time + 5000) { starting = false; @@ -89,7 +114,8 @@ else if (finished) { return Visibility.HIDE; } - DrawableHelper.fill(matrix, 3, 28, Math.max(3, (int) f), 29, -10948014); + DrawableHelper.fill(matrix, 4, 28, Math.max(3, (int) f), 29, ColourHelper.colour + (255, (int) ClientConfigManager.progressBarRed.get(), (int) ClientConfigManager.progressBarGreen.get(), (int) ClientConfigManager.progressBarBlue.get())); return Visibility.SHOW; } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java index cf5137e9..d2072cdd 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java @@ -15,8 +15,9 @@ public class ClientContactor implements IClientContactor { public void backupComplete() { MinecraftServer server = AdvancedBackups.server; List players = server.getPlayerManager().getPlayerList(); - PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, 0, 0); + PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, false, 0, 0); for (ServerPlayerEntity player : players) { + if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; if (!server.isDedicated() || player.hasPermissionLevel(3)) { NetworkHandler.sendToClient(player, packet); } @@ -27,8 +28,9 @@ public void backupComplete() { public void backupFailed() { MinecraftServer server = AdvancedBackups.server; List players = server.getPlayerManager().getPlayerList(); - PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, 0, 0); + PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, false, 0, 0); for (ServerPlayerEntity player : players) { + if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; if (!server.isDedicated() || player.hasPermissionLevel(3)) { NetworkHandler.sendToClient(player, packet); } @@ -39,8 +41,9 @@ public void backupFailed() { public void backupProgress(int progress, int max) { MinecraftServer server = AdvancedBackups.server; List players = server.getPlayerManager().getPlayerList(); - PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, progress, max); + PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, false, progress, max); for (ServerPlayerEntity player : players) { + if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; if (!server.isDedicated() || player.hasPermissionLevel(3)) { NetworkHandler.sendToClient(player, packet); } @@ -51,8 +54,22 @@ public void backupProgress(int progress, int max) { public void backupStarting() { MinecraftServer server = AdvancedBackups.server; List players = server.getPlayerManager().getPlayerList(); - PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, 0, 0); + PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, false, 0, 0); for (ServerPlayerEntity player : players) { + if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; + if (!server.isDedicated() || player.hasPermissionLevel(3)) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupCancelled() { + MinecraftServer server = AdvancedBackups.server; + List players = server.getPlayerManager().getPlayerList(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, false, false, true, 0, 0); + for (ServerPlayerEntity player : players) { + if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; if (!server.isDedicated() || player.hasPermissionLevel(3)) { NetworkHandler.sendToClient(player, packet); } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java index 3560bdf8..53c1afd7 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java @@ -1,19 +1,47 @@ package co.uk.mommyheather.advancedbackups.client; +import co.uk.mommyheather.advancedbackups.AdvancedBackups; +import co.uk.mommyheather.advancedbackups.core.ABCore; +import co.uk.mommyheather.advancedbackups.core.config.ClientConfigManager; import co.uk.mommyheather.advancedbackups.network.NetworkHandler; import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; +import co.uk.mommyheather.advancedbackups.network.PacketToastSubscribe; import net.fabricmc.api.ClientModInitializer; +import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents; +import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; +import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; import net.fabricmc.fabric.api.networking.v1.PacketSender; import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.ClientPlayNetworkHandler; import net.minecraft.network.PacketByteBuf; public class ClientWrapper implements ClientModInitializer { - + @Override public void onInitializeClient() { + + ABCore.infoLogger = AdvancedBackups.infoLogger; + ABCore.warningLogger = AdvancedBackups.warningLogger; + ABCore.errorLogger = AdvancedBackups.errorLogger; + ClientPlayNetworking.registerGlobalReceiver(NetworkHandler.STATUS_PACKET_ID, ClientWrapper::handle); + ClientLifecycleEvents.CLIENT_STARTED.register((client) -> { + ClientConfigManager.loadOrCreateConfig(); + }); + + ClientPlayConnectionEvents.JOIN.register((handler, sender, client) -> { + PacketToastSubscribe packet = new PacketToastSubscribe(ClientConfigManager.showProgress.get()); + sender.sendPacket(NetworkHandler.TOAST_SUBSCRIBE_ID, packet.write(PacketByteBufs.create())); + }); + + ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> { + AdvancedBackupsClientCommand.register(dispatcher); + + }); + + } @@ -28,6 +56,7 @@ public static void handle(MinecraftClient client, ClientPlayNetworkHandler handl BackupToast.started = message.started; BackupToast.failed = message.failed; BackupToast.finished = message.finished; + BackupToast.cancelled = message.cancelled; BackupToast.progress = message.progress; BackupToast.max = message.max; diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ColourHelper.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ColourHelper.java new file mode 100644 index 00000000..46a47b01 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ColourHelper.java @@ -0,0 +1,31 @@ +package co.uk.mommyheather.advancedbackups.client; + +//A colour helper, loosely based on that of vanilla 1.16. +//What is the modern equivalent..? +public class ColourHelper { + + public static int alpha(int in) { + return in >>> 24; + } + + public static int red(int in) { + return in >> 16 & 255; + } + + public static int green(int in) { + return in >> 8 & 255; + } + + public static int blue(int in) { + return in & 255; + } + + public static int colour(int a, int r, int g, int b) { + return a << 24 | r << 16 | g << 8 | b; + } + + public static int colour(int a, long r, long g, long b) { + return colour(a, (int) r, (int) g, (int) b); + } + +} \ No newline at end of file diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java index 1a064957..638e62bf 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java @@ -9,6 +9,7 @@ public class NetworkHandler { public static Identifier STATUS_PACKET_ID = new Identifier("advancedbackups", "backup_status"); + public static final Identifier TOAST_SUBSCRIBE_ID = new Identifier("advancedbackups", "toast_subscribe"); public static void sendToClient(ServerPlayerEntity player, PacketBackupStatus packet) { diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java index b4d76afb..747ccc1b 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java @@ -1,9 +1,5 @@ package co.uk.mommyheather.advancedbackups.network; -import co.uk.mommyheather.advancedbackups.client.BackupToast; -import net.fabricmc.fabric.api.networking.v1.PacketSender; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.network.ClientPlayNetworkHandler; import net.minecraft.network.PacketByteBuf; public class PacketBackupStatus { @@ -12,17 +8,19 @@ public class PacketBackupStatus { public boolean started; public boolean failed; public boolean finished; + public boolean cancelled; public int progress; public int max; - public PacketBackupStatus(boolean starting, boolean started, boolean failed, boolean finished, int progress, + public PacketBackupStatus(boolean starting, boolean started, boolean failed, boolean finished, boolean cancelled, int progress, int max) { this.starting = starting; this.started = started; this.failed = failed; this.finished = finished; + this.cancelled = cancelled; this.progress = progress; this.max = max; } @@ -36,6 +34,7 @@ public void read(PacketByteBuf buf) { started = buf.readBoolean(); failed = buf.readBoolean(); finished = buf.readBoolean(); + cancelled = buf.readBoolean(); progress = buf.readInt(); max = buf.readInt(); @@ -46,6 +45,7 @@ public PacketByteBuf write(PacketByteBuf buf) { buf.writeBoolean(started); buf.writeBoolean(failed); buf.writeBoolean(finished); + buf.writeBoolean(cancelled); buf.writeInt(progress); buf.writeInt(max); diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java new file mode 100644 index 00000000..28c99f76 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java @@ -0,0 +1,59 @@ +package co.uk.mommyheather.advancedbackups.network; + +import co.uk.mommyheather.advancedbackups.AdvancedBackups; +import net.fabricmc.fabric.api.networking.v1.PacketSender; +import net.minecraft.network.PacketByteBuf; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.network.ServerPlayNetworkHandler; +import net.minecraft.server.network.ServerPlayerEntity; + +public class PacketToastSubscribe { + + public boolean enable; + + + public PacketToastSubscribe(boolean enable) { + this.enable = enable; + } + + public PacketToastSubscribe() { + + } + + public void read(PacketByteBuf buf) { + enable = buf.readBoolean(); + } + + public PacketByteBuf write(PacketByteBuf buf) { + buf.writeBoolean(enable); + + return buf; + + } + + + public static void handle(MinecraftServer server, ServerPlayerEntity player, ServerPlayNetworkHandler handler, PacketByteBuf buf, PacketSender responseSender) { + + PacketToastSubscribe message = new PacketToastSubscribe(); + message.read(buf); + + + server.execute(() -> { + if (message.enable && !AdvancedBackups.players.contains(player.getUuidAsString())) { + AdvancedBackups.players.add(player.getUuidAsString()); + } + else if (!message.enable) { + AdvancedBackups.players.remove(player.getUuidAsString()); + } + + }); + + + + + + } + + + +} \ No newline at end of file From fb7c33ac718107c73a0f6151d4d88b2f12f71116 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sun, 4 Feb 2024 10:58:16 +0000 Subject: [PATCH 444/580] updfate localisation --- src/main/resources/assets/advancedbackups/lang/en_us.json | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/resources/assets/advancedbackups/lang/en_us.json b/src/main/resources/assets/advancedbackups/lang/en_us.json index cc68dae1..66caf08d 100644 --- a/src/main/resources/assets/advancedbackups/lang/en_us.json +++ b/src/main/resources/assets/advancedbackups/lang/en_us.json @@ -2,5 +2,6 @@ "advancedbackups.backup_starting" : "Backup starting!", "advancedbackups.progress": "Backup ongoing: %1$s%%", "advancedbackups.backup_failed": "Backup failed!\nCheck log for more info.", + "advancedbackups.backup_cancelled": "Backup cancelled!", "advancedbackups.backup_finished": "Backup complete!" } \ No newline at end of file From cea2f67c777565059947947153f98c6abf694768 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sun, 4 Feb 2024 20:25:50 +0000 Subject: [PATCH 445/580] bring up to speed with 3.5 - including localisation --- .../advancedbackups/AdvancedBackups.java | 73 +++++++++++-------- .../AdvancedBackupsCommand.java | 12 +++ .../client/AdvancedBackupsClientCommand.java | 67 +++++++++++++++++ .../advancedbackups/client/BackupToast.java | 58 +++++++++++---- .../client/ClientContactor.java | 26 ++++++- .../advancedbackups/client/ClientWrapper.java | 22 ++++++ .../advancedbackups/client/ColourHelper.java | 31 ++++++++ .../network/NetworkHandler.java | 10 +++ .../network/PacketBackupStatus.java | 6 +- .../network/PacketToastSubscribe.java | 41 +++++++++++ .../assets/advancedbackups/lang/en_us.json | 1 + 11 files changed, 296 insertions(+), 51 deletions(-) create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/client/ColourHelper.java create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 9b1739a0..1a90235a 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -1,5 +1,6 @@ package co.uk.mommyheather.advancedbackups; +import java.util.ArrayList; import java.util.List; import java.util.function.Consumer; @@ -8,6 +9,7 @@ import com.mojang.logging.LogUtils; import co.uk.mommyheather.advancedbackups.client.ClientContactor; +import co.uk.mommyheather.advancedbackups.client.ClientWrapper; import co.uk.mommyheather.advancedbackups.core.ABCore; import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; @@ -20,7 +22,6 @@ import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.RegisterCommandsEvent; import net.minecraftforge.event.TickEvent; -import net.minecraftforge.event.TickEvent.Phase; import net.minecraftforge.event.entity.player.PlayerEvent; import net.minecraftforge.event.server.ServerStartedEvent; import net.minecraftforge.event.server.ServerStartingEvent; @@ -28,6 +29,8 @@ import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.ModList; import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; +import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; import net.minecraftforge.server.ServerLifecycleHooks; @Mod("advancedbackups") @@ -40,18 +43,18 @@ public class AdvancedBackups public static final Consumer warningLogger = LOGGER::warn; public static final Consumer errorLogger = LOGGER::error; + public static final ArrayList players = new ArrayList<>(); + public AdvancedBackups() { // Register ourselves for server and other game events we are interested in MinecraftForge.EVENT_BUS.register(this); + FMLJavaModLoadingContext.get().getModEventBus().addListener(this::clientSetup); NetworkHandler.register(); - } - - @SubscribeEvent - public void onTickEnd(TickEvent.ServerTickEvent event) { - if (event.phase != Phase.END) return; - BackupTimer.check(); + ABCore.infoLogger = infoLogger; + ABCore.warningLogger = warningLogger; + ABCore.errorLogger = errorLogger; } @SubscribeEvent @@ -61,23 +64,27 @@ public void onServerStarting(ServerStartingEvent event) ABCore.worldName = event.getServer().getWorldData().getLevelName(); ABCore.worldDir = event.getServer().getWorldPath(LevelResource.ROOT); + ABCore.disableSaving = AdvancedBackups::disableSaving; ABCore.enableSaving = AdvancedBackups::enableSaving; ABCore.saveOnce = AdvancedBackups::saveOnce; - ABCore.infoLogger = infoLogger; - ABCore.warningLogger = warningLogger; - ABCore.errorLogger = errorLogger; - ABCore.resetActivity = AdvancedBackups::resetActivity; + ABCore.resetActivity = AdvancedBackups::resetActivity; ABCore.clientContactor = new ClientContactor(); + ABCore.modJar = ModList.get().getModFileById("advancedbackups").getFile().getFilePath().toFile(); ConfigManager.loadOrCreateConfig(); LOGGER.info("Config loaded!!"); + + } + + public void clientSetup(FMLClientSetupEvent e) { + ClientWrapper.init(e); } @SubscribeEvent @@ -101,30 +108,36 @@ public void registerCommands(RegisterCommandsEvent event){ AdvancedBackupsCommand.register(event.getDispatcher()); } + @SubscribeEvent + public void onTickEnd(TickEvent.ServerTickEvent event) { + if (!event.phase.equals(TickEvent.Phase.END)) return; + BackupTimer.check(); + } + public static final String savesDisabledMessage = """ - *************************************** - SAVING DISABLED - PREPARING FOR BACKUP! - *************************************** - """; +*************************************** +SAVING DISABLED - PREPARING FOR BACKUP! +*************************************** +"""; public static final String savesEnabledMessage = """ - - - ********************************* - SAVING ENABLED - BACKUP COMPLETE! - ********************************* - """; + + +********************************* +SAVING ENABLED - BACKUP COMPLETE! +********************************* +"""; public static final String saveCompleteMessage = """ - - - ************************************* - SAVE COMPLETE - PREPARING FOR BACKUP! - ************************************* - """; - - + + +************************************* +SAVE COMPLETE - PREPARING FOR BACKUP! +************************************* +"""; + + public static void disableSaving() { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); for (ServerLevel level : server.getAllLevels()) { @@ -147,7 +160,7 @@ public static void enableSaving() { warningLogger.accept(savesEnabledMessage); } - public static void saveOnce(boolean flush) { + public static void saveOnce(Boolean flush) { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); server.saveEverything(true, flush, true); if (ConfigManager.silent.get()) return; diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index e611ccc0..dcac6da8 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -39,6 +39,18 @@ public static void register(CommandDispatcher stack) { }); return 1; })) + + .then(Commands.literal("cancel").executes((runner) -> { + CoreCommandSystem.cancelBackup((response) -> { + runner.getSource().sendSuccess(Component.literal(response), true); + }); + return 1; + })) + + .then(Commands.literal("reload-client-config").executes((runner) -> { + runner.getSource().sendSuccess(Component.literal("This command can only be ran on the client!"), true); + return 1; + })) ); } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java new file mode 100644 index 00000000..826903a1 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java @@ -0,0 +1,67 @@ +package co.uk.mommyheather.advancedbackups.client; + +import java.time.Instant; + +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; + +import co.uk.mommyheather.advancedbackups.core.CoreCommandSystem; +import net.minecraft.client.Minecraft; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.commands.arguments.ArgumentSignatures; +import net.minecraft.network.chat.Component; +import net.minecraft.network.protocol.game.ServerboundChatCommandPacket; +import net.minecraftforge.client.ClientCommandSourceStack; +import net.minecraftforge.server.ServerLifecycleHooks; + +public class AdvancedBackupsClientCommand { + public static void register(CommandDispatcher commandDispatcher) { + commandDispatcher.register(literal("backup").requires((runner) -> { + return !ServerLifecycleHooks.getCurrentServer().isDedicatedServer() || runner.hasPermission(3); + }).then(literal("start").executes((runner) -> { + Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup start", Instant.now(), 0, + ArgumentSignatures.EMPTY, false, Minecraft.getInstance().player.connection.generateMessageAcknowledgements())); + return 1; + })) + + .then(literal("reload-config").executes((runner) -> { + Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup reload-config", Instant.now(), 0, + ArgumentSignatures.EMPTY, false, Minecraft.getInstance().player.connection.generateMessageAcknowledgements())); + return 1; + })) + + .then(literal("reset-chain").executes((runner) -> { + Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup reset-chain", Instant.now(), 0, + ArgumentSignatures.EMPTY, false, Minecraft.getInstance().player.connection.generateMessageAcknowledgements())); + return 1; + })) + + .then(literal("snapshot").executes((runner) -> { + Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup snapshot", Instant.now(), 0, + ArgumentSignatures.EMPTY, false, Minecraft.getInstance().player.connection.generateMessageAcknowledgements())); + return 1; + })) + + .then(literal("cancel").executes((runner) -> { + Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup cancel", Instant.now(), 0, + ArgumentSignatures.EMPTY, false, Minecraft.getInstance().player.connection.generateMessageAcknowledgements())); + return 1; + })) + + .then(literal("reload-client-config").executes((runner) -> { + CoreCommandSystem.reloadClientConfig((response) -> { + runner.getSource().sendSuccess(Component.literal(response), true); + }); + return 1; + })) + + ); + } + + //I'm no fan of having this here but it seems required + public static LiteralArgumentBuilder literal(String literal) { + return LiteralArgumentBuilder.literal(literal); + } + + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java index 710d549f..e4a485f2 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java @@ -3,6 +3,7 @@ import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; +import co.uk.mommyheather.advancedbackups.core.config.ClientConfigManager; import net.minecraft.ChatFormatting; import net.minecraft.client.gui.Gui; import net.minecraft.client.gui.components.toasts.Toast; @@ -18,6 +19,7 @@ public class BackupToast implements Toast { public static boolean started; public static boolean failed; public static boolean finished; + public static boolean cancelled; public static int progress; public static int max; @@ -29,55 +31,78 @@ public class BackupToast implements Toast { public static final ItemStack stack = new ItemStack(Items.PAPER); + private int textColour; + private String title = "You shouldn't see this!"; + @Override public Visibility render(PoseStack matrix, ToastComponent toastGui, long delta) { RenderSystem.setShader(GameRenderer::getPositionTexShader); RenderSystem.setShaderTexture(0, TEXTURE); RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); - toastGui.blit(matrix, 0, 0, 0, 0, this.width(), this.height()); - toastGui.getMinecraft().getItemRenderer().renderAndDecorateFakeItem(stack, 8, 8); - + toastGui.blit(matrix, 0, 0, 0, ClientConfigManager.darkMode.get() ? 0 : this.height(), this.width(), this.height()); + toastGui.getMinecraft().getItemRenderer().renderGuiItem(stack, 8, 8); float percent = finished ? 100 : (float) progress / (float) max; - Gui.fill(matrix, 3, 28, 156, 29, -1); + Gui.fill(matrix, 4, 28, 156, 29, ColourHelper.colour + (255, (int) ClientConfigManager.progressBackgroundRed.get(), (int) ClientConfigManager.progressBackgroundGreen.get(), (int) ClientConfigManager.progressBackgroundBlue.get())); + float f = Math.min(156, ( 156 * percent )); - - if (!exists) { - toastGui.getMinecraft().font.draw(matrix, ChatFormatting.GREEN + I18n.get("advancedbackups.backup_finished"), 25, 11, -11534256); - Gui.fill(matrix, 3, 28, 156, 29, -10948014); + if (!exists) { + if (title.equals(I18n.get("advancedbackups.backup_finished"))){ + textColour = ColourHelper.colour(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); + toastGui.getMinecraft().font.draw(matrix, I18n.get(title), 25, 11, textColour); + Gui.fill(matrix, 3, 28, 156, 29, ColourHelper.colour + (255, (int) ClientConfigManager.progressBarRed.get(), (int) ClientConfigManager.progressBarGreen.get(), (int) ClientConfigManager.progressBarBlue.get())); + } + else { + textColour = ColourHelper.colour(255, (int) ClientConfigManager.errorTextRed.get(), (int) ClientConfigManager.errorTextGreen.get(), (int) ClientConfigManager.errorTextBlue.get()); + toastGui.getMinecraft().font.draw(matrix, I18n.get(title), 25, 11, textColour); + } return Visibility.HIDE; } - String title = "You shouldn't see this!"; + title = "You shouldn't see this!"; if (starting) { - title = ChatFormatting.GREEN + I18n.get("advancedbackups.backup_starting"); + textColour = ColourHelper.colour(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); + title = I18n.get("advancedbackups.backup_starting"); } else if (started) { - title = ChatFormatting.GREEN + I18n.get("advancedbackups.progress", round(percent * 100)); + textColour = ColourHelper.colour(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); + title = I18n.get("advancedbackups.progress", round(percent * 100)); } else if (failed) { - title = ChatFormatting.RED + I18n.get("advancedbackups.backup_failed"); + textColour = ColourHelper.colour(255, (int) ClientConfigManager.errorTextRed.get(), (int) ClientConfigManager.errorTextGreen.get(), (int) ClientConfigManager.errorTextBlue.get()); + title = I18n.get("advancedbackups.backup_failed"); if (!timeSet) { time = System.currentTimeMillis(); timeSet = true; } } else if (finished) { - title = ChatFormatting.GREEN + I18n.get("advancedbackups.backup_finished"); + textColour = ColourHelper.colour(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); + title = I18n.get("advancedbackups.backup_finished"); + if (!timeSet) { + time = System.currentTimeMillis(); + timeSet = true; + } + } + else if (cancelled) { + textColour = ColourHelper.colour(255, (int) ClientConfigManager.errorTextRed.get(), (int) ClientConfigManager.errorTextGreen.get(), (int) ClientConfigManager.errorTextBlue.get()); + title = I18n.get("advancedbackups.backup_cancelled"); if (!timeSet) { time = System.currentTimeMillis(); timeSet = true; } } - toastGui.getMinecraft().font.draw(matrix, title, 25, 11, -11534256); + toastGui.getMinecraft().font.draw(matrix, title, 25, 11, textColour); if (timeSet && System.currentTimeMillis() >= time + 5000) { starting = false; @@ -90,8 +115,9 @@ else if (finished) { exists = false; return Visibility.HIDE; } - - Gui.fill(matrix, 3, 28, Math.max(3, (int) f), 29, -10948014); + + Gui.fill(matrix, 4, 28, Math.max(4, (int) f), 29, ColourHelper.colour + (255, (int) ClientConfigManager.progressBarRed.get(), (int) ClientConfigManager.progressBarGreen.get(), (int) ClientConfigManager.progressBarBlue.get())); return Visibility.SHOW; diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java index 2c72a8c7..3c25b3e7 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java @@ -2,6 +2,7 @@ import java.util.List; +import co.uk.mommyheather.advancedbackups.AdvancedBackups; import co.uk.mommyheather.advancedbackups.interfaces.IClientContactor; import co.uk.mommyheather.advancedbackups.network.NetworkHandler; import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; @@ -15,8 +16,9 @@ public class ClientContactor implements IClientContactor { public void backupComplete() { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); List players = server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, 0, 0); + PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, false, 0, 0); for (ServerPlayer player : players) { + if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; if (!server.isDedicatedServer() || player.hasPermissions(3)) { NetworkHandler.sendToClient(player, packet); } @@ -27,8 +29,9 @@ public void backupComplete() { public void backupFailed() { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); List players = server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, 0, 0); + PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, false, 0, 0); for (ServerPlayer player : players) { + if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; if (!server.isDedicatedServer() || player.hasPermissions(3)) { NetworkHandler.sendToClient(player, packet); } @@ -39,8 +42,9 @@ public void backupFailed() { public void backupProgress(int progress, int max) { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); List players = server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, progress, max); + PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, false, progress, max); for (ServerPlayer player : players) { + if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; if (!server.isDedicatedServer() || player.hasPermissions(3)) { NetworkHandler.sendToClient(player, packet); } @@ -51,8 +55,22 @@ public void backupProgress(int progress, int max) { public void backupStarting() { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); List players = server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, 0, 0); + PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, false, 0, 0); for (ServerPlayer player : players) { + if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; + if (!server.isDedicatedServer() || player.hasPermissions(3)) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupCancelled() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, false, false, true, 0, 0); + for (ServerPlayer player : players) { + if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; if (!server.isDedicatedServer() || player.hasPermissions(3)) { NetworkHandler.sendToClient(player, packet); } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java index 59709b69..8ed0cb03 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java @@ -1,7 +1,14 @@ package co.uk.mommyheather.advancedbackups.client; +import co.uk.mommyheather.advancedbackups.core.config.ClientConfigManager; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; +import co.uk.mommyheather.advancedbackups.network.PacketToastSubscribe; import net.minecraft.client.Minecraft; +import net.minecraftforge.client.event.ClientPlayerNetworkEvent; +import net.minecraftforge.client.event.RegisterClientCommandsEvent; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; public class ClientWrapper { @@ -10,6 +17,7 @@ public static void handle(PacketBackupStatus packet) { BackupToast.started = packet.started; BackupToast.failed = packet.failed; BackupToast.finished = packet.finished; + BackupToast.cancelled = packet.cancelled; BackupToast.progress = packet.progress; BackupToast.max = packet.max; @@ -19,5 +27,19 @@ public static void handle(PacketBackupStatus packet) { Minecraft.getInstance().getToasts().addToast(new BackupToast()); } } + + public static void init(FMLClientSetupEvent e) { + MinecraftForge.EVENT_BUS.addListener(ClientWrapper::registerClientCommands); + MinecraftForge.EVENT_BUS.addListener(ClientWrapper::onServerConnected); + ClientConfigManager.loadOrCreateConfig(); + } + + public static void registerClientCommands(RegisterClientCommandsEvent event) { + AdvancedBackupsClientCommand.register(event.getDispatcher()); + } + + public static void onServerConnected(ClientPlayerNetworkEvent.LoggingIn event) { + NetworkHandler.sendToServer(new PacketToastSubscribe(ClientConfigManager.showProgress.get())); + } } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ColourHelper.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ColourHelper.java new file mode 100644 index 00000000..dd559425 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ColourHelper.java @@ -0,0 +1,31 @@ +package co.uk.mommyheather.advancedbackups.client; + +//A colour helper, loosely based on that of vanilla 1.16. +//Where is it in modern? +public class ColourHelper { + + public static int alpha(int in) { + return in >>> 24; + } + + public static int red(int in) { + return in >> 16 & 255; + } + + public static int green(int in) { + return in >> 8 & 255; + } + + public static int blue(int in) { + return in & 255; + } + + public static int colour(int a, int r, int g, int b) { + return a << 24 | r << 16 | g << 8 | b; + } + + public static int colour(int a, long r, long g, long b) { + return colour(a, (int) r, (int) g, (int) b); + } + +} \ No newline at end of file diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java index 69a388a4..3d87e79a 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java @@ -28,10 +28,20 @@ public static void register() { .decoder(buf -> new PacketBackupStatus(buf)) .consumer(PacketBackupStatus::handle) .add(); + + INSTANCE.messageBuilder(PacketToastSubscribe.class, id()) + .encoder(PacketToastSubscribe::toBytes) + .decoder(buf -> new PacketToastSubscribe(buf)) + .consumer(PacketToastSubscribe::handle) + .add(); } public static void sendToClient(ServerPlayer player, Object packet) { INSTANCE.sendTo(packet, player.connection.connection, NetworkDirection.PLAY_TO_CLIENT); } + public static void sendToServer(Object packet) { + INSTANCE.sendToServer(packet); + } + } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java index 2de6fbac..4bc03330 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java @@ -14,17 +14,19 @@ public class PacketBackupStatus { public boolean failed; public boolean finished; + public boolean cancelled; public int progress; public int max; - public PacketBackupStatus(boolean starting, boolean started, boolean failed, boolean finished, int progress, + public PacketBackupStatus(boolean starting, boolean started, boolean failed, boolean finished, boolean cancelled, int progress, int max) { this.starting = starting; this.started = started; this.failed = failed; this.finished = finished; + this.cancelled = cancelled; this.progress = progress; this.max = max; } @@ -35,6 +37,7 @@ public PacketBackupStatus(FriendlyByteBuf buf) { started = buf.readBoolean(); failed = buf.readBoolean(); finished = buf.readBoolean(); + cancelled = buf.readBoolean(); progress = buf.readInt(); max = buf.readInt(); @@ -45,6 +48,7 @@ public void toBytes(FriendlyByteBuf buf) { buf.writeBoolean(started); buf.writeBoolean(failed); buf.writeBoolean(finished); + buf.writeBoolean(cancelled); buf.writeInt(progress); buf.writeInt(max); diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java new file mode 100644 index 00000000..49bbcf02 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java @@ -0,0 +1,41 @@ +package co.uk.mommyheather.advancedbackups.network; + +import java.util.function.Supplier; + +import co.uk.mommyheather.advancedbackups.AdvancedBackups; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraftforge.network.NetworkEvent; + +public class PacketToastSubscribe { + + private boolean enable; + + public PacketToastSubscribe(boolean enable) { + this.enable = enable; + } + + + public PacketToastSubscribe(FriendlyByteBuf buf) { + enable = buf.readBoolean(); + } + + public void toBytes(FriendlyByteBuf buf) { + buf.writeBoolean(enable); + } + + public boolean handle(Supplier ctx) { + ctx.get().enqueueWork(() -> { + if (ctx.get().getSender() == null) return; + if (enable && !AdvancedBackups.players.contains(ctx.get().getSender().getStringUUID())) { + AdvancedBackups.players.add(ctx.get().getSender().getStringUUID()); + } + else if (!enable) { + AdvancedBackups.players.remove(ctx.get().getSender().getStringUUID()); + } + }); + + return true; + + } + +} diff --git a/src/main/resources/assets/advancedbackups/lang/en_us.json b/src/main/resources/assets/advancedbackups/lang/en_us.json index cc68dae1..66caf08d 100644 --- a/src/main/resources/assets/advancedbackups/lang/en_us.json +++ b/src/main/resources/assets/advancedbackups/lang/en_us.json @@ -2,5 +2,6 @@ "advancedbackups.backup_starting" : "Backup starting!", "advancedbackups.progress": "Backup ongoing: %1$s%%", "advancedbackups.backup_failed": "Backup failed!\nCheck log for more info.", + "advancedbackups.backup_cancelled": "Backup cancelled!", "advancedbackups.backup_finished": "Backup complete!" } \ No newline at end of file From 208526af18b4ec8f3e82d0e5f3c2eaa791998361 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Mon, 5 Feb 2024 21:31:10 +0000 Subject: [PATCH 446/580] i hate needing an AW for this. rework at some point? --- build.gradle | 3 +++ src/main/resources/advancedbackups.accesswidener | 4 ++++ 2 files changed, 7 insertions(+) create mode 100644 src/main/resources/advancedbackups.accesswidener diff --git a/build.gradle b/build.gradle index 922c32ce..6753fb87 100644 --- a/build.gradle +++ b/build.gradle @@ -6,6 +6,9 @@ plugins { group = project.maven_group archivesBaseName = 'AdvancedBackups-' + modloaderName + "-" + minecraftVersion +loom { + accessWidenerPath = file("src/main/resources/advancedbackups.accesswidener") +} repositories { diff --git a/src/main/resources/advancedbackups.accesswidener b/src/main/resources/advancedbackups.accesswidener new file mode 100644 index 00000000..7ed2cc67 --- /dev/null +++ b/src/main/resources/advancedbackups.accesswidener @@ -0,0 +1,4 @@ +accessWidener v2 named + +#Required for commands for now, should rework this at some point +accessible field net/minecraft/client/network/ClientPlayNetworkHandler lastSeenMessagesCollector Lnet/minecraft/network/message/LastSeenMessagesCollector; \ No newline at end of file From b3eb8b568da2917dd4b14a418c7aa3252c09ac30 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Mon, 5 Feb 2024 21:31:25 +0000 Subject: [PATCH 447/580] 3.5, for fabric 1.19.3/4! --- .../advancedbackups/AdvancedBackups.java | 9 +++ .../AdvancedBackupsCommand.java | 12 ++++ .../client/AdvancedBackupsClientCommand.java | 62 +++++++++++++++++++ .../advancedbackups/client/BackupToast.java | 55 +++++++++++----- .../client/ClientContactor.java | 33 +++++++--- .../advancedbackups/client/ClientWrapper.java | 31 +++++++++- .../advancedbackups/client/ColourHelper.java | 31 ++++++++++ .../network/NetworkHandler.java | 1 + .../network/PacketBackupStatus.java | 10 +-- .../network/PacketToastSubscribe.java | 59 ++++++++++++++++++ .../assets/advancedbackups/lang/en_us.json | 1 + 11 files changed, 276 insertions(+), 28 deletions(-) create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/client/ColourHelper.java create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 9165ba19..ca750b99 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -1,6 +1,7 @@ package co.uk.mommyheather.advancedbackups; import java.io.File; +import java.util.ArrayList; import java.util.List; import java.util.function.Consumer; @@ -12,11 +13,14 @@ import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; +import co.uk.mommyheather.advancedbackups.network.PacketToastSubscribe; import net.fabricmc.api.ModInitializer; import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; +import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; import net.fabricmc.loader.impl.FabricLoaderImpl; import net.minecraft.server.MinecraftServer; import net.minecraft.server.network.ServerPlayerEntity; @@ -33,6 +37,8 @@ public class AdvancedBackups implements ModInitializer { public static final Consumer infoLogger = LOGGER::info; public static final Consumer warningLogger = LOGGER::warn; public static final Consumer errorLogger = LOGGER::error; + + public static final ArrayList players = new ArrayList<>(); public static MinecraftServer server; @@ -82,6 +88,9 @@ public void onInitialize() { }); + ServerPlayNetworking.registerGlobalReceiver(NetworkHandler.TOAST_SUBSCRIBE_ID, PacketToastSubscribe::handle); + + } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index 4f39606a..0c5ac9be 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -38,6 +38,18 @@ public static void register(CommandDispatcher stack) { }); return 1; })) + + .then(CommandManager.literal("cancel").executes((runner) -> { + CoreCommandSystem.cancelBackup((response) -> { + runner.getSource().sendFeedback(Text.of(response), true); + }); + return 1; + })) + + .then(CommandManager.literal("reload-client-config").executes((runner) -> { + runner.getSource().sendFeedback(Text.of("This command can only be ran on the client!"), false); + return 1; + })) ); } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java new file mode 100644 index 00000000..f3f18fdf --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java @@ -0,0 +1,62 @@ +package co.uk.mommyheather.advancedbackups.client; + + +import java.time.Instant; + +import com.mojang.brigadier.CommandDispatcher; + +import co.uk.mommyheather.advancedbackups.core.CoreCommandSystem; +import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; +import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; +import net.minecraft.client.MinecraftClient; +import net.minecraft.network.message.ArgumentSignatureDataMap; +import net.minecraft.network.message.LastSeenMessageList.Acknowledgment; +import net.minecraft.network.packet.c2s.play.CommandExecutionC2SPacket; +import net.minecraft.text.Text; + +public class AdvancedBackupsClientCommand { + public static void register(CommandDispatcher dispatcher) { + dispatcher.register(ClientCommandManager.literal("backup").requires((runner) -> { + return runner.hasPermissionLevel(0); + }).then(ClientCommandManager.literal("start").executes((runner) -> { + Acknowledgment acknowledgment = MinecraftClient.getInstance().player.networkHandler.lastSeenMessagesCollector.collect().update(); + MinecraftClient.getInstance().player.networkHandler.sendPacket(new CommandExecutionC2SPacket("backup start", Instant.now(), 0L, ArgumentSignatureDataMap.EMPTY, acknowledgment)); + return 1; + })) + + .then(ClientCommandManager.literal("reload-config").executes((runner) -> { + Acknowledgment acknowledgment = MinecraftClient.getInstance().player.networkHandler.lastSeenMessagesCollector.collect().update(); + MinecraftClient.getInstance().player.networkHandler.sendPacket(new CommandExecutionC2SPacket("backup reload-config", Instant.now(), 0L, ArgumentSignatureDataMap.EMPTY, acknowledgment)); + return 1; + })) + + .then(ClientCommandManager.literal("reset-chain").executes((runner) -> { + Acknowledgment acknowledgment = MinecraftClient.getInstance().player.networkHandler.lastSeenMessagesCollector.collect().update(); + MinecraftClient.getInstance().player.networkHandler.sendPacket(new CommandExecutionC2SPacket("backup reset-chain", Instant.now(), 0L, ArgumentSignatureDataMap.EMPTY, acknowledgment)); + return 1; + })) + + .then(ClientCommandManager.literal("snapshot").executes((runner) -> { + Acknowledgment acknowledgment = MinecraftClient.getInstance().player.networkHandler.lastSeenMessagesCollector.collect().update(); + MinecraftClient.getInstance().player.networkHandler.sendPacket(new CommandExecutionC2SPacket("backup snapshot", Instant.now(), 0L, ArgumentSignatureDataMap.EMPTY, acknowledgment)); + return 1; + })) + + .then(ClientCommandManager.literal("cancel").executes((runner) -> { + Acknowledgment acknowledgment = MinecraftClient.getInstance().player.networkHandler.lastSeenMessagesCollector.collect().update(); + MinecraftClient.getInstance().player.networkHandler.sendPacket(new CommandExecutionC2SPacket("backup cancel", Instant.now(), 0L, ArgumentSignatureDataMap.EMPTY, acknowledgment)); + return 1; + })) + + .then(ClientCommandManager.literal("reload-client-config").executes((runner) -> { + CoreCommandSystem.reloadClientConfig((response) -> { + runner.getSource().sendFeedback(Text.of(response)); + }); + return 1; + })) + + ); + } + + +} \ No newline at end of file diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java index 8a8915ee..d6193b63 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java @@ -2,15 +2,14 @@ import com.mojang.blaze3d.systems.RenderSystem; +import co.uk.mommyheather.advancedbackups.core.config.ClientConfigManager; import net.minecraft.client.gui.DrawableHelper; -import net.minecraft.client.render.GameRenderer; import net.minecraft.client.resource.language.I18n; import net.minecraft.client.toast.Toast; import net.minecraft.client.toast.ToastManager; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; -import net.minecraft.util.Formatting; public class BackupToast implements Toast { @@ -18,6 +17,7 @@ public class BackupToast implements Toast { public static boolean started; public static boolean failed; public static boolean finished; + public static boolean cancelled; public static int progress; public static int max; @@ -29,58 +29,84 @@ public class BackupToast implements Toast { public static final ItemStack stack = new ItemStack(Items.PAPER); + public static String title = "You shouldn't see this!"; + public static int textColour = 0; + @Override public Visibility draw(MatrixStack matrix, ToastManager manager, long startTime) { RenderSystem.setShaderTexture(0, TEXTURE); RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); - DrawableHelper.drawTexture(matrix, 0, 0, 0, 0, this.getWidth(), this.getHeight()); + DrawableHelper.drawTexture(matrix, 0, 0, 0, ClientConfigManager.darkMode.get() ? 0 : this.getHeight(), this.getWidth(), this.getHeight()); manager.getClient().getItemRenderer().renderInGui(matrix, stack, 8, 8); float percent = finished ? 100 : (float) progress / (float) max; - DrawableHelper.fill(matrix, 3, 28, 156, 29, -1); + DrawableHelper.fill(matrix, 4, 28, 156, 29, ColourHelper.colour + (255, (int) ClientConfigManager.progressBackgroundRed.get(), (int) ClientConfigManager.progressBackgroundGreen.get(), (int) ClientConfigManager.progressBackgroundBlue.get())); float f = Math.min(156, ( 156 * percent )); - if (!exists) { - manager.getClient().textRenderer.draw(matrix, Formatting.GREEN + I18n.translate("advancedbackups.backup_finished"), 25, 11, -11534256); - DrawableHelper.fill(matrix, 3, 28, 156, 29, -10948014); + + if (!exists) { + if (title.equals(I18n.translate("advancedbackups.backup_finished"))){ + textColour = ColourHelper.colour(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); + manager.getClient().textRenderer.draw(matrix, I18n.translate(title), 25, 11, textColour); + DrawableHelper.fill(matrix, 4, 28, 156, 29, ColourHelper.colour + (255, (int) ClientConfigManager.progressBarRed.get(), (int) ClientConfigManager.progressBarGreen.get(), (int) ClientConfigManager.progressBarBlue.get())); + } + else { + textColour = ColourHelper.colour(255, (int) ClientConfigManager.errorTextRed.get(), (int) ClientConfigManager.errorTextGreen.get(), (int) ClientConfigManager.errorTextBlue.get()); + manager.getClient().textRenderer.draw(matrix, I18n.translate(title), 25, 11, textColour); + } return Visibility.HIDE; } - String title = "You shouldn't see this!"; + title = "You shouldn't see this!"; if (starting) { - title = Formatting.GREEN + I18n.translate("advancedbackups.backup_starting"); + textColour = ColourHelper.colour(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); + title = I18n.translate("advancedbackups.backup_starting"); } else if (started) { - title = Formatting.GREEN + I18n.translate("advancedbackups.progress", round(percent * 100)); + textColour = ColourHelper.colour(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); + title = I18n.translate("advancedbackups.progress", round(percent * 100)); } else if (failed) { - title = Formatting.RED + I18n.translate("advancedbackups.backup_failed"); + textColour = ColourHelper.colour(255, (int) ClientConfigManager.errorTextRed.get(), (int) ClientConfigManager.errorTextGreen.get(), (int) ClientConfigManager.errorTextBlue.get()); + title = I18n.translate("advancedbackups.backup_failed"); if (!timeSet) { time = System.currentTimeMillis(); timeSet = true; } } else if (finished) { - title = Formatting.GREEN + I18n.translate("advancedbackups.backup_finished"); + textColour = ColourHelper.colour(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); + title = I18n.translate("advancedbackups.backup_finished"); + if (!timeSet) { + time = System.currentTimeMillis(); + timeSet = true; + } + } + else if (cancelled) { + textColour = ColourHelper.colour(255, (int) ClientConfigManager.errorTextRed.get(), (int) ClientConfigManager.errorTextGreen.get(), (int) ClientConfigManager.errorTextBlue.get()); + title = I18n.translate("advancedbackups.backup_cancelled"); if (!timeSet) { time = System.currentTimeMillis(); timeSet = true; } } - manager.getClient().textRenderer.draw(matrix, title, 25, 11, -11534256); + manager.getClient().textRenderer.draw(matrix, title, 25, 11, textColour); if (timeSet && System.currentTimeMillis() >= time + 5000) { starting = false; started = false; failed = false; finished = false; + cancelled = false; progress = 0; max = 0; timeSet = false; @@ -88,7 +114,8 @@ else if (finished) { return Visibility.HIDE; } - DrawableHelper.fill(matrix, 3, 28, Math.max(3, (int) f), 29, -10948014); + DrawableHelper.fill(matrix, 4, 28, Math.max(4, (int) f), 29, ColourHelper.colour + (255, (int) ClientConfigManager.progressBarRed.get(), (int) ClientConfigManager.progressBarGreen.get(), (int) ClientConfigManager.progressBarBlue.get())); return Visibility.SHOW; } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java index 4b125b1a..d2072cdd 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java @@ -15,9 +15,10 @@ public class ClientContactor implements IClientContactor { public void backupComplete() { MinecraftServer server = AdvancedBackups.server; List players = server.getPlayerManager().getPlayerList(); - PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, 0, 0); + PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, false, 0, 0); for (ServerPlayerEntity player : players) { - if (!AdvancedBackups.server.isDedicated() || player.hasPermissionLevel(3)) { + if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; + if (!server.isDedicated() || player.hasPermissionLevel(3)) { NetworkHandler.sendToClient(player, packet); } } @@ -27,9 +28,10 @@ public void backupComplete() { public void backupFailed() { MinecraftServer server = AdvancedBackups.server; List players = server.getPlayerManager().getPlayerList(); - PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, 0, 0); + PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, false, 0, 0); for (ServerPlayerEntity player : players) { - if (!AdvancedBackups.server.isDedicated() || player.hasPermissionLevel(3)) { + if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; + if (!server.isDedicated() || player.hasPermissionLevel(3)) { NetworkHandler.sendToClient(player, packet); } } @@ -39,9 +41,10 @@ public void backupFailed() { public void backupProgress(int progress, int max) { MinecraftServer server = AdvancedBackups.server; List players = server.getPlayerManager().getPlayerList(); - PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, progress, max); + PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, false, progress, max); for (ServerPlayerEntity player : players) { - if (!AdvancedBackups.server.isDedicated() || player.hasPermissionLevel(3)) { + if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; + if (!server.isDedicated() || player.hasPermissionLevel(3)) { NetworkHandler.sendToClient(player, packet); } } @@ -51,9 +54,23 @@ public void backupProgress(int progress, int max) { public void backupStarting() { MinecraftServer server = AdvancedBackups.server; List players = server.getPlayerManager().getPlayerList(); - PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, 0, 0); + PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, false, 0, 0); for (ServerPlayerEntity player : players) { - if (!AdvancedBackups.server.isDedicated() || player.hasPermissionLevel(3)) { + if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; + if (!server.isDedicated() || player.hasPermissionLevel(3)) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupCancelled() { + MinecraftServer server = AdvancedBackups.server; + List players = server.getPlayerManager().getPlayerList(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, false, false, true, 0, 0); + for (ServerPlayerEntity player : players) { + if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; + if (!server.isDedicated() || player.hasPermissionLevel(3)) { NetworkHandler.sendToClient(player, packet); } } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java index 3560bdf8..53c1afd7 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java @@ -1,19 +1,47 @@ package co.uk.mommyheather.advancedbackups.client; +import co.uk.mommyheather.advancedbackups.AdvancedBackups; +import co.uk.mommyheather.advancedbackups.core.ABCore; +import co.uk.mommyheather.advancedbackups.core.config.ClientConfigManager; import co.uk.mommyheather.advancedbackups.network.NetworkHandler; import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; +import co.uk.mommyheather.advancedbackups.network.PacketToastSubscribe; import net.fabricmc.api.ClientModInitializer; +import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents; +import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; +import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; import net.fabricmc.fabric.api.networking.v1.PacketSender; import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.ClientPlayNetworkHandler; import net.minecraft.network.PacketByteBuf; public class ClientWrapper implements ClientModInitializer { - + @Override public void onInitializeClient() { + + ABCore.infoLogger = AdvancedBackups.infoLogger; + ABCore.warningLogger = AdvancedBackups.warningLogger; + ABCore.errorLogger = AdvancedBackups.errorLogger; + ClientPlayNetworking.registerGlobalReceiver(NetworkHandler.STATUS_PACKET_ID, ClientWrapper::handle); + ClientLifecycleEvents.CLIENT_STARTED.register((client) -> { + ClientConfigManager.loadOrCreateConfig(); + }); + + ClientPlayConnectionEvents.JOIN.register((handler, sender, client) -> { + PacketToastSubscribe packet = new PacketToastSubscribe(ClientConfigManager.showProgress.get()); + sender.sendPacket(NetworkHandler.TOAST_SUBSCRIBE_ID, packet.write(PacketByteBufs.create())); + }); + + ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> { + AdvancedBackupsClientCommand.register(dispatcher); + + }); + + } @@ -28,6 +56,7 @@ public static void handle(MinecraftClient client, ClientPlayNetworkHandler handl BackupToast.started = message.started; BackupToast.failed = message.failed; BackupToast.finished = message.finished; + BackupToast.cancelled = message.cancelled; BackupToast.progress = message.progress; BackupToast.max = message.max; diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ColourHelper.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ColourHelper.java new file mode 100644 index 00000000..46a47b01 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ColourHelper.java @@ -0,0 +1,31 @@ +package co.uk.mommyheather.advancedbackups.client; + +//A colour helper, loosely based on that of vanilla 1.16. +//What is the modern equivalent..? +public class ColourHelper { + + public static int alpha(int in) { + return in >>> 24; + } + + public static int red(int in) { + return in >> 16 & 255; + } + + public static int green(int in) { + return in >> 8 & 255; + } + + public static int blue(int in) { + return in & 255; + } + + public static int colour(int a, int r, int g, int b) { + return a << 24 | r << 16 | g << 8 | b; + } + + public static int colour(int a, long r, long g, long b) { + return colour(a, (int) r, (int) g, (int) b); + } + +} \ No newline at end of file diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java index 72185c57..3aa3c276 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java @@ -8,6 +8,7 @@ public class NetworkHandler { public static Identifier STATUS_PACKET_ID = new Identifier("advancedbackups", "backup_status"); + public static final Identifier TOAST_SUBSCRIBE_ID = new Identifier("advancedbackups", "toast_subscribe"); public static void sendToClient(ServerPlayerEntity player, PacketBackupStatus packet) { diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java index b4d76afb..747ccc1b 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java @@ -1,9 +1,5 @@ package co.uk.mommyheather.advancedbackups.network; -import co.uk.mommyheather.advancedbackups.client.BackupToast; -import net.fabricmc.fabric.api.networking.v1.PacketSender; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.network.ClientPlayNetworkHandler; import net.minecraft.network.PacketByteBuf; public class PacketBackupStatus { @@ -12,17 +8,19 @@ public class PacketBackupStatus { public boolean started; public boolean failed; public boolean finished; + public boolean cancelled; public int progress; public int max; - public PacketBackupStatus(boolean starting, boolean started, boolean failed, boolean finished, int progress, + public PacketBackupStatus(boolean starting, boolean started, boolean failed, boolean finished, boolean cancelled, int progress, int max) { this.starting = starting; this.started = started; this.failed = failed; this.finished = finished; + this.cancelled = cancelled; this.progress = progress; this.max = max; } @@ -36,6 +34,7 @@ public void read(PacketByteBuf buf) { started = buf.readBoolean(); failed = buf.readBoolean(); finished = buf.readBoolean(); + cancelled = buf.readBoolean(); progress = buf.readInt(); max = buf.readInt(); @@ -46,6 +45,7 @@ public PacketByteBuf write(PacketByteBuf buf) { buf.writeBoolean(started); buf.writeBoolean(failed); buf.writeBoolean(finished); + buf.writeBoolean(cancelled); buf.writeInt(progress); buf.writeInt(max); diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java new file mode 100644 index 00000000..28c99f76 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java @@ -0,0 +1,59 @@ +package co.uk.mommyheather.advancedbackups.network; + +import co.uk.mommyheather.advancedbackups.AdvancedBackups; +import net.fabricmc.fabric.api.networking.v1.PacketSender; +import net.minecraft.network.PacketByteBuf; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.network.ServerPlayNetworkHandler; +import net.minecraft.server.network.ServerPlayerEntity; + +public class PacketToastSubscribe { + + public boolean enable; + + + public PacketToastSubscribe(boolean enable) { + this.enable = enable; + } + + public PacketToastSubscribe() { + + } + + public void read(PacketByteBuf buf) { + enable = buf.readBoolean(); + } + + public PacketByteBuf write(PacketByteBuf buf) { + buf.writeBoolean(enable); + + return buf; + + } + + + public static void handle(MinecraftServer server, ServerPlayerEntity player, ServerPlayNetworkHandler handler, PacketByteBuf buf, PacketSender responseSender) { + + PacketToastSubscribe message = new PacketToastSubscribe(); + message.read(buf); + + + server.execute(() -> { + if (message.enable && !AdvancedBackups.players.contains(player.getUuidAsString())) { + AdvancedBackups.players.add(player.getUuidAsString()); + } + else if (!message.enable) { + AdvancedBackups.players.remove(player.getUuidAsString()); + } + + }); + + + + + + } + + + +} \ No newline at end of file diff --git a/src/main/resources/assets/advancedbackups/lang/en_us.json b/src/main/resources/assets/advancedbackups/lang/en_us.json index cc68dae1..66caf08d 100644 --- a/src/main/resources/assets/advancedbackups/lang/en_us.json +++ b/src/main/resources/assets/advancedbackups/lang/en_us.json @@ -2,5 +2,6 @@ "advancedbackups.backup_starting" : "Backup starting!", "advancedbackups.progress": "Backup ongoing: %1$s%%", "advancedbackups.backup_failed": "Backup failed!\nCheck log for more info.", + "advancedbackups.backup_cancelled": "Backup cancelled!", "advancedbackups.backup_finished": "Backup complete!" } \ No newline at end of file From 5e5cca66e18e239ed18525a7f7952a0ef9d81381 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Thu, 22 Feb 2024 21:54:34 +0000 Subject: [PATCH 448/580] I'm no fan of an accesstransformer, but this looks to be the best way to have a client and server command with the same name. --- build.gradle | 1 + src/main/resources/META-INF/accesstransformer.cfg | 1 + 2 files changed, 2 insertions(+) create mode 100644 src/main/resources/META-INF/accesstransformer.cfg diff --git a/build.gradle b/build.gradle index ab32b114..a03159a2 100644 --- a/build.gradle +++ b/build.gradle @@ -30,6 +30,7 @@ minecraft { mappings channel: 'official', version: '1.19.4' // accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg') // Currently, this location cannot be changed from the default. + accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg') // Default run configurations. // These can be tweaked, removed, or duplicated as needed. diff --git a/src/main/resources/META-INF/accesstransformer.cfg b/src/main/resources/META-INF/accesstransformer.cfg new file mode 100644 index 00000000..e456e70b --- /dev/null +++ b/src/main/resources/META-INF/accesstransformer.cfg @@ -0,0 +1 @@ +public net.minecraft.client.multiplayer.ClientPacketListener f_244346_ # lastSeenMessages \ No newline at end of file From f9eae2c7728317fc0b2b330c7c0c3623d479a0f8 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Thu, 22 Feb 2024 21:54:51 +0000 Subject: [PATCH 449/580] Aforementioned commands. --- .../AdvancedBackupsCommand.java | 12 +++ .../client/AdvancedBackupsClientCommand.java | 73 +++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index e611ccc0..dcac6da8 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -39,6 +39,18 @@ public static void register(CommandDispatcher stack) { }); return 1; })) + + .then(Commands.literal("cancel").executes((runner) -> { + CoreCommandSystem.cancelBackup((response) -> { + runner.getSource().sendSuccess(Component.literal(response), true); + }); + return 1; + })) + + .then(Commands.literal("reload-client-config").executes((runner) -> { + runner.getSource().sendSuccess(Component.literal("This command can only be ran on the client!"), true); + return 1; + })) ); } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java new file mode 100644 index 00000000..b1e6038c --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java @@ -0,0 +1,73 @@ +package co.uk.mommyheather.advancedbackups.client; + +import java.time.Instant; + +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; + +import co.uk.mommyheather.advancedbackups.core.CoreCommandSystem; +import net.minecraft.client.Minecraft; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.commands.arguments.ArgumentSignatures; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.LastSeenMessages.Update; +import net.minecraft.network.protocol.game.ServerboundChatCommandPacket; +import net.minecraftforge.client.ClientCommandSourceStack; +import net.minecraftforge.server.ServerLifecycleHooks; + +public class AdvancedBackupsClientCommand { + public static void register(CommandDispatcher commandDispatcher) { + commandDispatcher.register(literal("backup").requires((runner) -> { + return !ServerLifecycleHooks.getCurrentServer().isDedicatedServer() || runner.hasPermission(3); + }).then(literal("start").executes((runner) -> { + Update acknowledgment = Minecraft.getInstance().player.connection.lastSeenMessages.generateAndApplyUpdate().update(); + Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup start", Instant.now(), 0, + ArgumentSignatures.EMPTY, acknowledgment)); + return 1; + })) + + .then(literal("reload-config").executes((runner) -> { + Update acknowledgment = Minecraft.getInstance().player.connection.lastSeenMessages.generateAndApplyUpdate().update(); + Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup reload-config", Instant.now(), 0, + ArgumentSignatures.EMPTY, acknowledgment)); + return 1; + })) + + .then(literal("reset-chain").executes((runner) -> { + Update acknowledgment = Minecraft.getInstance().player.connection.lastSeenMessages.generateAndApplyUpdate().update(); + Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup reset-chain", Instant.now(), 0, + ArgumentSignatures.EMPTY, acknowledgment)); + return 1; + })) + + .then(literal("snapshot").executes((runner) -> { + Update acknowledgment = Minecraft.getInstance().player.connection.lastSeenMessages.generateAndApplyUpdate().update(); + Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup snapshot", Instant.now(), 0, + ArgumentSignatures.EMPTY, acknowledgment)); + return 1; + })) + + .then(literal("cancel").executes((runner) -> { + Update acknowledgment = Minecraft.getInstance().player.connection.lastSeenMessages.generateAndApplyUpdate().update(); + Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup cancel", Instant.now(), 0, + ArgumentSignatures.EMPTY, acknowledgment)); + return 1; + })) + + .then(literal("reload-client-config").executes((runner) -> { + CoreCommandSystem.reloadClientConfig((response) -> { + runner.getSource().sendSuccess(Component.literal(response), true); + }); + return 1; + })) + + ); + } + + //I'm no fan of having this here but it seems required + public static LiteralArgumentBuilder literal(String literal) { + return LiteralArgumentBuilder.literal(literal); + } + + +} From ce37f987e3f6a5c57bbf279cfad3ce3041190709 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Thu, 22 Feb 2024 21:55:02 +0000 Subject: [PATCH 450/580] Packet changes. --- .../network/PacketBackupStatus.java | 7 +++- .../network/PacketToastSubscribe.java | 41 +++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java index 2de6fbac..add520b0 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java @@ -15,17 +15,20 @@ public class PacketBackupStatus { public boolean failed; public boolean finished; + public boolean cancelled; + public int progress; public int max; - public PacketBackupStatus(boolean starting, boolean started, boolean failed, boolean finished, int progress, + public PacketBackupStatus(boolean starting, boolean started, boolean failed, boolean finished, boolean cancelled, int progress, int max) { this.starting = starting; this.started = started; this.failed = failed; this.finished = finished; this.progress = progress; + this.cancelled = cancelled; this.max = max; } @@ -35,6 +38,7 @@ public PacketBackupStatus(FriendlyByteBuf buf) { started = buf.readBoolean(); failed = buf.readBoolean(); finished = buf.readBoolean(); + cancelled = buf.readBoolean(); progress = buf.readInt(); max = buf.readInt(); @@ -45,6 +49,7 @@ public void toBytes(FriendlyByteBuf buf) { buf.writeBoolean(started); buf.writeBoolean(failed); buf.writeBoolean(finished); + buf.writeBoolean(cancelled); buf.writeInt(progress); buf.writeInt(max); diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java new file mode 100644 index 00000000..49bbcf02 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java @@ -0,0 +1,41 @@ +package co.uk.mommyheather.advancedbackups.network; + +import java.util.function.Supplier; + +import co.uk.mommyheather.advancedbackups.AdvancedBackups; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraftforge.network.NetworkEvent; + +public class PacketToastSubscribe { + + private boolean enable; + + public PacketToastSubscribe(boolean enable) { + this.enable = enable; + } + + + public PacketToastSubscribe(FriendlyByteBuf buf) { + enable = buf.readBoolean(); + } + + public void toBytes(FriendlyByteBuf buf) { + buf.writeBoolean(enable); + } + + public boolean handle(Supplier ctx) { + ctx.get().enqueueWork(() -> { + if (ctx.get().getSender() == null) return; + if (enable && !AdvancedBackups.players.contains(ctx.get().getSender().getStringUUID())) { + AdvancedBackups.players.add(ctx.get().getSender().getStringUUID()); + } + else if (!enable) { + AdvancedBackups.players.remove(ctx.get().getSender().getStringUUID()); + } + }); + + return true; + + } + +} From a2c6393874e6d02823e4bcbe20b969b8716cccff Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Thu, 22 Feb 2024 21:58:17 +0000 Subject: [PATCH 451/580] new client events and storage of players to send toasts to --- .../advancedbackups/AdvancedBackups.java | 18 +++++++++++---- .../advancedbackups/client/ClientWrapper.java | 22 +++++++++++++++++++ 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 0d1d2d9e..ffd65cc8 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -1,5 +1,6 @@ package co.uk.mommyheather.advancedbackups; +import java.util.ArrayList; import java.util.List; import java.util.function.Consumer; @@ -8,6 +9,7 @@ import com.mojang.logging.LogUtils; import co.uk.mommyheather.advancedbackups.client.ClientContactor; +import co.uk.mommyheather.advancedbackups.client.ClientWrapper; import co.uk.mommyheather.advancedbackups.core.ABCore; import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; @@ -28,6 +30,8 @@ import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.ModList; import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; +import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; import net.minecraftforge.server.ServerLifecycleHooks; @Mod("advancedbackups") @@ -40,12 +44,22 @@ public class AdvancedBackups public static final Consumer warningLogger = LOGGER::warn; public static final Consumer errorLogger = LOGGER::error; + public static final ArrayList players = new ArrayList<>(); public AdvancedBackups() { // Register ourselves for server and other game events we are interested in MinecraftForge.EVENT_BUS.register(this); + FMLJavaModLoadingContext.get().getModEventBus().addListener(this::clientSetup); NetworkHandler.register(); + ABCore.infoLogger = infoLogger; + ABCore.warningLogger = warningLogger; + ABCore.errorLogger = errorLogger; + + } + + public void clientSetup(FMLClientSetupEvent e) { + ClientWrapper.init(e); } @SubscribeEvent @@ -65,10 +79,6 @@ public void onServerStarting(ServerStartingEvent event) ABCore.enableSaving = AdvancedBackups::enableSaving; ABCore.saveOnce = AdvancedBackups::saveOnce; - ABCore.infoLogger = infoLogger; - ABCore.warningLogger = warningLogger; - ABCore.errorLogger = errorLogger; - ABCore.resetActivity = AdvancedBackups::resetActivity; ABCore.clientContactor = new ClientContactor(); diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java index 59709b69..8ed0cb03 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java @@ -1,7 +1,14 @@ package co.uk.mommyheather.advancedbackups.client; +import co.uk.mommyheather.advancedbackups.core.config.ClientConfigManager; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; +import co.uk.mommyheather.advancedbackups.network.PacketToastSubscribe; import net.minecraft.client.Minecraft; +import net.minecraftforge.client.event.ClientPlayerNetworkEvent; +import net.minecraftforge.client.event.RegisterClientCommandsEvent; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; public class ClientWrapper { @@ -10,6 +17,7 @@ public static void handle(PacketBackupStatus packet) { BackupToast.started = packet.started; BackupToast.failed = packet.failed; BackupToast.finished = packet.finished; + BackupToast.cancelled = packet.cancelled; BackupToast.progress = packet.progress; BackupToast.max = packet.max; @@ -19,5 +27,19 @@ public static void handle(PacketBackupStatus packet) { Minecraft.getInstance().getToasts().addToast(new BackupToast()); } } + + public static void init(FMLClientSetupEvent e) { + MinecraftForge.EVENT_BUS.addListener(ClientWrapper::registerClientCommands); + MinecraftForge.EVENT_BUS.addListener(ClientWrapper::onServerConnected); + ClientConfigManager.loadOrCreateConfig(); + } + + public static void registerClientCommands(RegisterClientCommandsEvent event) { + AdvancedBackupsClientCommand.register(event.getDispatcher()); + } + + public static void onServerConnected(ClientPlayerNetworkEvent.LoggingIn event) { + NetworkHandler.sendToServer(new PacketToastSubscribe(ClientConfigManager.showProgress.get())); + } } From 1d958b30ac10abffc393889bf571574c464b64d0 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Thu, 22 Feb 2024 22:03:46 +0000 Subject: [PATCH 452/580] register new packet --- .../advancedbackups/network/NetworkHandler.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java index 69a388a4..3d87e79a 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java @@ -28,10 +28,20 @@ public static void register() { .decoder(buf -> new PacketBackupStatus(buf)) .consumer(PacketBackupStatus::handle) .add(); + + INSTANCE.messageBuilder(PacketToastSubscribe.class, id()) + .encoder(PacketToastSubscribe::toBytes) + .decoder(buf -> new PacketToastSubscribe(buf)) + .consumer(PacketToastSubscribe::handle) + .add(); } public static void sendToClient(ServerPlayer player, Object packet) { INSTANCE.sendTo(packet, player.connection.connection, NetworkDirection.PLAY_TO_CLIENT); } + public static void sendToServer(Object packet) { + INSTANCE.sendToServer(packet); + } + } From e52a3ae825086c220b353a973df8d1692f746be7 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Thu, 22 Feb 2024 22:03:53 +0000 Subject: [PATCH 453/580] colour helper --- .../advancedbackups/client/ColourHelper.java | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/client/ColourHelper.java diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ColourHelper.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ColourHelper.java new file mode 100644 index 00000000..dd559425 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ColourHelper.java @@ -0,0 +1,31 @@ +package co.uk.mommyheather.advancedbackups.client; + +//A colour helper, loosely based on that of vanilla 1.16. +//Where is it in modern? +public class ColourHelper { + + public static int alpha(int in) { + return in >>> 24; + } + + public static int red(int in) { + return in >> 16 & 255; + } + + public static int green(int in) { + return in >> 8 & 255; + } + + public static int blue(int in) { + return in & 255; + } + + public static int colour(int a, int r, int g, int b) { + return a << 24 | r << 16 | g << 8 | b; + } + + public static int colour(int a, long r, long g, long b) { + return colour(a, (int) r, (int) g, (int) b); + } + +} \ No newline at end of file From 24235b26f2e18645434a99dff8cae706fc3fb9ff Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Thu, 22 Feb 2024 22:06:47 +0000 Subject: [PATCH 454/580] contactor support for cancelled backups --- .../client/ClientContactor.java | 26 ++++++++++++++++--- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java index 2c72a8c7..3c25b3e7 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java @@ -2,6 +2,7 @@ import java.util.List; +import co.uk.mommyheather.advancedbackups.AdvancedBackups; import co.uk.mommyheather.advancedbackups.interfaces.IClientContactor; import co.uk.mommyheather.advancedbackups.network.NetworkHandler; import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; @@ -15,8 +16,9 @@ public class ClientContactor implements IClientContactor { public void backupComplete() { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); List players = server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, 0, 0); + PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, false, 0, 0); for (ServerPlayer player : players) { + if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; if (!server.isDedicatedServer() || player.hasPermissions(3)) { NetworkHandler.sendToClient(player, packet); } @@ -27,8 +29,9 @@ public void backupComplete() { public void backupFailed() { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); List players = server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, 0, 0); + PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, false, 0, 0); for (ServerPlayer player : players) { + if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; if (!server.isDedicatedServer() || player.hasPermissions(3)) { NetworkHandler.sendToClient(player, packet); } @@ -39,8 +42,9 @@ public void backupFailed() { public void backupProgress(int progress, int max) { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); List players = server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, progress, max); + PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, false, progress, max); for (ServerPlayer player : players) { + if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; if (!server.isDedicatedServer() || player.hasPermissions(3)) { NetworkHandler.sendToClient(player, packet); } @@ -51,8 +55,22 @@ public void backupProgress(int progress, int max) { public void backupStarting() { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); List players = server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, 0, 0); + PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, false, 0, 0); for (ServerPlayer player : players) { + if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; + if (!server.isDedicatedServer() || player.hasPermissions(3)) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupCancelled() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, false, false, true, 0, 0); + for (ServerPlayer player : players) { + if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; if (!server.isDedicatedServer() || player.hasPermissions(3)) { NetworkHandler.sendToClient(player, packet); } From 9c83b47cf432fe495c1059eac39bb96cd7ca9228 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Thu, 22 Feb 2024 22:07:03 +0000 Subject: [PATCH 455/580] toast supports client config now --- .../advancedbackups/client/BackupToast.java | 56 ++++++++++++++----- 1 file changed, 41 insertions(+), 15 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java index 53125427..d1c81bb3 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java @@ -3,6 +3,7 @@ import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; +import co.uk.mommyheather.advancedbackups.core.config.ClientConfigManager; import net.minecraft.ChatFormatting; import net.minecraft.client.gui.Gui; import net.minecraft.client.gui.components.toasts.Toast; @@ -18,6 +19,7 @@ public class BackupToast implements Toast { public static boolean started; public static boolean failed; public static boolean finished; + public static boolean cancelled; public static int progress; public static int max; @@ -29,55 +31,78 @@ public class BackupToast implements Toast { public static final ItemStack stack = new ItemStack(Items.PAPER); + private int textColour; + private String title = "You shouldn't see this!"; + @Override public Visibility render(PoseStack matrix, ToastComponent toastGui, long delta) { RenderSystem.setShader(GameRenderer::getPositionTexShader); RenderSystem.setShaderTexture(0, TEXTURE); RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); - ToastComponent.blit(matrix, 0, 0, 0, 0, this.width(), this.height()); + toastGui.blit(matrix, 0, 0, 0, ClientConfigManager.darkMode.get() ? 0 : this.height(), this.width(), this.height()); toastGui.getMinecraft().getItemRenderer().renderAndDecorateFakeItem(matrix, stack, 8, 8); - float percent = finished ? 100 : (float) progress / (float) max; - Gui.fill(matrix, 3, 28, 156, 29, -1); + Gui.fill(matrix, 4, 28, 156, 29, ColourHelper.colour + (255, (int) ClientConfigManager.progressBackgroundRed.get(), (int) ClientConfigManager.progressBackgroundGreen.get(), (int) ClientConfigManager.progressBackgroundBlue.get())); + float f = Math.min(156, ( 156 * percent )); - - if (!exists) { - toastGui.getMinecraft().font.draw(matrix, ChatFormatting.GREEN + I18n.get("advancedbackups.backup_finished"), 25, 11, -11534256); - Gui.fill(matrix, 3, 28, 156, 29, -10948014); + if (!exists) { + if (title.equals(I18n.get("advancedbackups.backup_finished"))){ + textColour = ColourHelper.colour(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); + toastGui.getMinecraft().font.draw(matrix, I18n.get(title), 25, 11, textColour); + Gui.fill(matrix, 3, 28, 156, 29, ColourHelper.colour + (255, (int) ClientConfigManager.progressBarRed.get(), (int) ClientConfigManager.progressBarGreen.get(), (int) ClientConfigManager.progressBarBlue.get())); + } + else { + textColour = ColourHelper.colour(255, (int) ClientConfigManager.errorTextRed.get(), (int) ClientConfigManager.errorTextGreen.get(), (int) ClientConfigManager.errorTextBlue.get()); + toastGui.getMinecraft().font.draw(matrix, I18n.get(title), 25, 11, textColour); + } return Visibility.HIDE; } - String title = "You shouldn't see this!"; + title = "You shouldn't see this!"; if (starting) { - title = ChatFormatting.GREEN + I18n.get("advancedbackups.backup_starting"); + textColour = ColourHelper.colour(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); + title = I18n.get("advancedbackups.backup_starting"); } else if (started) { - title = ChatFormatting.GREEN + I18n.get("advancedbackups.progress", round(percent * 100)); + textColour = ColourHelper.colour(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); + title = I18n.get("advancedbackups.progress", round(percent * 100)); } else if (failed) { - title = ChatFormatting.RED + I18n.get("advancedbackups.backup_failed"); + textColour = ColourHelper.colour(255, (int) ClientConfigManager.errorTextRed.get(), (int) ClientConfigManager.errorTextGreen.get(), (int) ClientConfigManager.errorTextBlue.get()); + title = I18n.get("advancedbackups.backup_failed"); if (!timeSet) { time = System.currentTimeMillis(); timeSet = true; } } else if (finished) { - title = ChatFormatting.GREEN + I18n.get("advancedbackups.backup_finished"); + textColour = ColourHelper.colour(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); + title = I18n.get("advancedbackups.backup_finished"); + if (!timeSet) { + time = System.currentTimeMillis(); + timeSet = true; + } + } + else if (cancelled) { + textColour = ColourHelper.colour(255, (int) ClientConfigManager.errorTextRed.get(), (int) ClientConfigManager.errorTextGreen.get(), (int) ClientConfigManager.errorTextBlue.get()); + title = I18n.get("advancedbackups.backup_cancelled"); if (!timeSet) { time = System.currentTimeMillis(); timeSet = true; } } - toastGui.getMinecraft().font.draw(matrix, title, 25, 11, -11534256); + toastGui.getMinecraft().font.draw(matrix, title, 25, 11, textColour); if (timeSet && System.currentTimeMillis() >= time + 5000) { starting = false; @@ -90,8 +115,9 @@ else if (finished) { exists = false; return Visibility.HIDE; } - - Gui.fill(matrix, 3, 28, Math.max(3, (int) f), 29, -10948014); + + Gui.fill(matrix, 4, 28, Math.max(4, (int) f), 29, ColourHelper.colour + (255, (int) ClientConfigManager.progressBarRed.get(), (int) ClientConfigManager.progressBarGreen.get(), (int) ClientConfigManager.progressBarBlue.get())); return Visibility.SHOW; From ba77132ad30134e73cce3974f7d826dab1bad281 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Mon, 26 Feb 2024 15:51:53 +0000 Subject: [PATCH 456/580] toast supports client config --- .../advancedbackups/AdvancedBackups.java | 3 ++ .../AdvancedBackupsCommand.java | 9 ++++ .../advancedbackups/client/BackupToast.java | 53 ++++++++++++++----- .../client/ClientContactor.java | 26 +++++++-- .../advancedbackups/client/ClientWrapper.java | 13 ++++- .../advancedbackups/client/ColourHelper.java | 31 +++++++++++ .../network/PacketBackupStatus.java | 13 ++--- 7 files changed, 121 insertions(+), 27 deletions(-) create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/client/ColourHelper.java diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 9ee90eda..7a3c64e0 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -1,5 +1,6 @@ package co.uk.mommyheather.advancedbackups; +import java.util.ArrayList; import java.util.List; import java.util.function.Consumer; @@ -39,6 +40,8 @@ public class AdvancedBackups public static final Consumer warningLogger = LOGGER::warn; public static final Consumer errorLogger = LOGGER::error; + public static final ArrayList players = new ArrayList<>(); + public AdvancedBackups() { diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index 5fa3344e..e34d4a7b 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -47,6 +47,15 @@ public static void register(CommandDispatcher stack) { }); return 1; })) + + .then(Commands.literal("cancel").executes((runner) -> { + CoreCommandSystem.cancelBackup((response) -> { + runner.getSource().sendSuccess(() -> { + return Component.literal(response) ; + }, true); + }); + return 1; + })) ); } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java index c08baf68..80adedc8 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java @@ -3,6 +3,7 @@ import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; +import co.uk.mommyheather.advancedbackups.core.config.ClientConfigManager; import net.minecraft.ChatFormatting; import net.minecraft.client.gui.Gui; import net.minecraft.client.gui.GuiGraphics; @@ -19,6 +20,7 @@ public class BackupToast implements Toast { public static boolean started; public static boolean failed; public static boolean finished; + public static boolean cancelled; public static int progress; public static int max; @@ -29,53 +31,75 @@ public class BackupToast implements Toast { private static boolean timeSet = false; public static final ItemStack stack = new ItemStack(Items.PAPER); + + private int textColour; + private String title = "You shouldn't see this!"; @Override public Visibility render(GuiGraphics graphics, ToastComponent toastGui, long delta) { - graphics.blit(TEXTURE, 0, 0, 0, 0, this.width(), this.height()); + graphics.blit(TEXTURE, 0, 0, 0, ClientConfigManager.darkMode.get() ? 0 : this.height(), this.width(), this.height()); graphics.renderFakeItem(stack, 8, 8); float percent = finished ? 100 : (float) progress / (float) max; - graphics.fill(3, 28, 156, 29, -1); + graphics.fill(4, 28, 156, 29, ColourHelper.colour + (255, (int) ClientConfigManager.progressBackgroundRed.get(), (int) ClientConfigManager.progressBackgroundGreen.get(), (int) ClientConfigManager.progressBackgroundBlue.get())); + float f = Math.min(156, ( 156 * percent )); - - if (!exists) { - graphics.drawString(toastGui.getMinecraft().font, ChatFormatting.GREEN + I18n.get("advancedbackups.backup_finished"), 25, 11, -11534256); - graphics.fill(3, 28, 156, 29, -10948014); + if (!exists) { + if (title.equals(I18n.get("advancedbackups.backup_finished"))){ + textColour = ColourHelper.colour(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); + graphics.drawString(toastGui.getMinecraft().font, I18n.get(title), 25, 11, textColour); + graphics.fill(3, 28, 156, 29, ColourHelper.colour + (255, (int) ClientConfigManager.progressBarRed.get(), (int) ClientConfigManager.progressBarGreen.get(), (int) ClientConfigManager.progressBarBlue.get())); + } + else { + textColour = ColourHelper.colour(255, (int) ClientConfigManager.errorTextRed.get(), (int) ClientConfigManager.errorTextGreen.get(), (int) ClientConfigManager.errorTextBlue.get()); + graphics.drawString(toastGui.getMinecraft().font, I18n.get(title), 25, 11, textColour); + } return Visibility.HIDE; } - String title = "You shouldn't see this!"; - if (starting) { - title = ChatFormatting.GREEN + I18n.get("advancedbackups.backup_starting"); + textColour = ColourHelper.colour(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); + title = I18n.get("advancedbackups.backup_starting"); } else if (started) { - title = ChatFormatting.GREEN + I18n.get("advancedbackups.progress", round(percent * 100)); + textColour = ColourHelper.colour(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); + title = I18n.get("advancedbackups.progress", round(percent * 100)); } else if (failed) { - title = ChatFormatting.RED + I18n.get("advancedbackups.backup_failed"); + textColour = ColourHelper.colour(255, (int) ClientConfigManager.errorTextRed.get(), (int) ClientConfigManager.errorTextGreen.get(), (int) ClientConfigManager.errorTextBlue.get()); + title = I18n.get("advancedbackups.backup_failed"); if (!timeSet) { time = System.currentTimeMillis(); timeSet = true; } } else if (finished) { - title = ChatFormatting.GREEN + I18n.get("advancedbackups.backup_finished"); + textColour = ColourHelper.colour(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); + title = I18n.get("advancedbackups.backup_finished"); + if (!timeSet) { + time = System.currentTimeMillis(); + timeSet = true; + } + } + else if (cancelled) { + textColour = ColourHelper.colour(255, (int) ClientConfigManager.errorTextRed.get(), (int) ClientConfigManager.errorTextGreen.get(), (int) ClientConfigManager.errorTextBlue.get()); + title = I18n.get("advancedbackups.backup_cancelled"); if (!timeSet) { time = System.currentTimeMillis(); timeSet = true; } } - graphics.drawString(toastGui.getMinecraft().font, title, 25, 11, -11534256); + graphics.drawString(toastGui.getMinecraft().font, title, 25, 11, textColour); if (timeSet && System.currentTimeMillis() >= time + 5000) { starting = false; @@ -89,7 +113,8 @@ else if (finished) { return Visibility.HIDE; } - graphics.fill(3, 28, Math.max(3, (int) f), 29, -10948014); + graphics.fill(4, 28, Math.max(4, (int) f), 29, ColourHelper.colour + (255, (int) ClientConfigManager.progressBarRed.get(), (int) ClientConfigManager.progressBarGreen.get(), (int) ClientConfigManager.progressBarBlue.get())); return Visibility.SHOW; diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java index 2c72a8c7..3c25b3e7 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java @@ -2,6 +2,7 @@ import java.util.List; +import co.uk.mommyheather.advancedbackups.AdvancedBackups; import co.uk.mommyheather.advancedbackups.interfaces.IClientContactor; import co.uk.mommyheather.advancedbackups.network.NetworkHandler; import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; @@ -15,8 +16,9 @@ public class ClientContactor implements IClientContactor { public void backupComplete() { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); List players = server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, 0, 0); + PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, false, 0, 0); for (ServerPlayer player : players) { + if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; if (!server.isDedicatedServer() || player.hasPermissions(3)) { NetworkHandler.sendToClient(player, packet); } @@ -27,8 +29,9 @@ public void backupComplete() { public void backupFailed() { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); List players = server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, 0, 0); + PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, false, 0, 0); for (ServerPlayer player : players) { + if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; if (!server.isDedicatedServer() || player.hasPermissions(3)) { NetworkHandler.sendToClient(player, packet); } @@ -39,8 +42,9 @@ public void backupFailed() { public void backupProgress(int progress, int max) { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); List players = server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, progress, max); + PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, false, progress, max); for (ServerPlayer player : players) { + if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; if (!server.isDedicatedServer() || player.hasPermissions(3)) { NetworkHandler.sendToClient(player, packet); } @@ -51,8 +55,22 @@ public void backupProgress(int progress, int max) { public void backupStarting() { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); List players = server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, 0, 0); + PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, false, 0, 0); for (ServerPlayer player : players) { + if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; + if (!server.isDedicatedServer() || player.hasPermissions(3)) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupCancelled() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, false, false, true, 0, 0); + for (ServerPlayer player : players) { + if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; if (!server.isDedicatedServer() || player.hasPermissions(3)) { NetworkHandler.sendToClient(player, packet); } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java index 8d0d63ee..f09cc00b 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java @@ -5,7 +5,18 @@ public class ClientWrapper { - public static void handle(PacketBackupStatus packetBackupStatus) { + public static void handle(PacketBackupStatus packet) { + + BackupToast.starting = packet.starting; + BackupToast.started = packet.started; + BackupToast.failed = packet.failed; + BackupToast.finished = packet.finished; + + BackupToast.cancelled = packet.cancelled; + + BackupToast.progress = packet.progress; + BackupToast.max = packet.max; + if (!BackupToast.exists) { BackupToast.exists = true; Minecraft.getInstance().getToasts().addToast(new BackupToast()); diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ColourHelper.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ColourHelper.java new file mode 100644 index 00000000..dd559425 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ColourHelper.java @@ -0,0 +1,31 @@ +package co.uk.mommyheather.advancedbackups.client; + +//A colour helper, loosely based on that of vanilla 1.16. +//Where is it in modern? +public class ColourHelper { + + public static int alpha(int in) { + return in >>> 24; + } + + public static int red(int in) { + return in >> 16 & 255; + } + + public static int green(int in) { + return in >> 8 & 255; + } + + public static int blue(int in) { + return in & 255; + } + + public static int colour(int a, int r, int g, int b) { + return a << 24 | r << 16 | g << 8 | b; + } + + public static int colour(int a, long r, long g, long b) { + return colour(a, (int) r, (int) g, (int) b); + } + +} \ No newline at end of file diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java index 78f1fe90..fcfe2e41 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java @@ -16,17 +16,19 @@ public class PacketBackupStatus { public boolean failed; public boolean finished; + public boolean cancelled; public int progress; public int max; - public PacketBackupStatus(boolean starting, boolean started, boolean failed, boolean finished, int progress, + public PacketBackupStatus(boolean starting, boolean started, boolean failed, boolean finished, boolean cancelled, int progress, int max) { this.starting = starting; this.started = started; this.failed = failed; this.finished = finished; + this.cancelled = cancelled; this.progress = progress; this.max = max; } @@ -37,6 +39,7 @@ public PacketBackupStatus(FriendlyByteBuf buf) { started = buf.readBoolean(); failed = buf.readBoolean(); finished = buf.readBoolean(); + cancelled = buf.readBoolean(); progress = buf.readInt(); max = buf.readInt(); @@ -47,19 +50,13 @@ public void toBytes(FriendlyByteBuf buf) { buf.writeBoolean(started); buf.writeBoolean(failed); buf.writeBoolean(finished); + buf.writeBoolean(cancelled); buf.writeInt(progress); buf.writeInt(max); } public boolean handle(Supplier ctx) { - BackupToast.starting = starting; - BackupToast.started = started; - BackupToast.failed = failed; - BackupToast.finished = finished; - - BackupToast.progress = progress; - BackupToast.max = max; ctx.get().enqueueWork(() -> { if (ctx.get().getDirection().getReceptionSide() == LogicalSide.CLIENT) { ClientWrapper.handle(this); From d158c8036e27ae1579744cc914c4e4f7616cef23 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Wed, 13 Mar 2024 18:57:03 +0000 Subject: [PATCH 457/580] Support client config reloading --- .../advancedbackups/AdvancedBackups.java | 342 +++++++++--------- .../AdvancedBackupsCommand.java | 135 +++---- .../client/AdvancedBackupsClientCommand.java | 73 ++++ .../advancedbackups/client/ClientWrapper.java | 72 ++-- 4 files changed, 365 insertions(+), 257 deletions(-) create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 7a3c64e0..8362c3a4 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -1,167 +1,175 @@ -package co.uk.mommyheather.advancedbackups; - -import java.util.ArrayList; -import java.util.List; -import java.util.function.Consumer; - -import org.slf4j.Logger; - -import com.mojang.logging.LogUtils; - -import co.uk.mommyheather.advancedbackups.client.ClientContactor; -import co.uk.mommyheather.advancedbackups.core.ABCore; -import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; -import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; -import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; -import co.uk.mommyheather.advancedbackups.network.NetworkHandler; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.level.storage.LevelResource; -import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.event.RegisterCommandsEvent; -import net.minecraftforge.event.TickEvent; -import net.minecraftforge.event.entity.player.PlayerEvent; -import net.minecraftforge.event.server.ServerStartedEvent; -import net.minecraftforge.event.server.ServerStartingEvent; -import net.minecraftforge.event.server.ServerStoppingEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.ModList; -import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.server.ServerLifecycleHooks; - -@Mod("advancedbackups") -public class AdvancedBackups -{ - - private static final Logger LOGGER = LogUtils.getLogger(); - - public static final Consumer infoLogger = LOGGER::info; - public static final Consumer warningLogger = LOGGER::warn; - public static final Consumer errorLogger = LOGGER::error; - - public static final ArrayList players = new ArrayList<>(); - - - public AdvancedBackups() - { - // Register ourselves for server and other game events we are interested in - MinecraftForge.EVENT_BUS.register(this); - NetworkHandler.register(); - } - - @SubscribeEvent - public void onServerStarting(ServerStartingEvent event) - { - // Do something when the server starts - ABCore.worldName = event.getServer().getWorldData().getLevelName(); - ABCore.worldDir = event.getServer().getWorldPath(LevelResource.ROOT); - - ABCore.disableSaving = AdvancedBackups::disableSaving; - ABCore.enableSaving = AdvancedBackups::enableSaving; - ABCore.saveOnce = AdvancedBackups::saveOnce; - - ABCore.infoLogger = infoLogger; - ABCore.warningLogger = warningLogger; - ABCore.errorLogger = errorLogger; - - ABCore.resetActivity = AdvancedBackups::resetActivity; - - ABCore.clientContactor = new ClientContactor(); - ABCore.modJar = ModList.get().getModFileById("advancedbackups").getFile().getFilePath().toFile(); - - - ConfigManager.loadOrCreateConfig(); - LOGGER.info("Config loaded!!"); - - } - - @SubscribeEvent - public void onServerStarted(ServerStartedEvent event) { - BackupWrapper.checkStartupBackups(); - } - - @SubscribeEvent - public void onServerStopping(ServerStoppingEvent event) { - BackupWrapper.checkShutdownBackups(); - } - - - @SubscribeEvent - public void onPlayerJoined(PlayerEvent.PlayerLoggedInEvent event) { - ABCore.setActivity(true); - } - - @SubscribeEvent - public void registerCommands(RegisterCommandsEvent event){ - AdvancedBackupsCommand.register(event.getDispatcher()); - } - - - @SubscribeEvent - public void onPostTick(TickEvent.ServerTickEvent event) { - if (!event.phase.equals(TickEvent.Phase.END)) return; - BackupTimer.check(); - } - - - public static final String savesDisabledMessage = """ - - - *************************************** - SAVING DISABLED - PREPARING FOR BACKUP! - *************************************** - """; - public static final String savesEnabledMessage = """ - - - ********************************* - SAVING ENABLED - BACKUP COMPLETE! - ********************************* - """; - public static final String saveCompleteMessage = """ - - - ************************************* - SAVE COMPLETE - PREPARING FOR BACKUP! - ************************************* - """; - - - public static void disableSaving() { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - for (ServerLevel level : server.getAllLevels()) { - if (level != null && !level.noSave) { - level.noSave = true; - } - } - if (ConfigManager.silent.get()) return; - warningLogger.accept(savesDisabledMessage); - } - - public static void enableSaving() { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - for (ServerLevel level : server.getAllLevels()) { - if (level != null && level.noSave) { - level.noSave = false; - } - } - if (ConfigManager.silent.get()) return; - warningLogger.accept(savesEnabledMessage); - } - - public static void saveOnce(boolean flush) { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - server.saveEverything(true, flush, true); - if (ConfigManager.silent.get()) return; - warningLogger.accept(saveCompleteMessage); - } - - - public static void resetActivity() { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - List players = server.getPlayerList().getPlayers(); - ABCore.setActivity(!players.isEmpty()); - } - -} +package co.uk.mommyheather.advancedbackups; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; + +import org.slf4j.Logger; + +import com.mojang.logging.LogUtils; + +import co.uk.mommyheather.advancedbackups.client.ClientContactor; +import co.uk.mommyheather.advancedbackups.client.ClientWrapper; +import co.uk.mommyheather.advancedbackups.core.ABCore; +import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; +import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; +import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.level.storage.LevelResource; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.RegisterCommandsEvent; +import net.minecraftforge.event.TickEvent; +import net.minecraftforge.event.entity.player.PlayerEvent; +import net.minecraftforge.event.server.ServerStartedEvent; +import net.minecraftforge.event.server.ServerStartingEvent; +import net.minecraftforge.event.server.ServerStoppingEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.ModList; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; +import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; +import net.minecraftforge.server.ServerLifecycleHooks; + +@Mod("advancedbackups") +public class AdvancedBackups +{ + + private static final Logger LOGGER = LogUtils.getLogger(); + + public static final Consumer infoLogger = LOGGER::info; + public static final Consumer warningLogger = LOGGER::warn; + public static final Consumer errorLogger = LOGGER::error; + + public static final ArrayList players = new ArrayList<>(); + + + public AdvancedBackups() + { + // Register ourselves for server and other game events we are interested in + MinecraftForge.EVENT_BUS.register(this); + FMLJavaModLoadingContext.get().getModEventBus().addListener(this::clientSetup); + NetworkHandler.register(); + + ABCore.infoLogger = infoLogger; + ABCore.warningLogger = warningLogger; + ABCore.errorLogger = errorLogger; + } + + @SubscribeEvent + public void onServerStarting(ServerStartingEvent event) + { + // Do something when the server starts + ABCore.worldName = event.getServer().getWorldData().getLevelName(); + ABCore.worldDir = event.getServer().getWorldPath(LevelResource.ROOT); + + ABCore.disableSaving = AdvancedBackups::disableSaving; + ABCore.enableSaving = AdvancedBackups::enableSaving; + ABCore.saveOnce = AdvancedBackups::saveOnce; + + ABCore.resetActivity = AdvancedBackups::resetActivity; + + ABCore.clientContactor = new ClientContactor(); + ABCore.modJar = ModList.get().getModFileById("advancedbackups").getFile().getFilePath().toFile(); + + + ConfigManager.loadOrCreateConfig(); + LOGGER.info("Config loaded!!"); + + } + + public void clientSetup(FMLClientSetupEvent e) { + ClientWrapper.init(e); + } + + @SubscribeEvent + public void onServerStarted(ServerStartedEvent event) { + BackupWrapper.checkStartupBackups(); + } + + @SubscribeEvent + public void onServerStopping(ServerStoppingEvent event) { + BackupWrapper.checkShutdownBackups(); + } + + + @SubscribeEvent + public void onPlayerJoined(PlayerEvent.PlayerLoggedInEvent event) { + ABCore.setActivity(true); + } + + @SubscribeEvent + public void registerCommands(RegisterCommandsEvent event){ + AdvancedBackupsCommand.register(event.getDispatcher()); + } + + + @SubscribeEvent + public void onPostTick(TickEvent.ServerTickEvent event) { + if (!event.phase.equals(TickEvent.Phase.END)) return; + BackupTimer.check(); + } + + + public static final String savesDisabledMessage = """ + + + *************************************** + SAVING DISABLED - PREPARING FOR BACKUP! + *************************************** + """; + public static final String savesEnabledMessage = """ + + + ********************************* + SAVING ENABLED - BACKUP COMPLETE! + ********************************* + """; + public static final String saveCompleteMessage = """ + + + ************************************* + SAVE COMPLETE - PREPARING FOR BACKUP! + ************************************* + """; + + + public static void disableSaving() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + for (ServerLevel level : server.getAllLevels()) { + if (level != null && !level.noSave) { + level.noSave = true; + } + } + if (ConfigManager.silent.get()) return; + warningLogger.accept(savesDisabledMessage); + } + + public static void enableSaving() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + for (ServerLevel level : server.getAllLevels()) { + if (level != null && level.noSave) { + level.noSave = false; + } + } + if (ConfigManager.silent.get()) return; + warningLogger.accept(savesEnabledMessage); + } + + public static void saveOnce(boolean flush) { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + server.saveEverything(true, flush, true); + if (ConfigManager.silent.get()) return; + warningLogger.accept(saveCompleteMessage); + } + + + public static void resetActivity() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + ABCore.setActivity(!players.isEmpty()); + } + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index e34d4a7b..39c41744 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -1,64 +1,71 @@ -package co.uk.mommyheather.advancedbackups; - -import com.mojang.brigadier.CommandDispatcher; - -import co.uk.mommyheather.advancedbackups.core.CoreCommandSystem; -import net.minecraft.commands.CommandSourceStack; -import net.minecraft.commands.Commands; -import net.minecraft.network.chat.Component; -import net.minecraftforge.server.ServerLifecycleHooks; - -public class AdvancedBackupsCommand { - public static void register(CommandDispatcher stack) { - stack.register(Commands.literal("backup").requires((runner) -> { - return !ServerLifecycleHooks.getCurrentServer().isDedicatedServer() || runner.hasPermission(3); - }).then(Commands.literal("start").executes((runner) -> { - CoreCommandSystem.startBackup((response) -> { - runner.getSource().sendSuccess(() -> { - return Component.literal(response) ; - }, true); - }); - return 1; - })) - - .then(Commands.literal("reload-config").executes((runner) -> { - CoreCommandSystem.reloadConfig((response) -> { - runner.getSource().sendSuccess(() -> { - return Component.literal(response) ; - }, true); - }); - return 1; - })) - - .then(Commands.literal("reset-chain").executes((runner) -> { - CoreCommandSystem.resetChainLength((response) -> { - runner.getSource().sendSuccess(() -> { - return Component.literal(response) ; - }, true); - }); - return 1; - })) - - .then(Commands.literal("snapshot").executes((runner) -> { - CoreCommandSystem.snapshot((response) -> { - runner.getSource().sendSuccess(() -> { - return Component.literal(response) ; - }, true); - }); - return 1; - })) - - .then(Commands.literal("cancel").executes((runner) -> { - CoreCommandSystem.cancelBackup((response) -> { - runner.getSource().sendSuccess(() -> { - return Component.literal(response) ; - }, true); - }); - return 1; - })) - - ); - } - - -} +package co.uk.mommyheather.advancedbackups; + +import com.mojang.brigadier.CommandDispatcher; + +import co.uk.mommyheather.advancedbackups.core.CoreCommandSystem; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.commands.Commands; +import net.minecraft.network.chat.Component; +import net.minecraftforge.server.ServerLifecycleHooks; + +public class AdvancedBackupsCommand { + public static void register(CommandDispatcher stack) { + stack.register(Commands.literal("backup").requires((runner) -> { + return !ServerLifecycleHooks.getCurrentServer().isDedicatedServer() || runner.hasPermission(3); + }).then(Commands.literal("start").executes((runner) -> { + CoreCommandSystem.startBackup((response) -> { + runner.getSource().sendSuccess(() -> { + return Component.literal(response) ; + }, true); + }); + return 1; + })) + + .then(Commands.literal("reload-config").executes((runner) -> { + CoreCommandSystem.reloadConfig((response) -> { + runner.getSource().sendSuccess(() -> { + return Component.literal(response) ; + }, true); + }); + return 1; + })) + + .then(Commands.literal("reset-chain").executes((runner) -> { + CoreCommandSystem.resetChainLength((response) -> { + runner.getSource().sendSuccess(() -> { + return Component.literal(response) ; + }, true); + }); + return 1; + })) + + .then(Commands.literal("snapshot").executes((runner) -> { + CoreCommandSystem.snapshot((response) -> { + runner.getSource().sendSuccess(() -> { + return Component.literal(response) ; + }, true); + }); + return 1; + })) + + .then(Commands.literal("cancel").executes((runner) -> { + CoreCommandSystem.cancelBackup((response) -> { + runner.getSource().sendSuccess(() -> { + return Component.literal(response) ; + }, true); + }); + return 1; + })) + + .then(Commands.literal("reload-client-config").executes((runner) -> { + runner.getSource().sendSuccess(() -> { + return Component.literal("This command can only be ran on the client!") ; + }, true); + return 1; + })) + + ); + } + + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java new file mode 100644 index 00000000..dd25a1d8 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java @@ -0,0 +1,73 @@ +package co.uk.mommyheather.advancedbackups.client; + +import java.time.Instant; + +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; + +import co.uk.mommyheather.advancedbackups.core.CoreCommandSystem; +import net.minecraft.client.Minecraft; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.commands.arguments.ArgumentSignatures; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.LastSeenMessages.Update; +import net.minecraft.network.protocol.game.ServerboundChatCommandPacket; +import net.minecraftforge.client.ClientCommandSourceStack; +import net.minecraftforge.server.ServerLifecycleHooks; + +public class AdvancedBackupsClientCommand { + public static void register(CommandDispatcher commandDispatcher) { + commandDispatcher.register(literal("backup").requires((runner) -> { + return !ServerLifecycleHooks.getCurrentServer().isDedicatedServer() || runner.hasPermission(3); + }).then(literal("start").executes((runner) -> { + Update acknowledgment = Minecraft.getInstance().player.connection.lastSeenMessages.generateAndApplyUpdate().update(); + Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup start", Instant.now(), 0, + ArgumentSignatures.EMPTY, acknowledgment)); + return 1; + })) + + .then(literal("reload-config").executes((runner) -> { + Update acknowledgment = Minecraft.getInstance().player.connection.lastSeenMessages.generateAndApplyUpdate().update(); + Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup reload-config", Instant.now(), 0, + ArgumentSignatures.EMPTY, acknowledgment)); + return 1; + })) + + .then(literal("reset-chain").executes((runner) -> { + Update acknowledgment = Minecraft.getInstance().player.connection.lastSeenMessages.generateAndApplyUpdate().update(); + Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup reset-chain", Instant.now(), 0, + ArgumentSignatures.EMPTY, acknowledgment)); + return 1; + })) + + .then(literal("snapshot").executes((runner) -> { + Update acknowledgment = Minecraft.getInstance().player.connection.lastSeenMessages.generateAndApplyUpdate().update(); + Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup snapshot", Instant.now(), 0, + ArgumentSignatures.EMPTY, acknowledgment)); + return 1; + })) + + .then(literal("cancel").executes((runner) -> { + Update acknowledgment = Minecraft.getInstance().player.connection.lastSeenMessages.generateAndApplyUpdate().update(); + Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup cancel", Instant.now(), 0, + ArgumentSignatures.EMPTY, acknowledgment)); + return 1; + })) + + .then(literal("reload-client-config").executes((runner) -> { + CoreCommandSystem.reloadClientConfig((response) -> { + runner.getSource().sendSuccess(Component.literal(response), true); + }); + return 1; + })) + + ); + } + + //I'm no fan of having this here but it seems required + public static LiteralArgumentBuilder literal(String literal) { + return LiteralArgumentBuilder.literal(literal); + } + + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java index f09cc00b..9ae56d6f 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java @@ -1,26 +1,46 @@ -package co.uk.mommyheather.advancedbackups.client; - -import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; -import net.minecraft.client.Minecraft; - -public class ClientWrapper { - - public static void handle(PacketBackupStatus packet) { - - BackupToast.starting = packet.starting; - BackupToast.started = packet.started; - BackupToast.failed = packet.failed; - BackupToast.finished = packet.finished; - - BackupToast.cancelled = packet.cancelled; - - BackupToast.progress = packet.progress; - BackupToast.max = packet.max; - - if (!BackupToast.exists) { - BackupToast.exists = true; - Minecraft.getInstance().getToasts().addToast(new BackupToast()); - } - } - -} +package co.uk.mommyheather.advancedbackups.client; + +import co.uk.mommyheather.advancedbackups.core.config.ClientConfigManager; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; +import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; +import net.minecraft.client.Minecraft; +import net.minecraftforge.client.event.ClientPlayerNetworkEvent; +import net.minecraftforge.client.event.RegisterClientCommandsEvent; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; + +public class ClientWrapper { + + public static void handle(PacketBackupStatus packet) { + + BackupToast.starting = packet.starting; + BackupToast.started = packet.started; + BackupToast.failed = packet.failed; + BackupToast.finished = packet.finished; + + BackupToast.cancelled = packet.cancelled; + + BackupToast.progress = packet.progress; + BackupToast.max = packet.max; + + if (!BackupToast.exists) { + BackupToast.exists = true; + Minecraft.getInstance().getToasts().addToast(new BackupToast()); + } + } + + public static void init(FMLClientSetupEvent e) { + MinecraftForge.EVENT_BUS.addListener(ClientWrapper::registerClientCommands); + MinecraftForge.EVENT_BUS.addListener(ClientWrapper::onServerConnected); + ClientConfigManager.loadOrCreateConfig(); + } + + public static void registerClientCommands(RegisterClientCommandsEvent event) { + AdvancedBackupsClientCommand.register(event.getDispatcher()); + } + + public static void onServerConnected(ClientPlayerNetworkEvent.LoggingIn event) { + NetworkHandler.sendToServer(new PacketToastSubscribe(ClientConfigManager.showProgress.get())); + } + +} From ee965fcbf60a3830983dccc6d35c49160f3091ae Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Wed, 13 Mar 2024 18:57:31 +0000 Subject: [PATCH 458/580] accesstransformer is required --- build.gradle | 453 +++++++++--------- .../resources/META-INF/accesstransformer.cfg | 1 + 2 files changed, 230 insertions(+), 224 deletions(-) create mode 100644 src/main/resources/META-INF/accesstransformer.cfg diff --git a/build.gradle b/build.gradle index cd978ce7..b91808db 100644 --- a/build.gradle +++ b/build.gradle @@ -1,224 +1,229 @@ -plugins { - id 'eclipse' - id 'idea' - id 'maven-publish' - id 'net.neoforged.gradle' version '[6.0.18,6.2)' - id 'org.spongepowered.mixin' version '0.7.+' -} - -group = mod_group_id - -base { - archivesName = 'AdvancedBackups-' + modloaderName + "-" + minecraftVersion -} - -task copyVSCodeResources (dependsOn: 'processResources', type: Copy) { - from 'build/resources' - into 'bin/' -} - -// Mojang ships Java 17 to end users in 1.18+, so your mod should target Java 17. -java.toolchain.languageVersion = JavaLanguageVersion.of(17) - -println "Java: ${System.getProperty 'java.version'}, JVM: ${System.getProperty 'java.vm.version'} (${System.getProperty 'java.vendor'}), Arch: ${System.getProperty 'os.arch'}" -minecraft { - // The mappings can be changed at any time and must be in the following format. - // Channel: Version: - // official MCVersion Official field/method names from Mojang mapping files - // parchment YYYY.MM.DD-MCVersion Open community-sourced parameter names and javadocs layered on top of official - // - // You must be aware of the Mojang license when using the 'official' or 'parchment' mappings. - // See more information here: https://github.com/NeoForged/NeoForm/blob/main/Mojang.md - // - // Parchment is an unofficial project maintained by ParchmentMC, separate from MinecraftForge - // Additional setup is needed to use their mappings: https://parchmentmc.org/docs/getting-started - // - // Use non-default mappings at your own risk. They may not always work. - // Simply re-run your setup task after changing the mappings to update your workspace. - mappings channel: mapping_channel, version: mapping_version - - // When true, this property will have all Eclipse/IntelliJ IDEA run configurations run the "prepareX" task for the given run configuration before launching the game. - // In most cases, it is not necessary to enable. - // enableEclipsePrepareRuns = true - // enableIdeaPrepareRuns = true - - // This property allows configuring Gradle's ProcessResources task(s) to run on IDE output locations before launching the game. - // It is REQUIRED to be set to true for this template to function. - // See https://docs.gradle.org/current/dsl/org.gradle.language.jvm.tasks.ProcessResources.html - copyIdeResources = true - - // When true, this property will add the folder name of all declared run configurations to generated IDE run configurations. - // The folder name can be set on a run configuration using the "folderName" property. - // By default, the folder name of a run configuration is the name of the Gradle project containing it. - // generateRunFolders = true - - // This property enables access transformers for use in development. - // They will be applied to the Minecraft artifact. - // The access transformer file can be anywhere in the project. - // However, it must be at "META-INF/accesstransformer.cfg" in the final mod jar to be loaded by Forge. - // This default location is a best practice to automatically put the file in the right place in the final jar. - // See https://docs.neoforged.net/docs/1.20.x/advanced/accesstransformers/ for more information. - - // accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg') - - // Default run configurations. - // These can be tweaked, removed, or duplicated as needed. - runs { - // applies to all the run configs below - configureEach { - workingDirectory project.file("run/${it.name}") - - // Recommended logging data for a userdev environment - // The markers can be added/remove as needed separated by commas. - // "SCAN": For mods scan. - // "REGISTRIES": For firing of registry events. - // "REGISTRYDUMP": For getting the contents of all registries. - property 'forge.logging.markers', 'REGISTRIES' - - // Recommended logging level for the console - // You can set various levels here. - // Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels - property 'forge.logging.console.level', 'debug' - - mods { - "${mod_id}" { - source sourceSets.main - } - } - } - - client { - // Comma-separated list of namespaces to load gametests from. Empty = all namespaces. - property 'forge.enabledGameTestNamespaces', mod_id - } - - server { - property 'forge.enabledGameTestNamespaces', mod_id - args '--nogui' - } - - // This run config launches GameTestServer and runs all registered gametests, then exits. - // By default, the server will crash when no gametests are provided. - // The gametest system is also enabled by default for other run configs under the /test command. - gameTestServer { - property 'forge.enabledGameTestNamespaces', mod_id - } - - data { - // example of overriding the workingDirectory set in configureEach above, uncomment if you want to use it - // workingDirectory project.file('run-data') - - // Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources. - args '--mod', mod_id, '--all', '--output', file('src/generated/resources/'), '--existing', file('src/main/resources/') - } - } -} - -// Include resources generated by data generators. -sourceSets.main.resources { srcDir 'src/generated/resources' } - -configurations { - // configuration that holds jars to include in the jar - extraLibs -} - -repositories { - // Put repositories for dependencies here - // NeoGradle automatically adds the Forge maven and Maven Central for you - - // If you have mod jar dependencies in ./libs, you can declare them as a repository like so. - // See https://docs.gradle.org/current/userguide/declaring_repositories.html#sub:flat_dir_resolver - // flatDir { - // dir 'libs' - // } -} - -dependencies { - // Specify the version of Minecraft to use. - // Any artifact can be supplied so long as it has a "userdev" classifier artifact and is a compatible patcher artifact. - // The "userdev" classifier will be requested and setup by NeoGradle. - // If the group id is "net.minecraft" and the artifact id is one of ["client", "server", "joined"], - // then special handling is done to allow a setup of a vanilla dependency without the use of an external repository. - minecraft "net.neoforged:forge:${minecraft_version}-${neo_version}" - - // Example mod dependency with JEI - using fg.deobf() ensures the dependency is remapped to your development mappings - // The JEI API is declared for compile time use, while the full JEI artifact is used at runtime - // compileOnly fg.deobf("mezz.jei:jei-${mc_version}-common-api:${jei_version}") - // compileOnly fg.deobf("mezz.jei:jei-${mc_version}-forge-api:${jei_version}") - // runtimeOnly fg.deobf("mezz.jei:jei-${mc_version}-forge:${jei_version}") - - // Example mod dependency using a mod jar from ./libs with a flat dir repository - // This maps to ./libs/coolmod-${mc_version}-${coolmod_version}.jar - // The group id is ignored when searching -- in this case, it is "blank" - // implementation fg.deobf("blank:coolmod-${mc_version}:${coolmod_version}") - - minecraftLibrary files ('advancedbackups-corelib.jar') - extraLibs files ('advancedbackups-corelib.jar') - - // For more info: - // http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html - // http://www.gradle.org/docs/current/userguide/dependency_management.html -} - -// This block of code expands all declared replace properties in the specified resource targets. -// A missing property will result in an error. Properties are expanded using ${} Groovy notation. -// When "copyIdeResources" is enabled, this will also run before the game launches in IDE environments. -// See https://docs.gradle.org/current/dsl/org.gradle.language.jvm.tasks.ProcessResources.html -tasks.withType(ProcessResources).configureEach { - var replaceProperties = [ - minecraft_version : minecraft_version, minecraft_version_range: minecraft_version_range, - neo_version : neo_version, neo_version_range: neo_version_range, - loader_version_range: loader_version_range, - mod_id : mod_id, mod_name: mod_name, mod_license: mod_license, mod_version: mod_version, - mod_authors : mod_authors, mod_description: mod_description, pack_format_number: pack_format_number, - ] - inputs.properties replaceProperties - - filesMatching(['META-INF/mods.toml', 'pack.mcmeta']) { - expand replaceProperties + [project: project] - } -} - -// Example for how to get properties into the manifest for reading at runtime. -tasks.named('jar', Jar).configure { - manifest { - attributes([ - "Main-Class" : "co.uk.mommyheather.advancedbackups.cli.AdvancedBackupsCLI", - "Specification-Title" : "advancedbackups", - "Specification-Vendor" : "mommyheather", - "Specification-Version" : "1", // We are version 1 of ourselves - "Implementation-Title" : project.name, - "Implementation-Version" : project.jar.archiveVersion, - "Implementation-Vendor" : "mommyheather", - "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ") - ]) - } - from { - configurations.extraLibs.collect { it.isDirectory() ? it : zipTree(it) } - } - // This is the preferred method to reobfuscate your jar file - finalizedBy 'reobfJar' -} - -// However if you are in a multi-project build, dev time needs unobfed jar files, so you can delay the obfuscation until publishing by doing: -// tasks.named('publish').configure { -// dependsOn 'reobfJar' -// } - -// Example configuration to allow publishing using the maven-publish plugin -publishing { - publications { - register('mavenJava', MavenPublication) { - artifact jar - } - } - repositories { - maven { - url "file://${project.projectDir}/mcmodsrepo" - } - } -} - -tasks.withType(JavaCompile).configureEach { - options.encoding = 'UTF-8' // Use the UTF-8 charset for Java compilation -} +plugins { + id 'eclipse' + id 'idea' + id 'maven-publish' + id 'net.neoforged.gradle' version '[6.0.18,6.2)' + id 'org.spongepowered.mixin' version '0.7.+' +} + +group = mod_group_id + +base { + archivesName = 'AdvancedBackups-' + modloaderName + "-" + minecraftVersion +} + +task copyVSCodeResources (dependsOn: 'processResources', type: Copy) { + from 'build/resources' + into 'bin/' +} + +// Mojang ships Java 17 to end users in 1.18+, so your mod should target Java 17. +java.toolchain.languageVersion = JavaLanguageVersion.of(17) + +println "Java: ${System.getProperty 'java.version'}, JVM: ${System.getProperty 'java.vm.version'} (${System.getProperty 'java.vendor'}), Arch: ${System.getProperty 'os.arch'}" +minecraft { + // The mappings can be changed at any time and must be in the following format. + // Channel: Version: + // official MCVersion Official field/method names from Mojang mapping files + // parchment YYYY.MM.DD-MCVersion Open community-sourced parameter names and javadocs layered on top of official + // + // You must be aware of the Mojang license when using the 'official' or 'parchment' mappings. + // See more information here: https://github.com/NeoForged/NeoForm/blob/main/Mojang.md + // + // Parchment is an unofficial project maintained by ParchmentMC, separate from MinecraftForge + // Additional setup is needed to use their mappings: https://parchmentmc.org/docs/getting-started + // + // Use non-default mappings at your own risk. They may not always work. + // Simply re-run your setup task after changing the mappings to update your workspace. + mappings channel: mapping_channel, version: mapping_version + + // When true, this property will have all Eclipse/IntelliJ IDEA run configurations run the "prepareX" task for the given run configuration before launching the game. + // In most cases, it is not necessary to enable. + // enableEclipsePrepareRuns = true + // enableIdeaPrepareRuns = true + + // This property allows configuring Gradle's ProcessResources task(s) to run on IDE output locations before launching the game. + // It is REQUIRED to be set to true for this template to function. + // See https://docs.gradle.org/current/dsl/org.gradle.language.jvm.tasks.ProcessResources.html + copyIdeResources = true + + // When true, this property will add the folder name of all declared run configurations to generated IDE run configurations. + // The folder name can be set on a run configuration using the "folderName" property. + // By default, the folder name of a run configuration is the name of the Gradle project containing it. + // generateRunFolders = true + + // This property enables access transformers for use in development. + // They will be applied to the Minecraft artifact. + // The access transformer file can be anywhere in the project. + // However, it must be at "META-INF/accesstransformer.cfg" in the final mod jar to be loaded by Forge. + // This default location is a best practice to automatically put the file in the right place in the final jar. + // See https://docs.neoforged.net/docs/1.20.x/advanced/accesstransformers/ for more information. + + accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg') + + // Default run configurations. + // These can be tweaked, removed, or duplicated as needed. + runs { + // applies to all the run configs below + configureEach { + workingDirectory project.file("run/${it.name}") + + // Recommended logging data for a userdev environment + // The markers can be added/remove as needed separated by commas. + // "SCAN": For mods scan. + // "REGISTRIES": For firing of registry events. + // "REGISTRYDUMP": For getting the contents of all registries. + property 'forge.logging.markers', 'REGISTRIES' + + // Recommended logging level for the console + // You can set various levels here. + // Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels + property 'forge.logging.console.level', 'debug' + + mods { + "${mod_id}" { + source sourceSets.main + } + } + } + + client { + // Comma-separated list of namespaces to load gametests from. Empty = all namespaces. + property 'forge.enabledGameTestNamespaces', mod_id + } + + server { + property 'forge.enabledGameTestNamespaces', mod_id + args '--nogui' + } + + // This run config launches GameTestServer and runs all registered gametests, then exits. + // By default, the server will crash when no gametests are provided. + // The gametest system is also enabled by default for other run configs under the /test command. + gameTestServer { + property 'forge.enabledGameTestNamespaces', mod_id + } + + data { + // example of overriding the workingDirectory set in configureEach above, uncomment if you want to use it + // workingDirectory project.file('run-data') + + // Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources. + args '--mod', mod_id, '--all', '--output', file('src/generated/resources/'), '--existing', file('src/main/resources/') + } + } +} + +// Include resources generated by data generators. +sourceSets.main.resources { srcDir 'src/generated/resources' } + +configurations { + // configuration that holds jars to include in the jar + extraLibs +} + +repositories { + // Put repositories for dependencies here + // NeoGradle automatically adds the Forge maven and Maven Central for you + + // If you have mod jar dependencies in ./libs, you can declare them as a repository like so. + // See https://docs.gradle.org/current/userguide/declaring_repositories.html#sub:flat_dir_resolver + // flatDir { + // dir 'libs' + // } + maven { + url "https://cursemaven.com" + } +} + +dependencies { + // Specify the version of Minecraft to use. + // Any artifact can be supplied so long as it has a "userdev" classifier artifact and is a compatible patcher artifact. + // The "userdev" classifier will be requested and setup by NeoGradle. + // If the group id is "net.minecraft" and the artifact id is one of ["client", "server", "joined"], + // then special handling is done to allow a setup of a vanilla dependency without the use of an external repository. + minecraft "net.neoforged:forge:${minecraft_version}-${neo_version}" + + // Example mod dependency with JEI - using fg.deobf() ensures the dependency is remapped to your development mappings + // The JEI API is declared for compile time use, while the full JEI artifact is used at runtime + // compileOnly fg.deobf("mezz.jei:jei-${mc_version}-common-api:${jei_version}") + // compileOnly fg.deobf("mezz.jei:jei-${mc_version}-forge-api:${jei_version}") + // runtimeOnly fg.deobf("mezz.jei:jei-${mc_version}-forge:${jei_version}") + + // Example mod dependency using a mod jar from ./libs with a flat dir repository + // This maps to ./libs/coolmod-${mc_version}-${coolmod_version}.jar + // The group id is ignored when searching -- in this case, it is "blank" + // implementation fg.deobf("blank:coolmod-${mc_version}:${coolmod_version}") + + minecraftLibrary files ('advancedbackups-corelib.jar') + extraLibs files ('advancedbackups-corelib.jar') + + implementation fg.deobf('curse.maven:jei-322036:4680512') + + // For more info: + // http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html + // http://www.gradle.org/docs/current/userguide/dependency_management.html +} + +// This block of code expands all declared replace properties in the specified resource targets. +// A missing property will result in an error. Properties are expanded using ${} Groovy notation. +// When "copyIdeResources" is enabled, this will also run before the game launches in IDE environments. +// See https://docs.gradle.org/current/dsl/org.gradle.language.jvm.tasks.ProcessResources.html +tasks.withType(ProcessResources).configureEach { + var replaceProperties = [ + minecraft_version : minecraft_version, minecraft_version_range: minecraft_version_range, + neo_version : neo_version, neo_version_range: neo_version_range, + loader_version_range: loader_version_range, + mod_id : mod_id, mod_name: mod_name, mod_license: mod_license, mod_version: mod_version, + mod_authors : mod_authors, mod_description: mod_description, pack_format_number: pack_format_number, + ] + inputs.properties replaceProperties + + filesMatching(['META-INF/mods.toml', 'pack.mcmeta']) { + expand replaceProperties + [project: project] + } +} + +// Example for how to get properties into the manifest for reading at runtime. +tasks.named('jar', Jar).configure { + manifest { + attributes([ + "Main-Class" : "co.uk.mommyheather.advancedbackups.cli.AdvancedBackupsCLI", + "Specification-Title" : "advancedbackups", + "Specification-Vendor" : "mommyheather", + "Specification-Version" : "1", // We are version 1 of ourselves + "Implementation-Title" : project.name, + "Implementation-Version" : project.jar.archiveVersion, + "Implementation-Vendor" : "mommyheather", + "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ") + ]) + } + from { + configurations.extraLibs.collect { it.isDirectory() ? it : zipTree(it) } + } + // This is the preferred method to reobfuscate your jar file + finalizedBy 'reobfJar' +} + +// However if you are in a multi-project build, dev time needs unobfed jar files, so you can delay the obfuscation until publishing by doing: +// tasks.named('publish').configure { +// dependsOn 'reobfJar' +// } + +// Example configuration to allow publishing using the maven-publish plugin +publishing { + publications { + register('mavenJava', MavenPublication) { + artifact jar + } + } + repositories { + maven { + url "file://${project.projectDir}/mcmodsrepo" + } + } +} + +tasks.withType(JavaCompile).configureEach { + options.encoding = 'UTF-8' // Use the UTF-8 charset for Java compilation +} diff --git a/src/main/resources/META-INF/accesstransformer.cfg b/src/main/resources/META-INF/accesstransformer.cfg new file mode 100644 index 00000000..e456e70b --- /dev/null +++ b/src/main/resources/META-INF/accesstransformer.cfg @@ -0,0 +1 @@ +public net.minecraft.client.multiplayer.ClientPacketListener f_244346_ # lastSeenMessages \ No newline at end of file From bb65cff27618b2291a10130b81cd48ab2c3553f7 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Wed, 13 Mar 2024 19:21:47 +0000 Subject: [PATCH 459/580] localise cancelled toast --- .../resources/assets/advancedbackups/lang/en_us.json | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main/resources/assets/advancedbackups/lang/en_us.json b/src/main/resources/assets/advancedbackups/lang/en_us.json index cc68dae1..9a59cd17 100644 --- a/src/main/resources/assets/advancedbackups/lang/en_us.json +++ b/src/main/resources/assets/advancedbackups/lang/en_us.json @@ -1,6 +1,7 @@ -{ - "advancedbackups.backup_starting" : "Backup starting!", - "advancedbackups.progress": "Backup ongoing: %1$s%%", - "advancedbackups.backup_failed": "Backup failed!\nCheck log for more info.", - "advancedbackups.backup_finished": "Backup complete!" +{ + "advancedbackups.backup_starting" : "Backup starting!", + "advancedbackups.progress": "Backup ongoing: %1$s%%", + "advancedbackups.backup_failed": "Backup failed!\nCheck log for more info.", + "advancedbackups.backup_finished": "Backup complete!", + "advancedbackups.backup_cancelled": "Backup cancelled!" } \ No newline at end of file From 1751387bc967cf34fed1de9d4d417c7c001e989d Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Wed, 13 Mar 2024 19:22:04 +0000 Subject: [PATCH 460/580] client can now subscribe to toasts --- .../advancedbackups/client/ClientWrapper.java | 1 + .../network/NetworkHandler.java | 84 +++++++++++-------- .../network/PacketToastSubscribe.java | 41 +++++++++ 3 files changed, 89 insertions(+), 37 deletions(-) create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java index 9ae56d6f..01815817 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java @@ -3,6 +3,7 @@ import co.uk.mommyheather.advancedbackups.core.config.ClientConfigManager; import co.uk.mommyheather.advancedbackups.network.NetworkHandler; import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; +import co.uk.mommyheather.advancedbackups.network.PacketToastSubscribe; import net.minecraft.client.Minecraft; import net.minecraftforge.client.event.ClientPlayerNetworkEvent; import net.minecraftforge.client.event.RegisterClientCommandsEvent; diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java index 0c856fa0..f94af49e 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java @@ -1,37 +1,47 @@ -package co.uk.mommyheather.advancedbackups.network; - -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.level.ServerPlayer; -import net.minecraftforge.network.NetworkDirection; -import net.minecraftforge.network.NetworkRegistry; -import net.minecraftforge.network.simple.SimpleChannel; - -public class NetworkHandler { - - private static final String PROTOCOL_VERSION = "1"; - private static int id = 0; - private static int id() { - return id++; - } - - public static final SimpleChannel INSTANCE = NetworkRegistry.newSimpleChannel( - new ResourceLocation("advancedbackups", "main"), - () -> PROTOCOL_VERSION, - (version) -> true, - (version) -> true - ); - - - public static void register() { - INSTANCE.messageBuilder(PacketBackupStatus.class, id()) - .encoder(PacketBackupStatus::toBytes) - .decoder(buf -> new PacketBackupStatus(buf)) - .consumerNetworkThread(PacketBackupStatus::handle) - .add(); - } - - public static void sendToClient(ServerPlayer player, Object packet) { - INSTANCE.sendTo(packet, player.connection.connection, NetworkDirection.PLAY_TO_CLIENT); - } - -} +package co.uk.mommyheather.advancedbackups.network; + +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerPlayer; +import net.minecraftforge.network.NetworkDirection; +import net.minecraftforge.network.NetworkRegistry; +import net.minecraftforge.network.simple.SimpleChannel; + +public class NetworkHandler { + + private static final String PROTOCOL_VERSION = "1"; + private static int id = 0; + private static int id() { + return id++; + } + + public static final SimpleChannel INSTANCE = NetworkRegistry.newSimpleChannel( + new ResourceLocation("advancedbackups", "main"), + () -> PROTOCOL_VERSION, + (version) -> true, + (version) -> true + ); + + + public static void register() { + INSTANCE.messageBuilder(PacketBackupStatus.class, id()) + .encoder(PacketBackupStatus::toBytes) + .decoder(buf -> new PacketBackupStatus(buf)) + .consumerNetworkThread(PacketBackupStatus::handle) + .add(); + + INSTANCE.messageBuilder(PacketToastSubscribe.class, id()) + .encoder(PacketToastSubscribe::toBytes) + .decoder(buf -> new PacketToastSubscribe(buf)) + .consumerNetworkThread(PacketToastSubscribe::handle) + .add(); + } + + public static void sendToClient(ServerPlayer player, Object packet) { + INSTANCE.sendTo(packet, player.connection.connection, NetworkDirection.PLAY_TO_CLIENT); + } + + public static void sendToServer(Object packet) { + INSTANCE.sendToServer(packet); + } + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java new file mode 100644 index 00000000..c4bf9942 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java @@ -0,0 +1,41 @@ +package co.uk.mommyheather.advancedbackups.network; + +import java.util.function.Supplier; + +import co.uk.mommyheather.advancedbackups.AdvancedBackups; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraftforge.network.NetworkEvent; + +public class PacketToastSubscribe { + + private boolean enable; + + public PacketToastSubscribe(boolean enable) { + this.enable = enable; + } + + + public PacketToastSubscribe(FriendlyByteBuf buf) { + enable = buf.readBoolean(); + } + + public void toBytes(FriendlyByteBuf buf) { + buf.writeBoolean(enable); + } + + public boolean handle(Supplier ctx) { + ctx.get().enqueueWork(() -> { + if (ctx.get().getSender() == null) return; + if (enable && !AdvancedBackups.players.contains(ctx.get().getSender().getStringUUID())) { + AdvancedBackups.players.add(ctx.get().getSender().getStringUUID()); + } + else if (!enable) { + AdvancedBackups.players.remove(ctx.get().getSender().getStringUUID()); + } + }); + + return true; + + } + +} From 4324bc26d5a32199d5b26e0f1d4c8f363e6a8aec Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Wed, 13 Mar 2024 19:22:48 +0000 Subject: [PATCH 461/580] client config reloading --- .../advancedbackups/client/AdvancedBackupsClientCommand.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java index dd25a1d8..6352c467 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java @@ -56,7 +56,9 @@ public static void register(CommandDispatcher commandDispatc .then(literal("reload-client-config").executes((runner) -> { CoreCommandSystem.reloadClientConfig((response) -> { - runner.getSource().sendSuccess(Component.literal(response), true); + runner.getSource().sendSuccess(() -> { + return Component.literal(response); + }, true); }); return 1; })) From 9046a53d34c62f6901c41875d03a5a4f0441b9b8 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Mon, 18 Mar 2024 18:45:07 +0000 Subject: [PATCH 462/580] support all 3.5 changes in 1.20 fabric --- build.gradle | 194 ++++++------ .../advancedbackups/AdvancedBackups.java | 298 +++++++++--------- .../AdvancedBackupsCommand.java | 104 +++--- .../client/AdvancedBackupsClientCommand.java | 62 ++++ .../advancedbackups/client/BackupToast.java | 227 +++++++------ .../client/ClientContactor.java | 139 ++++---- .../advancedbackups/client/ClientWrapper.java | 120 ++++--- .../advancedbackups/client/ColourHelper.java | 31 ++ .../network/NetworkHandler.java | 45 +-- .../network/PacketBackupStatus.java | 115 +++---- .../network/PacketToastSubscribe.java | 59 ++++ .../resources/advancedbackups.accesswidener | 4 + .../assets/advancedbackups/lang/en_us.json | 11 +- 13 files changed, 831 insertions(+), 578 deletions(-) create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/client/ColourHelper.java create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java create mode 100644 src/main/resources/advancedbackups.accesswidener diff --git a/build.gradle b/build.gradle index 922c32ce..5073512d 100644 --- a/build.gradle +++ b/build.gradle @@ -1,97 +1,99 @@ -plugins { - id 'fabric-loom' version '1.3-SNAPSHOT' - id 'maven-publish' -} - -group = project.maven_group -archivesBaseName = 'AdvancedBackups-' + modloaderName + "-" + minecraftVersion - - - -repositories { - // Add repositories to retrieve artifacts from in here. - // You should only use this when depending on other mods because - // Loom adds the essential maven repositories to download Minecraft and libraries from automatically. - // See https://docs.gradle.org/current/userguide/declaring_repositories.html - // for more information about repositories. -} - -configurations { - // configuration that holds jars to include in the jar - extraLibs -} - -dependencies { - // To change the versions see the gradle.properties file - minecraft "com.mojang:minecraft:${project.minecraft_version}" - mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" - modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" - - // Fabric API. This is technically optional, but you probably want it anyway. - modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" - - // Uncomment the following line to enable the deprecated Fabric API modules. - // These are included in the Fabric API production distribution and allow you to update your mod to the latest modules at a later more convenient time. - - // modImplementation "net.fabricmc.fabric-api:fabric-api-deprecated:${project.fabric_version}" - - implementation files ('advancedbackups-corelib.jar') - extraLibs files ('advancedbackups-corelib.jar') -} - -processResources { - inputs.property "version", project.version - - filesMatching("fabric.mod.json") { - expand "version": project.version - } -} - -tasks.withType(JavaCompile).configureEach { - it.options.release = 17 -} - -java { - // Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task - // if it is present. - // If you remove this line, sources will not be generated. - withSourcesJar() - - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 -} - -jar { - manifest { - attributes([ - "Main-Class" : "co.uk.mommyheather.advancedbackups.cli.AdvancedBackupsCLI", - "Specification-Title" : "advancedbackups", - "Specification-Vendor" : "mommyheather", - "Specification-Version" : "1", // We are version 1 of ourselves - "Implementation-Title" : project.name, - "Implementation-Version" : project.jar.archiveVersion, - "Implementation-Vendor" : "mommyheather", - "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ") - ]) - } - from { - configurations.extraLibs.collect { it.isDirectory() ? it : zipTree(it) } - } -} - -// configure the maven publication -publishing { - publications { - mavenJava(MavenPublication) { - from components.java - } - } - - // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing. - repositories { - // Add repositories to publish to here. - // Notice: This block does NOT have the same function as the block in the top level. - // The repositories here will be used for publishing your artifact, not for - // retrieving dependencies. - } +plugins { + id 'fabric-loom' version '1.3-SNAPSHOT' + id 'maven-publish' +} + +group = project.maven_group +archivesBaseName = 'AdvancedBackups-' + modloaderName + "-" + minecraftVersion + +loom { + accessWidenerPath = file("src/main/resources/advancedbackups.accesswidener") +} + +repositories { + // Add repositories to retrieve artifacts from in here. + // You should only use this when depending on other mods because + // Loom adds the essential maven repositories to download Minecraft and libraries from automatically. + // See https://docs.gradle.org/current/userguide/declaring_repositories.html + // for more information about repositories. +} + +configurations { + // configuration that holds jars to include in the jar + extraLibs +} + +dependencies { + // To change the versions see the gradle.properties file + minecraft "com.mojang:minecraft:${project.minecraft_version}" + mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" + modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" + + // Fabric API. This is technically optional, but you probably want it anyway. + modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" + + // Uncomment the following line to enable the deprecated Fabric API modules. + // These are included in the Fabric API production distribution and allow you to update your mod to the latest modules at a later more convenient time. + + // modImplementation "net.fabricmc.fabric-api:fabric-api-deprecated:${project.fabric_version}" + + implementation files ('advancedbackups-corelib.jar') + extraLibs files ('advancedbackups-corelib.jar') +} + +processResources { + inputs.property "version", project.version + + filesMatching("fabric.mod.json") { + expand "version": project.version + } +} + +tasks.withType(JavaCompile).configureEach { + it.options.release = 17 +} + +java { + // Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task + // if it is present. + // If you remove this line, sources will not be generated. + withSourcesJar() + + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 +} + +jar { + manifest { + attributes([ + "Main-Class" : "co.uk.mommyheather.advancedbackups.cli.AdvancedBackupsCLI", + "Specification-Title" : "advancedbackups", + "Specification-Vendor" : "mommyheather", + "Specification-Version" : "1", // We are version 1 of ourselves + "Implementation-Title" : project.name, + "Implementation-Version" : project.jar.archiveVersion, + "Implementation-Vendor" : "mommyheather", + "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ") + ]) + } + from { + configurations.extraLibs.collect { it.isDirectory() ? it : zipTree(it) } + } +} + +// configure the maven publication +publishing { + publications { + mavenJava(MavenPublication) { + from components.java + } + } + + // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing. + repositories { + // Add repositories to publish to here. + // Notice: This block does NOT have the same function as the block in the top level. + // The repositories here will be used for publishing your artifact, not for + // retrieving dependencies. + } } \ No newline at end of file diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index b5f0e257..69adbc9f 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -1,145 +1,153 @@ -package co.uk.mommyheather.advancedbackups; - -import java.io.File; -import java.util.List; -import java.util.function.Consumer; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import co.uk.mommyheather.advancedbackups.client.ClientContactor; -import co.uk.mommyheather.advancedbackups.core.ABCore; -import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; -import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; -import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; -import net.fabricmc.api.ModInitializer; -import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; -import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; -import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; -import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; -import net.fabricmc.loader.impl.FabricLoaderImpl; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.server.world.ServerWorld; -import net.minecraft.util.WorldSavePath; - -public class AdvancedBackups implements ModInitializer { - // This logger is used to write text to the console and the log file. - // It is considered best practice to use your mod id as the logger's name. - // That way, it's clear which mod wrote info, warnings, and errors. - - public static final Logger LOGGER = LoggerFactory.getLogger("advanced-backups"); - - public static final Consumer infoLogger = LOGGER::info; - public static final Consumer warningLogger = LOGGER::warn; - public static final Consumer errorLogger = LOGGER::error; - - public static MinecraftServer server; - - @Override - public void onInitialize() { - - ServerLifecycleEvents.SERVER_STARTING.register((server) -> { - AdvancedBackups.server = server; - ABCore.worldName = server.getSaveProperties().getLevelName(); - ABCore.worldDir = server.getSavePath(WorldSavePath.ROOT); - - ABCore.disableSaving = AdvancedBackups::disableSaving; - ABCore.enableSaving = AdvancedBackups::enableSaving; - ABCore.saveOnce = AdvancedBackups::saveOnce; - - ABCore.infoLogger = infoLogger; - ABCore.warningLogger = warningLogger; - ABCore.errorLogger = errorLogger; - - ABCore.resetActivity = AdvancedBackups::resetActivity; - - ABCore.clientContactor = new ClientContactor(); - ABCore.modJar = new File(FabricLoaderImpl.INSTANCE.getModContainer("advancedbackups").get().getOrigin().getPaths().get(0).toAbsolutePath().toString()); - - - ConfigManager.loadOrCreateConfig(); - LOGGER.info("Config loaded!!"); - }); - - ServerLifecycleEvents.SERVER_STARTED.register((server) -> { - BackupWrapper.checkStartupBackups(); - }); - ServerLifecycleEvents.SERVER_STOPPING.register((server) -> { - BackupWrapper.checkShutdownBackups(); - }); - - ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> { - ABCore.setActivity(true); - }); - - CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> { - AdvancedBackupsCommand.register(dispatcher); - }); - - - ServerTickEvents.END_SERVER_TICK.register((server) -> { - BackupTimer.check(); - }); - - - - } - - public static final String savesDisabledMessage = """ - - - *************************************** - SAVING DISABLED - PREPARING FOR BACKUP! - *************************************** - """; - public static final String savesEnabledMessage = """ - - - ********************************* - SAVING ENABLED - BACKUP COMPLETE! - ********************************* - """; - public static final String saveCompleteMessage = """ - - - ************************************* - SAVE COMPLETE - PREPARING FOR BACKUP! - ************************************* - """; - - - public static void disableSaving() { - MinecraftServer server = AdvancedBackups.server; - for (ServerWorld level : server.getWorlds()) { - if (level != null && !level.savingDisabled) { - level.savingDisabled = true; - } - } - if (ConfigManager.silent.get()) return; - warningLogger.accept(savesDisabledMessage); - } - - public static void enableSaving() { - MinecraftServer server = AdvancedBackups.server; - for (ServerWorld level : server.getWorlds()) { - if (level != null && level.savingDisabled) { - level.savingDisabled = false; - } - } - if (ConfigManager.silent.get()) return; - warningLogger.accept(savesEnabledMessage); - } - - public static void saveOnce(boolean flush) { - MinecraftServer server = AdvancedBackups.server; - server.saveAll(true, flush, true); - if (ConfigManager.silent.get()) return; - warningLogger.accept(saveCompleteMessage); - } - - public static void resetActivity() { - List players = server.getPlayerManager().getPlayerList(); - ABCore.setActivity(!players.isEmpty()); - } -} +package co.uk.mommyheather.advancedbackups; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import co.uk.mommyheather.advancedbackups.client.ClientContactor; +import co.uk.mommyheather.advancedbackups.core.ABCore; +import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; +import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; +import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; +import co.uk.mommyheather.advancedbackups.network.PacketToastSubscribe; +import net.fabricmc.api.ModInitializer; +import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; +import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; +import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; +import net.fabricmc.loader.impl.FabricLoaderImpl; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.WorldSavePath; + +public class AdvancedBackups implements ModInitializer { + // This logger is used to write text to the console and the log file. + // It is considered best practice to use your mod id as the logger's name. + // That way, it's clear which mod wrote info, warnings, and errors. + + public static final Logger LOGGER = LoggerFactory.getLogger("advanced-backups"); + + public static final Consumer infoLogger = LOGGER::info; + public static final Consumer warningLogger = LOGGER::warn; + public static final Consumer errorLogger = LOGGER::error; + + public static final ArrayList players = new ArrayList<>(); + + public static MinecraftServer server; + + @Override + public void onInitialize() { + + ServerLifecycleEvents.SERVER_STARTING.register((server) -> { + AdvancedBackups.server = server; + ABCore.worldName = server.getSaveProperties().getLevelName(); + ABCore.worldDir = server.getSavePath(WorldSavePath.ROOT); + + ABCore.disableSaving = AdvancedBackups::disableSaving; + ABCore.enableSaving = AdvancedBackups::enableSaving; + ABCore.saveOnce = AdvancedBackups::saveOnce; + + ABCore.infoLogger = infoLogger; + ABCore.warningLogger = warningLogger; + ABCore.errorLogger = errorLogger; + + ABCore.resetActivity = AdvancedBackups::resetActivity; + + ABCore.clientContactor = new ClientContactor(); + ABCore.modJar = new File(FabricLoaderImpl.INSTANCE.getModContainer("advancedbackups").get().getOrigin().getPaths().get(0).toAbsolutePath().toString()); + + + ConfigManager.loadOrCreateConfig(); + LOGGER.info("Config loaded!!"); + }); + + ServerLifecycleEvents.SERVER_STARTED.register((server) -> { + BackupWrapper.checkStartupBackups(); + }); + ServerLifecycleEvents.SERVER_STOPPING.register((server) -> { + BackupWrapper.checkShutdownBackups(); + }); + + ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> { + ABCore.setActivity(true); + }); + + CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> { + AdvancedBackupsCommand.register(dispatcher); + }); + + + ServerTickEvents.END_SERVER_TICK.register((server) -> { + BackupTimer.check(); + }); + + ServerPlayNetworking.registerGlobalReceiver(NetworkHandler.TOAST_SUBSCRIBE_ID, PacketToastSubscribe::handle); + + + + } + + public static final String savesDisabledMessage = """ + + + *************************************** + SAVING DISABLED - PREPARING FOR BACKUP! + *************************************** + """; + public static final String savesEnabledMessage = """ + + + ********************************* + SAVING ENABLED - BACKUP COMPLETE! + ********************************* + """; + public static final String saveCompleteMessage = """ + + + ************************************* + SAVE COMPLETE - PREPARING FOR BACKUP! + ************************************* + """; + + + public static void disableSaving() { + MinecraftServer server = AdvancedBackups.server; + for (ServerWorld level : server.getWorlds()) { + if (level != null && !level.savingDisabled) { + level.savingDisabled = true; + } + } + if (ConfigManager.silent.get()) return; + warningLogger.accept(savesDisabledMessage); + } + + public static void enableSaving() { + MinecraftServer server = AdvancedBackups.server; + for (ServerWorld level : server.getWorlds()) { + if (level != null && level.savingDisabled) { + level.savingDisabled = false; + } + } + if (ConfigManager.silent.get()) return; + warningLogger.accept(savesEnabledMessage); + } + + public static void saveOnce(boolean flush) { + MinecraftServer server = AdvancedBackups.server; + server.saveAll(true, flush, true); + if (ConfigManager.silent.get()) return; + warningLogger.accept(saveCompleteMessage); + } + + public static void resetActivity() { + List players = server.getPlayerManager().getPlayerList(); + ABCore.setActivity(!players.isEmpty()); + } +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index 78bbdc6f..af44e177 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -1,46 +1,58 @@ -package co.uk.mommyheather.advancedbackups; - -import com.mojang.brigadier.CommandDispatcher; - -import co.uk.mommyheather.advancedbackups.core.CoreCommandSystem; -import net.minecraft.server.command.CommandManager; -import net.minecraft.server.command.ServerCommandSource; -import net.minecraft.text.Text; - -public class AdvancedBackupsCommand { - public static void register(CommandDispatcher stack) { - stack.register(CommandManager.literal("backup").requires((runner) -> { - return !AdvancedBackups.server.isDedicated() || runner.hasPermissionLevel(3); - }).then(CommandManager.literal("start").executes((runner) -> { - CoreCommandSystem.startBackup((response) -> { - runner.getSource().sendFeedback(() -> Text.of(response), true); - }); - return 1; - })) - - .then(CommandManager.literal("reload-config").executes((runner) -> { - CoreCommandSystem.reloadConfig((response) -> { - runner.getSource().sendFeedback(() -> Text.of(response), true); - }); - return 1; - })) - - .then(CommandManager.literal("reset-chain").executes((runner) -> { - CoreCommandSystem.resetChainLength((response) -> { - runner.getSource().sendFeedback(() -> Text.of(response), true); - }); - return 1; - })) - - .then(CommandManager.literal("snapshot").executes((runner) -> { - CoreCommandSystem.snapshot((response) -> { - runner.getSource().sendFeedback(() -> Text.of(response), true); - }); - return 1; - })) - - ); - } - - -} +package co.uk.mommyheather.advancedbackups; + +import com.mojang.brigadier.CommandDispatcher; + +import co.uk.mommyheather.advancedbackups.core.CoreCommandSystem; +import net.minecraft.server.command.CommandManager; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.text.Text; + +public class AdvancedBackupsCommand { + public static void register(CommandDispatcher stack) { + stack.register(CommandManager.literal("backup").requires((runner) -> { + return !AdvancedBackups.server.isDedicated() || runner.hasPermissionLevel(3); + }).then(CommandManager.literal("start").executes((runner) -> { + CoreCommandSystem.startBackup((response) -> { + runner.getSource().sendFeedback(() -> Text.of(response), true); + }); + return 1; + })) + + .then(CommandManager.literal("reload-config").executes((runner) -> { + CoreCommandSystem.reloadConfig((response) -> { + runner.getSource().sendFeedback(() -> Text.of(response), true); + }); + return 1; + })) + + .then(CommandManager.literal("reset-chain").executes((runner) -> { + CoreCommandSystem.resetChainLength((response) -> { + runner.getSource().sendFeedback(() -> Text.of(response), true); + }); + return 1; + })) + + .then(CommandManager.literal("snapshot").executes((runner) -> { + CoreCommandSystem.snapshot((response) -> { + runner.getSource().sendFeedback(() -> Text.of(response), true); + }); + return 1; + })) + + .then(CommandManager.literal("cancel").executes((runner) -> { + CoreCommandSystem.cancelBackup((response) -> { + runner.getSource().sendFeedback(() -> Text.of(response), true); + }); + return 1; + })) + + .then(CommandManager.literal("reload-client-config").executes((runner) -> { + runner.getSource().sendFeedback(() -> Text.of("This command can only be ran on the client!"), true); + return 1; + })) + + ); + } + + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java new file mode 100644 index 00000000..c6316e9e --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java @@ -0,0 +1,62 @@ +package co.uk.mommyheather.advancedbackups.client; + + +import java.time.Instant; + +import com.mojang.brigadier.CommandDispatcher; + +import co.uk.mommyheather.advancedbackups.core.CoreCommandSystem; +import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; +import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; +import net.minecraft.client.MinecraftClient; +import net.minecraft.network.message.ArgumentSignatureDataMap; +import net.minecraft.network.message.LastSeenMessageList.Acknowledgment; +import net.minecraft.network.packet.c2s.play.CommandExecutionC2SPacket; +import net.minecraft.text.Text; + +public class AdvancedBackupsClientCommand { + public static void register(CommandDispatcher dispatcher) { + dispatcher.register(ClientCommandManager.literal("backup").requires((runner) -> { + return runner.hasPermissionLevel(0); + }).then(ClientCommandManager.literal("start").executes((runner) -> { + Acknowledgment acknowledgment = MinecraftClient.getInstance().player.networkHandler.lastSeenMessagesCollector.collect().update(); + MinecraftClient.getInstance().player.networkHandler.sendPacket(new CommandExecutionC2SPacket("backup start", Instant.now(), 0L, ArgumentSignatureDataMap.EMPTY, acknowledgment)); + return 1; + })) + + .then(ClientCommandManager.literal("reload-config").executes((runner) -> { + Acknowledgment acknowledgment = MinecraftClient.getInstance().player.networkHandler.lastSeenMessagesCollector.collect().update(); + MinecraftClient.getInstance().player.networkHandler.sendPacket(new CommandExecutionC2SPacket("backup reload-config", Instant.now(), 0L, ArgumentSignatureDataMap.EMPTY, acknowledgment)); + return 1; + })) + + .then(ClientCommandManager.literal("reset-chain").executes((runner) -> { + Acknowledgment acknowledgment = MinecraftClient.getInstance().player.networkHandler.lastSeenMessagesCollector.collect().update(); + MinecraftClient.getInstance().player.networkHandler.sendPacket(new CommandExecutionC2SPacket("backup reset-chain", Instant.now(), 0L, ArgumentSignatureDataMap.EMPTY, acknowledgment)); + return 1; + })) + + .then(ClientCommandManager.literal("snapshot").executes((runner) -> { + Acknowledgment acknowledgment = MinecraftClient.getInstance().player.networkHandler.lastSeenMessagesCollector.collect().update(); + MinecraftClient.getInstance().player.networkHandler.sendPacket(new CommandExecutionC2SPacket("backup snapshot", Instant.now(), 0L, ArgumentSignatureDataMap.EMPTY, acknowledgment)); + return 1; + })) + + .then(ClientCommandManager.literal("cancel").executes((runner) -> { + Acknowledgment acknowledgment = MinecraftClient.getInstance().player.networkHandler.lastSeenMessagesCollector.collect().update(); + MinecraftClient.getInstance().player.networkHandler.sendPacket(new CommandExecutionC2SPacket("backup cancel", Instant.now(), 0L, ArgumentSignatureDataMap.EMPTY, acknowledgment)); + return 1; + })) + + .then(ClientCommandManager.literal("reload-client-config").executes((runner) -> { + CoreCommandSystem.reloadClientConfig((response) -> { + runner.getSource().sendFeedback(Text.of(response)); + }); + return 1; + })) + + ); + } + + +} \ No newline at end of file diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java index 92fe93fb..4bfd00a6 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java @@ -1,100 +1,127 @@ -package co.uk.mommyheather.advancedbackups.client; - -import com.mojang.blaze3d.systems.RenderSystem; - -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.render.GameRenderer; -import net.minecraft.client.resource.language.I18n; -import net.minecraft.client.toast.Toast; -import net.minecraft.client.toast.ToastManager; -import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.item.ItemStack; -import net.minecraft.item.Items; -import net.minecraft.util.Formatting; - -public class BackupToast implements Toast { - - public static boolean starting; - public static boolean started; - public static boolean failed; - public static boolean finished; - - public static int progress; - public static int max; - - public static boolean exists = false; - - private static long time; - private static boolean timeSet = false; - - public static final ItemStack stack = new ItemStack(Items.PAPER); - - @Override - public Visibility draw(DrawContext context, ToastManager manager, long startTime) { - context.drawTexture(TEXTURE, 0, 0, 0, 0, this.getWidth(), this.getHeight()); - - context.drawItemWithoutEntity(stack, 8, 8);; - - float percent = finished ? 100 : (float) progress / (float) max; - - context.fill(3, 28, 156, 29, -1); - - float f = Math.min(156, ( - 156 * percent - )); - - if (!exists) { - context.drawText(manager.getClient().textRenderer, Formatting.GREEN + I18n.translate("advancedbackups.backup_finished"), 25, 11, -11534256, false); - context.fill(3, 28, 156, 29, -10948014); - return Visibility.HIDE; - } - - String title = "You shouldn't see this!"; - - - if (starting) { - title = Formatting.GREEN + I18n.translate("advancedbackups.backup_starting"); - } - else if (started) { - title = Formatting.GREEN + I18n.translate("advancedbackups.progress", round(percent * 100)); - } - else if (failed) { - title = Formatting.RED + I18n.translate("advancedbackups.backup_failed"); - if (!timeSet) { - time = System.currentTimeMillis(); - timeSet = true; - } - } - else if (finished) { - title = Formatting.GREEN + I18n.translate("advancedbackups.backup_finished"); - if (!timeSet) { - time = System.currentTimeMillis(); - timeSet = true; - } - } - - context.drawText(manager.getClient().textRenderer, title, 25, 11, -11534256, false); - - if (timeSet && System.currentTimeMillis() >= time + 5000) { - starting = false; - started = false; - failed = false; - finished = false; - progress = 0; - max = 0; - timeSet = false; - exists = false; - return Visibility.HIDE; - } - - context.fill(3, 28, Math.max(3, (int) f), 29, -10948014); - - return Visibility.SHOW; - } - - - private static String round (float value) { - return String.format("%.1f", value); - } - -} +package co.uk.mommyheather.advancedbackups.client; + +import com.mojang.blaze3d.systems.RenderSystem; + +import co.uk.mommyheather.advancedbackups.core.config.ClientConfigManager; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.render.GameRenderer; +import net.minecraft.client.resource.language.I18n; +import net.minecraft.client.toast.Toast; +import net.minecraft.client.toast.ToastManager; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.util.Formatting; + +public class BackupToast implements Toast { + + public static boolean starting; + public static boolean started; + public static boolean failed; + public static boolean finished; + public static boolean cancelled; + + public static int progress; + public static int max; + + public static boolean exists = false; + + private static long time; + private static boolean timeSet = false; + + public static final ItemStack stack = new ItemStack(Items.PAPER); + + public static String title = "You shouldn't see this!"; + public static int textColour = 0; + + @Override + public Visibility draw(DrawContext context, ToastManager manager, long startTime) { + context.drawTexture(TEXTURE, 0, 0, 0, ClientConfigManager.darkMode.get() ? 0 : this.getHeight(), this.getWidth(), this.getHeight()); + + context.drawItemWithoutEntity(stack, 8, 8);; + + float percent = finished ? 100 : (float) progress / (float) max; + + context.fill(4, 28, 156, 29, ColourHelper.colour + (255, (int) ClientConfigManager.progressBackgroundRed.get(), (int) ClientConfigManager.progressBackgroundGreen.get(), (int) ClientConfigManager.progressBackgroundBlue.get())); + + float f = Math.min(156, ( + 156 * percent + )); + + if (!exists) { + if (title.equals(I18n.translate("advancedbackups.backup_finished"))){ + textColour = ColourHelper.colour(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); + context.drawText(manager.getClient().textRenderer, I18n.translate(title), 25, 11, textColour, false); + context.fill(4, 28, 156, 29, ColourHelper.colour + (255, (int) ClientConfigManager.progressBarRed.get(), (int) ClientConfigManager.progressBarGreen.get(), (int) ClientConfigManager.progressBarBlue.get())); + } + else { + textColour = ColourHelper.colour(255, (int) ClientConfigManager.errorTextRed.get(), (int) ClientConfigManager.errorTextGreen.get(), (int) ClientConfigManager.errorTextBlue.get()); + context.drawText(manager.getClient().textRenderer, I18n.translate(title), 25, 11, textColour, false); + } + return Visibility.HIDE; + } + + title = "You shouldn't see this!"; + + + if (starting) { + textColour = ColourHelper.colour(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); + title = I18n.translate("advancedbackups.backup_starting"); + } + else if (started) { + textColour = ColourHelper.colour(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); + title = I18n.translate("advancedbackups.progress", round(percent * 100)); + } + else if (failed) { + textColour = ColourHelper.colour(255, (int) ClientConfigManager.errorTextRed.get(), (int) ClientConfigManager.errorTextGreen.get(), (int) ClientConfigManager.errorTextBlue.get()); + title = I18n.translate("advancedbackups.backup_failed"); + if (!timeSet) { + time = System.currentTimeMillis(); + timeSet = true; + } + } + else if (finished) { + textColour = ColourHelper.colour(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); + title = I18n.translate("advancedbackups.backup_finished"); + if (!timeSet) { + time = System.currentTimeMillis(); + timeSet = true; + } + } + else if (cancelled) { + textColour = ColourHelper.colour(255, (int) ClientConfigManager.errorTextRed.get(), (int) ClientConfigManager.errorTextGreen.get(), (int) ClientConfigManager.errorTextBlue.get()); + title = I18n.translate("advancedbackups.backup_cancelled"); + if (!timeSet) { + time = System.currentTimeMillis(); + timeSet = true; + } + } + + context.drawText(manager.getClient().textRenderer, title, 25, 11, textColour, false); + + if (timeSet && System.currentTimeMillis() >= time + 5000) { + starting = false; + started = false; + failed = false; + finished = false; + progress = 0; + max = 0; + timeSet = false; + exists = false; + return Visibility.HIDE; + } + + context.fill(4, 28, Math.max(4, (int) f), 29, ColourHelper.colour + (255, (int) ClientConfigManager.progressBarRed.get(), (int) ClientConfigManager.progressBarGreen.get(), (int) ClientConfigManager.progressBarBlue.get())); + + return Visibility.SHOW; + } + + + private static String round (float value) { + return String.format("%.1f", value); + } + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java index cf5137e9..770a6deb 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java @@ -1,61 +1,78 @@ -package co.uk.mommyheather.advancedbackups.client; - -import java.util.List; - -import co.uk.mommyheather.advancedbackups.AdvancedBackups; -import co.uk.mommyheather.advancedbackups.interfaces.IClientContactor; -import co.uk.mommyheather.advancedbackups.network.NetworkHandler; -import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.network.ServerPlayerEntity; - -public class ClientContactor implements IClientContactor { - - @Override - public void backupComplete() { - MinecraftServer server = AdvancedBackups.server; - List players = server.getPlayerManager().getPlayerList(); - PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, 0, 0); - for (ServerPlayerEntity player : players) { - if (!server.isDedicated() || player.hasPermissionLevel(3)) { - NetworkHandler.sendToClient(player, packet); - } - } - } - - @Override - public void backupFailed() { - MinecraftServer server = AdvancedBackups.server; - List players = server.getPlayerManager().getPlayerList(); - PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, 0, 0); - for (ServerPlayerEntity player : players) { - if (!server.isDedicated() || player.hasPermissionLevel(3)) { - NetworkHandler.sendToClient(player, packet); - } - } - } - - @Override - public void backupProgress(int progress, int max) { - MinecraftServer server = AdvancedBackups.server; - List players = server.getPlayerManager().getPlayerList(); - PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, progress, max); - for (ServerPlayerEntity player : players) { - if (!server.isDedicated() || player.hasPermissionLevel(3)) { - NetworkHandler.sendToClient(player, packet); - } - } - } - - @Override - public void backupStarting() { - MinecraftServer server = AdvancedBackups.server; - List players = server.getPlayerManager().getPlayerList(); - PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, 0, 0); - for (ServerPlayerEntity player : players) { - if (!server.isDedicated() || player.hasPermissionLevel(3)) { - NetworkHandler.sendToClient(player, packet); - } - } - } -} +package co.uk.mommyheather.advancedbackups.client; + +import java.util.List; + +import co.uk.mommyheather.advancedbackups.AdvancedBackups; +import co.uk.mommyheather.advancedbackups.interfaces.IClientContactor; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; +import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.network.ServerPlayerEntity; + +public class ClientContactor implements IClientContactor { + + @Override + public void backupComplete() { + MinecraftServer server = AdvancedBackups.server; + List players = server.getPlayerManager().getPlayerList(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, false, 0, 0); + for (ServerPlayerEntity player : players) { + if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; + if (!server.isDedicated() || player.hasPermissionLevel(3)) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupFailed() { + MinecraftServer server = AdvancedBackups.server; + List players = server.getPlayerManager().getPlayerList(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, false, 0, 0); + for (ServerPlayerEntity player : players) { + if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; + if (!server.isDedicated() || player.hasPermissionLevel(3)) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupProgress(int progress, int max) { + MinecraftServer server = AdvancedBackups.server; + List players = server.getPlayerManager().getPlayerList(); + PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, false, progress, max); + for (ServerPlayerEntity player : players) { + if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; + if (!server.isDedicated() || player.hasPermissionLevel(3)) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupStarting() { + MinecraftServer server = AdvancedBackups.server; + List players = server.getPlayerManager().getPlayerList(); + PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, false, 0, 0); + for (ServerPlayerEntity player : players) { + if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; + if (!server.isDedicated() || player.hasPermissionLevel(3)) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupCancelled() { + MinecraftServer server = AdvancedBackups.server; + List players = server.getPlayerManager().getPlayerList(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, false, false, true, 0, 0); + for (ServerPlayerEntity player : players) { + if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; + if (!server.isDedicated() || player.hasPermissionLevel(3)) { + NetworkHandler.sendToClient(player, packet); + } + } + } +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java index 462dd7b9..42f70d89 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java @@ -1,46 +1,74 @@ -package co.uk.mommyheather.advancedbackups.client; - -import co.uk.mommyheather.advancedbackups.network.NetworkHandler; -import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; -import net.fabricmc.api.ClientModInitializer; -import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; -import net.fabricmc.fabric.api.networking.v1.PacketSender; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.network.ClientPlayNetworkHandler; -import net.minecraft.network.PacketByteBuf; - -public class ClientWrapper implements ClientModInitializer { - - @Override - public void onInitializeClient() { - ClientPlayNetworking.registerGlobalReceiver(NetworkHandler.STATUS_PACKET_ID, ClientWrapper::handle); - } - - - - - public static void handle(MinecraftClient client, ClientPlayNetworkHandler handler, PacketByteBuf buf, PacketSender responseSender) { - - PacketBackupStatus message = new PacketBackupStatus(); - message.read(buf); - - client.execute(() -> { - BackupToast.starting = message.starting; - BackupToast.started = message.started; - BackupToast.failed = message.failed; - BackupToast.finished = message.finished; - - BackupToast.progress = message.progress; - BackupToast.max = message.max; - - if (!BackupToast.exists) { - BackupToast.exists = true; - client.getToastManager().add(new BackupToast()); - } - - }); - - - } - -} +package co.uk.mommyheather.advancedbackups.client; + +import co.uk.mommyheather.advancedbackups.AdvancedBackups; +import co.uk.mommyheather.advancedbackups.core.ABCore; +import co.uk.mommyheather.advancedbackups.core.config.ClientConfigManager; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; +import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; +import co.uk.mommyheather.advancedbackups.network.PacketToastSubscribe; +import net.fabricmc.api.ClientModInitializer; +import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents; +import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents; +import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; +import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; +import net.fabricmc.fabric.api.networking.v1.PacketSender; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientPlayNetworkHandler; +import net.minecraft.network.PacketByteBuf; + +public class ClientWrapper implements ClientModInitializer { + + @Override + public void onInitializeClient() { + + ABCore.infoLogger = AdvancedBackups.infoLogger; + ABCore.warningLogger = AdvancedBackups.warningLogger; + ABCore.errorLogger = AdvancedBackups.errorLogger; + + ClientPlayNetworking.registerGlobalReceiver(NetworkHandler.STATUS_PACKET_ID, ClientWrapper::handle); + ClientLifecycleEvents.CLIENT_STARTED.register((client) -> { + ClientConfigManager.loadOrCreateConfig(); + }); + + ClientPlayConnectionEvents.JOIN.register((handler, sender, client) -> { + PacketToastSubscribe packet = new PacketToastSubscribe(ClientConfigManager.showProgress.get()); + sender.sendPacket(NetworkHandler.TOAST_SUBSCRIBE_ID, packet.write(PacketByteBufs.create())); + }); + + ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> { + AdvancedBackupsClientCommand.register(dispatcher); + + }); + + + } + + + + public static void handle(MinecraftClient client, ClientPlayNetworkHandler handler, PacketByteBuf buf, PacketSender responseSender) { + + PacketBackupStatus message = new PacketBackupStatus(); + message.read(buf); + + client.execute(() -> { + BackupToast.starting = message.starting; + BackupToast.started = message.started; + BackupToast.failed = message.failed; + BackupToast.finished = message.finished; + BackupToast.cancelled = message.cancelled; + + BackupToast.progress = message.progress; + BackupToast.max = message.max; + + if (!BackupToast.exists) { + BackupToast.exists = true; + client.getToastManager().add(new BackupToast()); + } + + }); + + + } + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ColourHelper.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ColourHelper.java new file mode 100644 index 00000000..b03dda52 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ColourHelper.java @@ -0,0 +1,31 @@ +package co.uk.mommyheather.advancedbackups.client; + +//A colour helper, loosely based on that of vanilla 1.16. +//What is the modern equivalent..? +public class ColourHelper { + + public static int alpha(int in) { + return in >>> 24; + } + + public static int red(int in) { + return in >> 16 & 255; + } + + public static int green(int in) { + return in >> 8 & 255; + } + + public static int blue(int in) { + return in & 255; + } + + public static int colour(int a, int r, int g, int b) { + return a << 24 | r << 16 | g << 8 | b; + } + + public static int colour(int a, long r, long g, long b) { + return colour(a, (int) r, (int) g, (int) b); + } + +} \ No newline at end of file diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java index 1a064957..8faf7e33 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java @@ -1,22 +1,23 @@ -package co.uk.mommyheather.advancedbackups.network; - -import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; -import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; -import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; -import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.util.Identifier; - -public class NetworkHandler { - - public static Identifier STATUS_PACKET_ID = new Identifier("advancedbackups", "backup_status"); - - - public static void sendToClient(ServerPlayerEntity player, PacketBackupStatus packet) { - - ServerPlayNetworking.send(player, STATUS_PACKET_ID, packet.write(PacketByteBufs.create())); - - } - - - -} +package co.uk.mommyheather.advancedbackups.network; + +import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; +import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; +import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.util.Identifier; + +public class NetworkHandler { + + public static Identifier STATUS_PACKET_ID = new Identifier("advancedbackups", "backup_status"); + public static final Identifier TOAST_SUBSCRIBE_ID = new Identifier("advancedbackups", "toast_subscribe"); + + + public static void sendToClient(ServerPlayerEntity player, PacketBackupStatus packet) { + + ServerPlayNetworking.send(player, STATUS_PACKET_ID, packet.write(PacketByteBufs.create())); + + } + + + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java index db47da17..633236a3 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java @@ -1,57 +1,58 @@ -package co.uk.mommyheather.advancedbackups.network; - -import co.uk.mommyheather.advancedbackups.client.BackupToast; -import net.fabricmc.fabric.api.networking.v1.PacketSender; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.network.ClientPlayNetworkHandler; -import net.minecraft.network.PacketByteBuf; - -public class PacketBackupStatus { - - public boolean starting; - public boolean started; - public boolean failed; - public boolean finished; - - public int progress; - public int max; - - - public PacketBackupStatus(boolean starting, boolean started, boolean failed, boolean finished, int progress, - int max) { - this.starting = starting; - this.started = started; - this.failed = failed; - this.finished = finished; - this.progress = progress; - this.max = max; - } - - public PacketBackupStatus() { - - } - - public void read(PacketByteBuf buf) { - starting = buf.readBoolean(); - started = buf.readBoolean(); - failed = buf.readBoolean(); - finished = buf.readBoolean(); - - progress = buf.readInt(); - max = buf.readInt(); - } - - public PacketByteBuf write(PacketByteBuf buf) { - buf.writeBoolean(starting); - buf.writeBoolean(started); - buf.writeBoolean(failed); - buf.writeBoolean(finished); - - buf.writeInt(progress); - buf.writeInt(max); - - return buf; - - } - -} +package co.uk.mommyheather.advancedbackups.network; + +import net.minecraft.network.PacketByteBuf; + +public class PacketBackupStatus { + + public boolean starting; + public boolean started; + public boolean failed; + public boolean finished; + public boolean cancelled; + + public int progress; + public int max; + + + public PacketBackupStatus(boolean starting, boolean started, boolean failed, boolean finished, boolean cancelled, int progress, + int max) { + this.starting = starting; + this.started = started; + this.failed = failed; + this.finished = finished; + this.cancelled = cancelled; + this.progress = progress; + this.max = max; + } + + public PacketBackupStatus() { + + } + + public void read(PacketByteBuf buf) { + starting = buf.readBoolean(); + started = buf.readBoolean(); + failed = buf.readBoolean(); + finished = buf.readBoolean(); + cancelled = buf.readBoolean(); + + progress = buf.readInt(); + max = buf.readInt(); + } + + public PacketByteBuf write(PacketByteBuf buf) { + buf.writeBoolean(starting); + buf.writeBoolean(started); + buf.writeBoolean(failed); + buf.writeBoolean(finished); + buf.writeBoolean(cancelled); + + buf.writeInt(progress); + buf.writeInt(max); + + return buf; + + } + + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java new file mode 100644 index 00000000..5d8b743e --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java @@ -0,0 +1,59 @@ +package co.uk.mommyheather.advancedbackups.network; + +import co.uk.mommyheather.advancedbackups.AdvancedBackups; +import net.fabricmc.fabric.api.networking.v1.PacketSender; +import net.minecraft.network.PacketByteBuf; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.network.ServerPlayNetworkHandler; +import net.minecraft.server.network.ServerPlayerEntity; + +public class PacketToastSubscribe { + + public boolean enable; + + + public PacketToastSubscribe(boolean enable) { + this.enable = enable; + } + + public PacketToastSubscribe() { + + } + + public void read(PacketByteBuf buf) { + enable = buf.readBoolean(); + } + + public PacketByteBuf write(PacketByteBuf buf) { + buf.writeBoolean(enable); + + return buf; + + } + + + public static void handle(MinecraftServer server, ServerPlayerEntity player, ServerPlayNetworkHandler handler, PacketByteBuf buf, PacketSender responseSender) { + + PacketToastSubscribe message = new PacketToastSubscribe(); + message.read(buf); + + + server.execute(() -> { + if (message.enable && !AdvancedBackups.players.contains(player.getUuidAsString())) { + AdvancedBackups.players.add(player.getUuidAsString()); + } + else if (!message.enable) { + AdvancedBackups.players.remove(player.getUuidAsString()); + } + + }); + + + + + + } + + + +} \ No newline at end of file diff --git a/src/main/resources/advancedbackups.accesswidener b/src/main/resources/advancedbackups.accesswidener new file mode 100644 index 00000000..e5e5a975 --- /dev/null +++ b/src/main/resources/advancedbackups.accesswidener @@ -0,0 +1,4 @@ +accessWidener v2 named + +#Required for commands for now, should rework this at some point +accessible field net/minecraft/client/network/ClientPlayNetworkHandler lastSeenMessagesCollector Lnet/minecraft/network/message/LastSeenMessagesCollector; \ No newline at end of file diff --git a/src/main/resources/assets/advancedbackups/lang/en_us.json b/src/main/resources/assets/advancedbackups/lang/en_us.json index cc68dae1..9a59cd17 100644 --- a/src/main/resources/assets/advancedbackups/lang/en_us.json +++ b/src/main/resources/assets/advancedbackups/lang/en_us.json @@ -1,6 +1,7 @@ -{ - "advancedbackups.backup_starting" : "Backup starting!", - "advancedbackups.progress": "Backup ongoing: %1$s%%", - "advancedbackups.backup_failed": "Backup failed!\nCheck log for more info.", - "advancedbackups.backup_finished": "Backup complete!" +{ + "advancedbackups.backup_starting" : "Backup starting!", + "advancedbackups.progress": "Backup ongoing: %1$s%%", + "advancedbackups.backup_failed": "Backup failed!\nCheck log for more info.", + "advancedbackups.backup_finished": "Backup complete!", + "advancedbackups.backup_cancelled": "Backup cancelled!" } \ No newline at end of file From 72d61fe3935976c8c8c4b37287bfbe5866ecc7b6 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Fri, 22 Mar 2024 18:37:24 +0000 Subject: [PATCH 463/580] support v3.5 changes on 1.20.2 --- build.gradle | 195 ++++++------ .../advancedbackups/AdvancedBackups.java | 298 +++++++++--------- .../AdvancedBackupsCommand.java | 104 +++--- .../client/AdvancedBackupsClientCommand.java | 62 ++++ .../advancedbackups/client/BackupToast.java | 51 ++- .../client/ClientContactor.java | 139 ++++---- .../advancedbackups/client/ClientWrapper.java | 120 ++++--- .../advancedbackups/client/ColourHelper.java | 31 ++ .../network/NetworkHandler.java | 45 +-- .../network/PacketBackupStatus.java | 115 +++---- .../network/PacketToastSubscribe.java | 59 ++++ .../resources/advancedbackups.accesswidener | 4 + .../assets/advancedbackups/lang/en_us.json | 11 +- src/main/resources/fabric.mod.json | 3 +- 14 files changed, 746 insertions(+), 491 deletions(-) create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/client/ColourHelper.java create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java create mode 100644 src/main/resources/advancedbackups.accesswidener diff --git a/build.gradle b/build.gradle index 914145b7..269aba8b 100644 --- a/build.gradle +++ b/build.gradle @@ -1,97 +1,100 @@ -plugins { - id 'fabric-loom' version '1.4-SNAPSHOT' - id 'maven-publish' -} - -group = project.maven_group -archivesBaseName = 'AdvancedBackups-' + modloaderName + "-" + minecraftVersion - - - -repositories { - // Add repositories to retrieve artifacts from in here. - // You should only use this when depending on other mods because - // Loom adds the essential maven repositories to download Minecraft and libraries from automatically. - // See https://docs.gradle.org/current/userguide/declaring_repositories.html - // for more information about repositories. -} - -configurations { - // configuration that holds jars to include in the jar - extraLibs -} - -dependencies { - // To change the versions see the gradle.properties file - minecraft "com.mojang:minecraft:${project.minecraft_version}" - mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" - modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" - - // Fabric API. This is technically optional, but you probably want it anyway. - modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" - - // Uncomment the following line to enable the deprecated Fabric API modules. - // These are included in the Fabric API production distribution and allow you to update your mod to the latest modules at a later more convenient time. - - // modImplementation "net.fabricmc.fabric-api:fabric-api-deprecated:${project.fabric_version}" - - implementation files ('advancedbackups-corelib.jar') - extraLibs files ('advancedbackups-corelib.jar') -} - -processResources { - inputs.property "version", project.version - - filesMatching("fabric.mod.json") { - expand "version": project.version - } -} - -tasks.withType(JavaCompile).configureEach { - it.options.release = 17 -} - -java { - // Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task - // if it is present. - // If you remove this line, sources will not be generated. - withSourcesJar() - - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 -} - -jar { - manifest { - attributes([ - "Main-Class" : "co.uk.mommyheather.advancedbackups.cli.AdvancedBackupsCLI", - "Specification-Title" : "advancedbackups", - "Specification-Vendor" : "mommyheather", - "Specification-Version" : "1", // We are version 1 of ourselves - "Implementation-Title" : project.name, - "Implementation-Version" : project.jar.archiveVersion, - "Implementation-Vendor" : "mommyheather", - "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ") - ]) - } - from { - configurations.extraLibs.collect { it.isDirectory() ? it : zipTree(it) } - } -} - -// configure the maven publication -publishing { - publications { - mavenJava(MavenPublication) { - from components.java - } - } - - // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing. - repositories { - // Add repositories to publish to here. - // Notice: This block does NOT have the same function as the block in the top level. - // The repositories here will be used for publishing your artifact, not for - // retrieving dependencies. - } +plugins { + id 'fabric-loom' version '1.4-SNAPSHOT' + id 'maven-publish' +} + +group = project.maven_group +archivesBaseName = 'AdvancedBackups-' + modloaderName + "-" + minecraftVersion + +loom { + accessWidenerPath = file("src/main/resources/advancedbackups.accesswidener") +} + + +repositories { + // Add repositories to retrieve artifacts from in here. + // You should only use this when depending on other mods because + // Loom adds the essential maven repositories to download Minecraft and libraries from automatically. + // See https://docs.gradle.org/current/userguide/declaring_repositories.html + // for more information about repositories. +} + +configurations { + // configuration that holds jars to include in the jar + extraLibs +} + +dependencies { + // To change the versions see the gradle.properties file + minecraft "com.mojang:minecraft:${project.minecraft_version}" + mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" + modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" + + // Fabric API. This is technically optional, but you probably want it anyway. + modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" + + // Uncomment the following line to enable the deprecated Fabric API modules. + // These are included in the Fabric API production distribution and allow you to update your mod to the latest modules at a later more convenient time. + + // modImplementation "net.fabricmc.fabric-api:fabric-api-deprecated:${project.fabric_version}" + + implementation files ('advancedbackups-corelib.jar') + extraLibs files ('advancedbackups-corelib.jar') +} + +processResources { + inputs.property "version", project.version + + filesMatching("fabric.mod.json") { + expand "version": project.version + } +} + +tasks.withType(JavaCompile).configureEach { + it.options.release = 17 +} + +java { + // Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task + // if it is present. + // If you remove this line, sources will not be generated. + withSourcesJar() + + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 +} + +jar { + manifest { + attributes([ + "Main-Class" : "co.uk.mommyheather.advancedbackups.cli.AdvancedBackupsCLI", + "Specification-Title" : "advancedbackups", + "Specification-Vendor" : "mommyheather", + "Specification-Version" : "1", // We are version 1 of ourselves + "Implementation-Title" : project.name, + "Implementation-Version" : project.jar.archiveVersion, + "Implementation-Vendor" : "mommyheather", + "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ") + ]) + } + from { + configurations.extraLibs.collect { it.isDirectory() ? it : zipTree(it) } + } +} + +// configure the maven publication +publishing { + publications { + mavenJava(MavenPublication) { + from components.java + } + } + + // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing. + repositories { + // Add repositories to publish to here. + // Notice: This block does NOT have the same function as the block in the top level. + // The repositories here will be used for publishing your artifact, not for + // retrieving dependencies. + } } \ No newline at end of file diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index b5f0e257..69adbc9f 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -1,145 +1,153 @@ -package co.uk.mommyheather.advancedbackups; - -import java.io.File; -import java.util.List; -import java.util.function.Consumer; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import co.uk.mommyheather.advancedbackups.client.ClientContactor; -import co.uk.mommyheather.advancedbackups.core.ABCore; -import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; -import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; -import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; -import net.fabricmc.api.ModInitializer; -import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; -import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; -import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; -import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; -import net.fabricmc.loader.impl.FabricLoaderImpl; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.server.world.ServerWorld; -import net.minecraft.util.WorldSavePath; - -public class AdvancedBackups implements ModInitializer { - // This logger is used to write text to the console and the log file. - // It is considered best practice to use your mod id as the logger's name. - // That way, it's clear which mod wrote info, warnings, and errors. - - public static final Logger LOGGER = LoggerFactory.getLogger("advanced-backups"); - - public static final Consumer infoLogger = LOGGER::info; - public static final Consumer warningLogger = LOGGER::warn; - public static final Consumer errorLogger = LOGGER::error; - - public static MinecraftServer server; - - @Override - public void onInitialize() { - - ServerLifecycleEvents.SERVER_STARTING.register((server) -> { - AdvancedBackups.server = server; - ABCore.worldName = server.getSaveProperties().getLevelName(); - ABCore.worldDir = server.getSavePath(WorldSavePath.ROOT); - - ABCore.disableSaving = AdvancedBackups::disableSaving; - ABCore.enableSaving = AdvancedBackups::enableSaving; - ABCore.saveOnce = AdvancedBackups::saveOnce; - - ABCore.infoLogger = infoLogger; - ABCore.warningLogger = warningLogger; - ABCore.errorLogger = errorLogger; - - ABCore.resetActivity = AdvancedBackups::resetActivity; - - ABCore.clientContactor = new ClientContactor(); - ABCore.modJar = new File(FabricLoaderImpl.INSTANCE.getModContainer("advancedbackups").get().getOrigin().getPaths().get(0).toAbsolutePath().toString()); - - - ConfigManager.loadOrCreateConfig(); - LOGGER.info("Config loaded!!"); - }); - - ServerLifecycleEvents.SERVER_STARTED.register((server) -> { - BackupWrapper.checkStartupBackups(); - }); - ServerLifecycleEvents.SERVER_STOPPING.register((server) -> { - BackupWrapper.checkShutdownBackups(); - }); - - ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> { - ABCore.setActivity(true); - }); - - CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> { - AdvancedBackupsCommand.register(dispatcher); - }); - - - ServerTickEvents.END_SERVER_TICK.register((server) -> { - BackupTimer.check(); - }); - - - - } - - public static final String savesDisabledMessage = """ - - - *************************************** - SAVING DISABLED - PREPARING FOR BACKUP! - *************************************** - """; - public static final String savesEnabledMessage = """ - - - ********************************* - SAVING ENABLED - BACKUP COMPLETE! - ********************************* - """; - public static final String saveCompleteMessage = """ - - - ************************************* - SAVE COMPLETE - PREPARING FOR BACKUP! - ************************************* - """; - - - public static void disableSaving() { - MinecraftServer server = AdvancedBackups.server; - for (ServerWorld level : server.getWorlds()) { - if (level != null && !level.savingDisabled) { - level.savingDisabled = true; - } - } - if (ConfigManager.silent.get()) return; - warningLogger.accept(savesDisabledMessage); - } - - public static void enableSaving() { - MinecraftServer server = AdvancedBackups.server; - for (ServerWorld level : server.getWorlds()) { - if (level != null && level.savingDisabled) { - level.savingDisabled = false; - } - } - if (ConfigManager.silent.get()) return; - warningLogger.accept(savesEnabledMessage); - } - - public static void saveOnce(boolean flush) { - MinecraftServer server = AdvancedBackups.server; - server.saveAll(true, flush, true); - if (ConfigManager.silent.get()) return; - warningLogger.accept(saveCompleteMessage); - } - - public static void resetActivity() { - List players = server.getPlayerManager().getPlayerList(); - ABCore.setActivity(!players.isEmpty()); - } -} +package co.uk.mommyheather.advancedbackups; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import co.uk.mommyheather.advancedbackups.client.ClientContactor; +import co.uk.mommyheather.advancedbackups.core.ABCore; +import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; +import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; +import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; +import co.uk.mommyheather.advancedbackups.network.PacketToastSubscribe; +import net.fabricmc.api.ModInitializer; +import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; +import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; +import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; +import net.fabricmc.loader.impl.FabricLoaderImpl; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.WorldSavePath; + +public class AdvancedBackups implements ModInitializer { + // This logger is used to write text to the console and the log file. + // It is considered best practice to use your mod id as the logger's name. + // That way, it's clear which mod wrote info, warnings, and errors. + + public static final Logger LOGGER = LoggerFactory.getLogger("advanced-backups"); + + public static final Consumer infoLogger = LOGGER::info; + public static final Consumer warningLogger = LOGGER::warn; + public static final Consumer errorLogger = LOGGER::error; + + public static final ArrayList players = new ArrayList<>(); + + public static MinecraftServer server; + + @Override + public void onInitialize() { + + ServerLifecycleEvents.SERVER_STARTING.register((server) -> { + AdvancedBackups.server = server; + ABCore.worldName = server.getSaveProperties().getLevelName(); + ABCore.worldDir = server.getSavePath(WorldSavePath.ROOT); + + ABCore.disableSaving = AdvancedBackups::disableSaving; + ABCore.enableSaving = AdvancedBackups::enableSaving; + ABCore.saveOnce = AdvancedBackups::saveOnce; + + ABCore.infoLogger = infoLogger; + ABCore.warningLogger = warningLogger; + ABCore.errorLogger = errorLogger; + + ABCore.resetActivity = AdvancedBackups::resetActivity; + + ABCore.clientContactor = new ClientContactor(); + ABCore.modJar = new File(FabricLoaderImpl.INSTANCE.getModContainer("advancedbackups").get().getOrigin().getPaths().get(0).toAbsolutePath().toString()); + + + ConfigManager.loadOrCreateConfig(); + LOGGER.info("Config loaded!!"); + }); + + ServerLifecycleEvents.SERVER_STARTED.register((server) -> { + BackupWrapper.checkStartupBackups(); + }); + ServerLifecycleEvents.SERVER_STOPPING.register((server) -> { + BackupWrapper.checkShutdownBackups(); + }); + + ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> { + ABCore.setActivity(true); + }); + + CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> { + AdvancedBackupsCommand.register(dispatcher); + }); + + + ServerTickEvents.END_SERVER_TICK.register((server) -> { + BackupTimer.check(); + }); + + ServerPlayNetworking.registerGlobalReceiver(NetworkHandler.TOAST_SUBSCRIBE_ID, PacketToastSubscribe::handle); + + + + } + + public static final String savesDisabledMessage = """ + + + *************************************** + SAVING DISABLED - PREPARING FOR BACKUP! + *************************************** + """; + public static final String savesEnabledMessage = """ + + + ********************************* + SAVING ENABLED - BACKUP COMPLETE! + ********************************* + """; + public static final String saveCompleteMessage = """ + + + ************************************* + SAVE COMPLETE - PREPARING FOR BACKUP! + ************************************* + """; + + + public static void disableSaving() { + MinecraftServer server = AdvancedBackups.server; + for (ServerWorld level : server.getWorlds()) { + if (level != null && !level.savingDisabled) { + level.savingDisabled = true; + } + } + if (ConfigManager.silent.get()) return; + warningLogger.accept(savesDisabledMessage); + } + + public static void enableSaving() { + MinecraftServer server = AdvancedBackups.server; + for (ServerWorld level : server.getWorlds()) { + if (level != null && level.savingDisabled) { + level.savingDisabled = false; + } + } + if (ConfigManager.silent.get()) return; + warningLogger.accept(savesEnabledMessage); + } + + public static void saveOnce(boolean flush) { + MinecraftServer server = AdvancedBackups.server; + server.saveAll(true, flush, true); + if (ConfigManager.silent.get()) return; + warningLogger.accept(saveCompleteMessage); + } + + public static void resetActivity() { + List players = server.getPlayerManager().getPlayerList(); + ABCore.setActivity(!players.isEmpty()); + } +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index 78bbdc6f..af44e177 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -1,46 +1,58 @@ -package co.uk.mommyheather.advancedbackups; - -import com.mojang.brigadier.CommandDispatcher; - -import co.uk.mommyheather.advancedbackups.core.CoreCommandSystem; -import net.minecraft.server.command.CommandManager; -import net.minecraft.server.command.ServerCommandSource; -import net.minecraft.text.Text; - -public class AdvancedBackupsCommand { - public static void register(CommandDispatcher stack) { - stack.register(CommandManager.literal("backup").requires((runner) -> { - return !AdvancedBackups.server.isDedicated() || runner.hasPermissionLevel(3); - }).then(CommandManager.literal("start").executes((runner) -> { - CoreCommandSystem.startBackup((response) -> { - runner.getSource().sendFeedback(() -> Text.of(response), true); - }); - return 1; - })) - - .then(CommandManager.literal("reload-config").executes((runner) -> { - CoreCommandSystem.reloadConfig((response) -> { - runner.getSource().sendFeedback(() -> Text.of(response), true); - }); - return 1; - })) - - .then(CommandManager.literal("reset-chain").executes((runner) -> { - CoreCommandSystem.resetChainLength((response) -> { - runner.getSource().sendFeedback(() -> Text.of(response), true); - }); - return 1; - })) - - .then(CommandManager.literal("snapshot").executes((runner) -> { - CoreCommandSystem.snapshot((response) -> { - runner.getSource().sendFeedback(() -> Text.of(response), true); - }); - return 1; - })) - - ); - } - - -} +package co.uk.mommyheather.advancedbackups; + +import com.mojang.brigadier.CommandDispatcher; + +import co.uk.mommyheather.advancedbackups.core.CoreCommandSystem; +import net.minecraft.server.command.CommandManager; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.text.Text; + +public class AdvancedBackupsCommand { + public static void register(CommandDispatcher stack) { + stack.register(CommandManager.literal("backup").requires((runner) -> { + return !AdvancedBackups.server.isDedicated() || runner.hasPermissionLevel(3); + }).then(CommandManager.literal("start").executes((runner) -> { + CoreCommandSystem.startBackup((response) -> { + runner.getSource().sendFeedback(() -> Text.of(response), true); + }); + return 1; + })) + + .then(CommandManager.literal("reload-config").executes((runner) -> { + CoreCommandSystem.reloadConfig((response) -> { + runner.getSource().sendFeedback(() -> Text.of(response), true); + }); + return 1; + })) + + .then(CommandManager.literal("reset-chain").executes((runner) -> { + CoreCommandSystem.resetChainLength((response) -> { + runner.getSource().sendFeedback(() -> Text.of(response), true); + }); + return 1; + })) + + .then(CommandManager.literal("snapshot").executes((runner) -> { + CoreCommandSystem.snapshot((response) -> { + runner.getSource().sendFeedback(() -> Text.of(response), true); + }); + return 1; + })) + + .then(CommandManager.literal("cancel").executes((runner) -> { + CoreCommandSystem.cancelBackup((response) -> { + runner.getSource().sendFeedback(() -> Text.of(response), true); + }); + return 1; + })) + + .then(CommandManager.literal("reload-client-config").executes((runner) -> { + runner.getSource().sendFeedback(() -> Text.of("This command can only be ran on the client!"), true); + return 1; + })) + + ); + } + + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java new file mode 100644 index 00000000..c6316e9e --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java @@ -0,0 +1,62 @@ +package co.uk.mommyheather.advancedbackups.client; + + +import java.time.Instant; + +import com.mojang.brigadier.CommandDispatcher; + +import co.uk.mommyheather.advancedbackups.core.CoreCommandSystem; +import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; +import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; +import net.minecraft.client.MinecraftClient; +import net.minecraft.network.message.ArgumentSignatureDataMap; +import net.minecraft.network.message.LastSeenMessageList.Acknowledgment; +import net.minecraft.network.packet.c2s.play.CommandExecutionC2SPacket; +import net.minecraft.text.Text; + +public class AdvancedBackupsClientCommand { + public static void register(CommandDispatcher dispatcher) { + dispatcher.register(ClientCommandManager.literal("backup").requires((runner) -> { + return runner.hasPermissionLevel(0); + }).then(ClientCommandManager.literal("start").executes((runner) -> { + Acknowledgment acknowledgment = MinecraftClient.getInstance().player.networkHandler.lastSeenMessagesCollector.collect().update(); + MinecraftClient.getInstance().player.networkHandler.sendPacket(new CommandExecutionC2SPacket("backup start", Instant.now(), 0L, ArgumentSignatureDataMap.EMPTY, acknowledgment)); + return 1; + })) + + .then(ClientCommandManager.literal("reload-config").executes((runner) -> { + Acknowledgment acknowledgment = MinecraftClient.getInstance().player.networkHandler.lastSeenMessagesCollector.collect().update(); + MinecraftClient.getInstance().player.networkHandler.sendPacket(new CommandExecutionC2SPacket("backup reload-config", Instant.now(), 0L, ArgumentSignatureDataMap.EMPTY, acknowledgment)); + return 1; + })) + + .then(ClientCommandManager.literal("reset-chain").executes((runner) -> { + Acknowledgment acknowledgment = MinecraftClient.getInstance().player.networkHandler.lastSeenMessagesCollector.collect().update(); + MinecraftClient.getInstance().player.networkHandler.sendPacket(new CommandExecutionC2SPacket("backup reset-chain", Instant.now(), 0L, ArgumentSignatureDataMap.EMPTY, acknowledgment)); + return 1; + })) + + .then(ClientCommandManager.literal("snapshot").executes((runner) -> { + Acknowledgment acknowledgment = MinecraftClient.getInstance().player.networkHandler.lastSeenMessagesCollector.collect().update(); + MinecraftClient.getInstance().player.networkHandler.sendPacket(new CommandExecutionC2SPacket("backup snapshot", Instant.now(), 0L, ArgumentSignatureDataMap.EMPTY, acknowledgment)); + return 1; + })) + + .then(ClientCommandManager.literal("cancel").executes((runner) -> { + Acknowledgment acknowledgment = MinecraftClient.getInstance().player.networkHandler.lastSeenMessagesCollector.collect().update(); + MinecraftClient.getInstance().player.networkHandler.sendPacket(new CommandExecutionC2SPacket("backup cancel", Instant.now(), 0L, ArgumentSignatureDataMap.EMPTY, acknowledgment)); + return 1; + })) + + .then(ClientCommandManager.literal("reload-client-config").executes((runner) -> { + CoreCommandSystem.reloadClientConfig((response) -> { + runner.getSource().sendFeedback(Text.of(response)); + }); + return 1; + })) + + ); + } + + +} \ No newline at end of file diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java index ef610dd0..5e07eee1 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java @@ -2,6 +2,7 @@ import com.mojang.blaze3d.systems.RenderSystem; +import co.uk.mommyheather.advancedbackups.core.config.ClientConfigManager; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.render.GameRenderer; import net.minecraft.client.resource.language.I18n; @@ -19,6 +20,7 @@ public class BackupToast implements Toast { public static boolean started; public static boolean failed; public static boolean finished; + public static boolean cancelled; public static int progress; public static int max; @@ -31,51 +33,75 @@ public class BackupToast implements Toast { public static final ItemStack stack = new ItemStack(Items.PAPER); private static final Identifier TEXTURE = new Identifier("toast/advancement"); + public static String title = "You shouldn't see this!"; + public static int textColour = 0; + @Override public Visibility draw(DrawContext context, ToastManager manager, long startTime) { - context.drawGuiTexture(TEXTURE, 0, 0, this.getWidth(), this.getHeight()); + context.drawGuiTexture(TEXTURE, 0, ClientConfigManager.darkMode.get() ? 0 : this.getHeight(), this.getWidth(), this.getHeight()); context.drawItemWithoutEntity(stack, 8, 8);; float percent = finished ? 100 : (float) progress / (float) max; - context.fill(3, 28, 156, 29, -1); + context.fill(4, 28, 156, 29, ColourHelper.colour + (255, (int) ClientConfigManager.progressBackgroundRed.get(), (int) ClientConfigManager.progressBackgroundGreen.get(), (int) ClientConfigManager.progressBackgroundBlue.get())); float f = Math.min(156, ( 156 * percent )); - if (!exists) { - context.drawText(manager.getClient().textRenderer, Formatting.GREEN + I18n.translate("advancedbackups.backup_finished"), 25, 11, -11534256, false); - context.fill(3, 28, 156, 29, -10948014); + if (!exists) { + if (title.equals(I18n.translate("advancedbackups.backup_finished"))){ + textColour = ColourHelper.colour(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); + context.drawText(manager.getClient().textRenderer, I18n.translate(title), 25, 11, textColour, false); + context.fill(4, 28, 156, 29, ColourHelper.colour + (255, (int) ClientConfigManager.progressBarRed.get(), (int) ClientConfigManager.progressBarGreen.get(), (int) ClientConfigManager.progressBarBlue.get())); + } + else { + textColour = ColourHelper.colour(255, (int) ClientConfigManager.errorTextRed.get(), (int) ClientConfigManager.errorTextGreen.get(), (int) ClientConfigManager.errorTextBlue.get()); + context.drawText(manager.getClient().textRenderer, I18n.translate(title), 25, 11, textColour, false); + } return Visibility.HIDE; } - String title = "You shouldn't see this!"; + title = "You shouldn't see this!"; if (starting) { - title = Formatting.GREEN + I18n.translate("advancedbackups.backup_starting"); + textColour = ColourHelper.colour(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); + title = I18n.translate("advancedbackups.backup_starting"); } else if (started) { - title = Formatting.GREEN + I18n.translate("advancedbackups.progress", round(percent * 100)); + textColour = ColourHelper.colour(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); + title = I18n.translate("advancedbackups.progress", round(percent * 100)); } else if (failed) { - title = Formatting.RED + I18n.translate("advancedbackups.backup_failed"); + textColour = ColourHelper.colour(255, (int) ClientConfigManager.errorTextRed.get(), (int) ClientConfigManager.errorTextGreen.get(), (int) ClientConfigManager.errorTextBlue.get()); + title = I18n.translate("advancedbackups.backup_failed"); if (!timeSet) { time = System.currentTimeMillis(); timeSet = true; } } else if (finished) { - title = Formatting.GREEN + I18n.translate("advancedbackups.backup_finished"); + textColour = ColourHelper.colour(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); + title = I18n.translate("advancedbackups.backup_finished"); + if (!timeSet) { + time = System.currentTimeMillis(); + timeSet = true; + } + } + else if (cancelled) { + textColour = ColourHelper.colour(255, (int) ClientConfigManager.errorTextRed.get(), (int) ClientConfigManager.errorTextGreen.get(), (int) ClientConfigManager.errorTextBlue.get()); + title = I18n.translate("advancedbackups.backup_cancelled"); if (!timeSet) { time = System.currentTimeMillis(); timeSet = true; } } - context.drawText(manager.getClient().textRenderer, title, 25, 11, -11534256, false); + context.drawText(manager.getClient().textRenderer, title, 25, 11, textColour, false); if (timeSet && System.currentTimeMillis() >= time + 5000) { starting = false; @@ -89,7 +115,8 @@ else if (finished) { return Visibility.HIDE; } - context.fill(3, 28, Math.max(3, (int) f), 29, -10948014); + context.fill(4, 28, Math.max(4, (int) f), 29, ColourHelper.colour + (255, (int) ClientConfigManager.progressBarRed.get(), (int) ClientConfigManager.progressBarGreen.get(), (int) ClientConfigManager.progressBarBlue.get())); return Visibility.SHOW; } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java index cf5137e9..770a6deb 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java @@ -1,61 +1,78 @@ -package co.uk.mommyheather.advancedbackups.client; - -import java.util.List; - -import co.uk.mommyheather.advancedbackups.AdvancedBackups; -import co.uk.mommyheather.advancedbackups.interfaces.IClientContactor; -import co.uk.mommyheather.advancedbackups.network.NetworkHandler; -import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.network.ServerPlayerEntity; - -public class ClientContactor implements IClientContactor { - - @Override - public void backupComplete() { - MinecraftServer server = AdvancedBackups.server; - List players = server.getPlayerManager().getPlayerList(); - PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, 0, 0); - for (ServerPlayerEntity player : players) { - if (!server.isDedicated() || player.hasPermissionLevel(3)) { - NetworkHandler.sendToClient(player, packet); - } - } - } - - @Override - public void backupFailed() { - MinecraftServer server = AdvancedBackups.server; - List players = server.getPlayerManager().getPlayerList(); - PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, 0, 0); - for (ServerPlayerEntity player : players) { - if (!server.isDedicated() || player.hasPermissionLevel(3)) { - NetworkHandler.sendToClient(player, packet); - } - } - } - - @Override - public void backupProgress(int progress, int max) { - MinecraftServer server = AdvancedBackups.server; - List players = server.getPlayerManager().getPlayerList(); - PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, progress, max); - for (ServerPlayerEntity player : players) { - if (!server.isDedicated() || player.hasPermissionLevel(3)) { - NetworkHandler.sendToClient(player, packet); - } - } - } - - @Override - public void backupStarting() { - MinecraftServer server = AdvancedBackups.server; - List players = server.getPlayerManager().getPlayerList(); - PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, 0, 0); - for (ServerPlayerEntity player : players) { - if (!server.isDedicated() || player.hasPermissionLevel(3)) { - NetworkHandler.sendToClient(player, packet); - } - } - } -} +package co.uk.mommyheather.advancedbackups.client; + +import java.util.List; + +import co.uk.mommyheather.advancedbackups.AdvancedBackups; +import co.uk.mommyheather.advancedbackups.interfaces.IClientContactor; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; +import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.network.ServerPlayerEntity; + +public class ClientContactor implements IClientContactor { + + @Override + public void backupComplete() { + MinecraftServer server = AdvancedBackups.server; + List players = server.getPlayerManager().getPlayerList(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, false, 0, 0); + for (ServerPlayerEntity player : players) { + if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; + if (!server.isDedicated() || player.hasPermissionLevel(3)) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupFailed() { + MinecraftServer server = AdvancedBackups.server; + List players = server.getPlayerManager().getPlayerList(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, false, 0, 0); + for (ServerPlayerEntity player : players) { + if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; + if (!server.isDedicated() || player.hasPermissionLevel(3)) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupProgress(int progress, int max) { + MinecraftServer server = AdvancedBackups.server; + List players = server.getPlayerManager().getPlayerList(); + PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, false, progress, max); + for (ServerPlayerEntity player : players) { + if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; + if (!server.isDedicated() || player.hasPermissionLevel(3)) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupStarting() { + MinecraftServer server = AdvancedBackups.server; + List players = server.getPlayerManager().getPlayerList(); + PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, false, 0, 0); + for (ServerPlayerEntity player : players) { + if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; + if (!server.isDedicated() || player.hasPermissionLevel(3)) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupCancelled() { + MinecraftServer server = AdvancedBackups.server; + List players = server.getPlayerManager().getPlayerList(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, false, false, true, 0, 0); + for (ServerPlayerEntity player : players) { + if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; + if (!server.isDedicated() || player.hasPermissionLevel(3)) { + NetworkHandler.sendToClient(player, packet); + } + } + } +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java index 462dd7b9..42f70d89 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java @@ -1,46 +1,74 @@ -package co.uk.mommyheather.advancedbackups.client; - -import co.uk.mommyheather.advancedbackups.network.NetworkHandler; -import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; -import net.fabricmc.api.ClientModInitializer; -import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; -import net.fabricmc.fabric.api.networking.v1.PacketSender; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.network.ClientPlayNetworkHandler; -import net.minecraft.network.PacketByteBuf; - -public class ClientWrapper implements ClientModInitializer { - - @Override - public void onInitializeClient() { - ClientPlayNetworking.registerGlobalReceiver(NetworkHandler.STATUS_PACKET_ID, ClientWrapper::handle); - } - - - - - public static void handle(MinecraftClient client, ClientPlayNetworkHandler handler, PacketByteBuf buf, PacketSender responseSender) { - - PacketBackupStatus message = new PacketBackupStatus(); - message.read(buf); - - client.execute(() -> { - BackupToast.starting = message.starting; - BackupToast.started = message.started; - BackupToast.failed = message.failed; - BackupToast.finished = message.finished; - - BackupToast.progress = message.progress; - BackupToast.max = message.max; - - if (!BackupToast.exists) { - BackupToast.exists = true; - client.getToastManager().add(new BackupToast()); - } - - }); - - - } - -} +package co.uk.mommyheather.advancedbackups.client; + +import co.uk.mommyheather.advancedbackups.AdvancedBackups; +import co.uk.mommyheather.advancedbackups.core.ABCore; +import co.uk.mommyheather.advancedbackups.core.config.ClientConfigManager; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; +import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; +import co.uk.mommyheather.advancedbackups.network.PacketToastSubscribe; +import net.fabricmc.api.ClientModInitializer; +import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents; +import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents; +import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; +import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; +import net.fabricmc.fabric.api.networking.v1.PacketSender; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientPlayNetworkHandler; +import net.minecraft.network.PacketByteBuf; + +public class ClientWrapper implements ClientModInitializer { + + @Override + public void onInitializeClient() { + + ABCore.infoLogger = AdvancedBackups.infoLogger; + ABCore.warningLogger = AdvancedBackups.warningLogger; + ABCore.errorLogger = AdvancedBackups.errorLogger; + + ClientPlayNetworking.registerGlobalReceiver(NetworkHandler.STATUS_PACKET_ID, ClientWrapper::handle); + ClientLifecycleEvents.CLIENT_STARTED.register((client) -> { + ClientConfigManager.loadOrCreateConfig(); + }); + + ClientPlayConnectionEvents.JOIN.register((handler, sender, client) -> { + PacketToastSubscribe packet = new PacketToastSubscribe(ClientConfigManager.showProgress.get()); + sender.sendPacket(NetworkHandler.TOAST_SUBSCRIBE_ID, packet.write(PacketByteBufs.create())); + }); + + ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> { + AdvancedBackupsClientCommand.register(dispatcher); + + }); + + + } + + + + public static void handle(MinecraftClient client, ClientPlayNetworkHandler handler, PacketByteBuf buf, PacketSender responseSender) { + + PacketBackupStatus message = new PacketBackupStatus(); + message.read(buf); + + client.execute(() -> { + BackupToast.starting = message.starting; + BackupToast.started = message.started; + BackupToast.failed = message.failed; + BackupToast.finished = message.finished; + BackupToast.cancelled = message.cancelled; + + BackupToast.progress = message.progress; + BackupToast.max = message.max; + + if (!BackupToast.exists) { + BackupToast.exists = true; + client.getToastManager().add(new BackupToast()); + } + + }); + + + } + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ColourHelper.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ColourHelper.java new file mode 100644 index 00000000..b03dda52 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ColourHelper.java @@ -0,0 +1,31 @@ +package co.uk.mommyheather.advancedbackups.client; + +//A colour helper, loosely based on that of vanilla 1.16. +//What is the modern equivalent..? +public class ColourHelper { + + public static int alpha(int in) { + return in >>> 24; + } + + public static int red(int in) { + return in >> 16 & 255; + } + + public static int green(int in) { + return in >> 8 & 255; + } + + public static int blue(int in) { + return in & 255; + } + + public static int colour(int a, int r, int g, int b) { + return a << 24 | r << 16 | g << 8 | b; + } + + public static int colour(int a, long r, long g, long b) { + return colour(a, (int) r, (int) g, (int) b); + } + +} \ No newline at end of file diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java index 1a064957..8faf7e33 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java @@ -1,22 +1,23 @@ -package co.uk.mommyheather.advancedbackups.network; - -import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; -import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; -import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; -import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.util.Identifier; - -public class NetworkHandler { - - public static Identifier STATUS_PACKET_ID = new Identifier("advancedbackups", "backup_status"); - - - public static void sendToClient(ServerPlayerEntity player, PacketBackupStatus packet) { - - ServerPlayNetworking.send(player, STATUS_PACKET_ID, packet.write(PacketByteBufs.create())); - - } - - - -} +package co.uk.mommyheather.advancedbackups.network; + +import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; +import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; +import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.util.Identifier; + +public class NetworkHandler { + + public static Identifier STATUS_PACKET_ID = new Identifier("advancedbackups", "backup_status"); + public static final Identifier TOAST_SUBSCRIBE_ID = new Identifier("advancedbackups", "toast_subscribe"); + + + public static void sendToClient(ServerPlayerEntity player, PacketBackupStatus packet) { + + ServerPlayNetworking.send(player, STATUS_PACKET_ID, packet.write(PacketByteBufs.create())); + + } + + + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java index db47da17..633236a3 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java @@ -1,57 +1,58 @@ -package co.uk.mommyheather.advancedbackups.network; - -import co.uk.mommyheather.advancedbackups.client.BackupToast; -import net.fabricmc.fabric.api.networking.v1.PacketSender; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.network.ClientPlayNetworkHandler; -import net.minecraft.network.PacketByteBuf; - -public class PacketBackupStatus { - - public boolean starting; - public boolean started; - public boolean failed; - public boolean finished; - - public int progress; - public int max; - - - public PacketBackupStatus(boolean starting, boolean started, boolean failed, boolean finished, int progress, - int max) { - this.starting = starting; - this.started = started; - this.failed = failed; - this.finished = finished; - this.progress = progress; - this.max = max; - } - - public PacketBackupStatus() { - - } - - public void read(PacketByteBuf buf) { - starting = buf.readBoolean(); - started = buf.readBoolean(); - failed = buf.readBoolean(); - finished = buf.readBoolean(); - - progress = buf.readInt(); - max = buf.readInt(); - } - - public PacketByteBuf write(PacketByteBuf buf) { - buf.writeBoolean(starting); - buf.writeBoolean(started); - buf.writeBoolean(failed); - buf.writeBoolean(finished); - - buf.writeInt(progress); - buf.writeInt(max); - - return buf; - - } - -} +package co.uk.mommyheather.advancedbackups.network; + +import net.minecraft.network.PacketByteBuf; + +public class PacketBackupStatus { + + public boolean starting; + public boolean started; + public boolean failed; + public boolean finished; + public boolean cancelled; + + public int progress; + public int max; + + + public PacketBackupStatus(boolean starting, boolean started, boolean failed, boolean finished, boolean cancelled, int progress, + int max) { + this.starting = starting; + this.started = started; + this.failed = failed; + this.finished = finished; + this.cancelled = cancelled; + this.progress = progress; + this.max = max; + } + + public PacketBackupStatus() { + + } + + public void read(PacketByteBuf buf) { + starting = buf.readBoolean(); + started = buf.readBoolean(); + failed = buf.readBoolean(); + finished = buf.readBoolean(); + cancelled = buf.readBoolean(); + + progress = buf.readInt(); + max = buf.readInt(); + } + + public PacketByteBuf write(PacketByteBuf buf) { + buf.writeBoolean(starting); + buf.writeBoolean(started); + buf.writeBoolean(failed); + buf.writeBoolean(finished); + buf.writeBoolean(cancelled); + + buf.writeInt(progress); + buf.writeInt(max); + + return buf; + + } + + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java new file mode 100644 index 00000000..5d8b743e --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java @@ -0,0 +1,59 @@ +package co.uk.mommyheather.advancedbackups.network; + +import co.uk.mommyheather.advancedbackups.AdvancedBackups; +import net.fabricmc.fabric.api.networking.v1.PacketSender; +import net.minecraft.network.PacketByteBuf; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.network.ServerPlayNetworkHandler; +import net.minecraft.server.network.ServerPlayerEntity; + +public class PacketToastSubscribe { + + public boolean enable; + + + public PacketToastSubscribe(boolean enable) { + this.enable = enable; + } + + public PacketToastSubscribe() { + + } + + public void read(PacketByteBuf buf) { + enable = buf.readBoolean(); + } + + public PacketByteBuf write(PacketByteBuf buf) { + buf.writeBoolean(enable); + + return buf; + + } + + + public static void handle(MinecraftServer server, ServerPlayerEntity player, ServerPlayNetworkHandler handler, PacketByteBuf buf, PacketSender responseSender) { + + PacketToastSubscribe message = new PacketToastSubscribe(); + message.read(buf); + + + server.execute(() -> { + if (message.enable && !AdvancedBackups.players.contains(player.getUuidAsString())) { + AdvancedBackups.players.add(player.getUuidAsString()); + } + else if (!message.enable) { + AdvancedBackups.players.remove(player.getUuidAsString()); + } + + }); + + + + + + } + + + +} \ No newline at end of file diff --git a/src/main/resources/advancedbackups.accesswidener b/src/main/resources/advancedbackups.accesswidener new file mode 100644 index 00000000..e5e5a975 --- /dev/null +++ b/src/main/resources/advancedbackups.accesswidener @@ -0,0 +1,4 @@ +accessWidener v2 named + +#Required for commands for now, should rework this at some point +accessible field net/minecraft/client/network/ClientPlayNetworkHandler lastSeenMessagesCollector Lnet/minecraft/network/message/LastSeenMessagesCollector; \ No newline at end of file diff --git a/src/main/resources/assets/advancedbackups/lang/en_us.json b/src/main/resources/assets/advancedbackups/lang/en_us.json index cc68dae1..9a59cd17 100644 --- a/src/main/resources/assets/advancedbackups/lang/en_us.json +++ b/src/main/resources/assets/advancedbackups/lang/en_us.json @@ -1,6 +1,7 @@ -{ - "advancedbackups.backup_starting" : "Backup starting!", - "advancedbackups.progress": "Backup ongoing: %1$s%%", - "advancedbackups.backup_failed": "Backup failed!\nCheck log for more info.", - "advancedbackups.backup_finished": "Backup complete!" +{ + "advancedbackups.backup_starting" : "Backup starting!", + "advancedbackups.progress": "Backup ongoing: %1$s%%", + "advancedbackups.backup_failed": "Backup failed!\nCheck log for more info.", + "advancedbackups.backup_finished": "Backup complete!", + "advancedbackups.backup_cancelled": "Backup cancelled!" } \ No newline at end of file diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 3cb4fc40..81bd0977 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -2,6 +2,7 @@ "schemaVersion": 1, "id": "advancedbackups", "version": "${version}", + "accessWidener" : "advancedbackups.accesswidener", "name": "Advanced Backups", "description": "An extremely advanced backup mod.\n\nSupports many backup types.\n\nConfig file and github contain documentation.", "authors": [ @@ -23,7 +24,7 @@ }, "depends": { "fabricloader": ">=0.14.22", - "minecraft": ">=1.20.2", + "minecraft": ">=1.20", "java": ">=17", "fabric-api": "*" } From 5bb59389aec69ca3403ea4ff8d959b3147cfb63a Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Mon, 25 Mar 2024 18:39:16 +0000 Subject: [PATCH 464/580] Support version 3.5 for forge 1.20.2 --- build.gradle | 448 +++++++++--------- .../advancedbackups/AdvancedBackups.java | 339 ++++++------- .../AdvancedBackupsCommand.java | 126 ++--- .../client/AdvancedBackupsClientCommand.java | 75 +++ .../advancedbackups/client/BackupToast.java | 225 +++++---- .../client/ClientContactor.java | 140 +++--- .../advancedbackups/client/ClientWrapper.java | 71 ++- .../advancedbackups/client/ColourHelper.java | 31 ++ .../network/NetworkHandler.java | 71 +-- .../network/PacketBackupStatus.java | 133 +++--- .../network/PacketToastSubscribe.java | 40 ++ .../resources/META-INF/accesstransformer.cfg | 1 + .../assets/advancedbackups/lang/en_us.json | 11 +- 13 files changed, 977 insertions(+), 734 deletions(-) create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/client/ColourHelper.java create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java create mode 100644 src/main/resources/META-INF/accesstransformer.cfg diff --git a/build.gradle b/build.gradle index c33446fa..d96139aa 100644 --- a/build.gradle +++ b/build.gradle @@ -1,224 +1,224 @@ -plugins { - id 'eclipse' - id 'idea' - id 'maven-publish' - id 'net.minecraftforge.gradle' version '[6.0.14,6.2)' - id 'org.spongepowered.mixin' version '0.7.+' -} - -group = mod_group_id - -base { - archivesName = 'AdvancedBackups-' + modloaderName + "-" + minecraftVersion -} - -task copyVSCodeResources (dependsOn: 'processResources', type: Copy) { - from 'build/resources' - into 'bin/' -} - -// Mojang ships Java 17 to end users in 1.18+, so your mod should target Java 17. -java.toolchain.languageVersion = JavaLanguageVersion.of(17) - -println "Java: ${System.getProperty 'java.version'}, JVM: ${System.getProperty 'java.vm.version'} (${System.getProperty 'java.vendor'}), Arch: ${System.getProperty 'os.arch'}" -minecraft { - // The mappings can be changed at any time and must be in the following format. - // Channel: Version: - // official MCVersion Official field/method names from Mojang mapping files - // parchment YYYY.MM.DD-MCVersion Open community-sourced parameter names and javadocs layered on top of official - // - // You must be aware of the Mojang license when using the 'official' or 'parchment' mappings. - // See more information here: https://github.com/NeoForged/NeoForm/blob/main/Mojang.md - // - // Parchment is an unofficial project maintained by ParchmentMC, separate from MinecraftForge - // Additional setup is needed to use their mappings: https://parchmentmc.org/docs/getting-started - // - // Use non-default mappings at your own risk. They may not always work. - // Simply re-run your setup task after changing the mappings to update your workspace. - mappings channel: mapping_channel, version: mapping_version - - // When true, this property will have all Eclipse/IntelliJ IDEA run configurations run the "prepareX" task for the given run configuration before launching the game. - // In most cases, it is not necessary to enable. - // enableEclipsePrepareRuns = true - // enableIdeaPrepareRuns = true - - // This property allows configuring Gradle's ProcessResources task(s) to run on IDE output locations before launching the game. - // It is REQUIRED to be set to true for this template to function. - // See https://docs.gradle.org/current/dsl/org.gradle.language.jvm.tasks.ProcessResources.html - copyIdeResources = true - - // When true, this property will add the folder name of all declared run configurations to generated IDE run configurations. - // The folder name can be set on a run configuration using the "folderName" property. - // By default, the folder name of a run configuration is the name of the Gradle project containing it. - // generateRunFolders = true - - // This property enables access transformers for use in development. - // They will be applied to the Minecraft artifact. - // The access transformer file can be anywhere in the project. - // However, it must be at "META-INF/accesstransformer.cfg" in the final mod jar to be loaded by Forge. - // This default location is a best practice to automatically put the file in the right place in the final jar. - // See https://docs.neoforged.net/docs/1.20.x/advanced/accesstransformers/ for more information. - - // accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg') - - // Default run configurations. - // These can be tweaked, removed, or duplicated as needed. - runs { - // applies to all the run configs below - configureEach { - workingDirectory project.file("run/${it.name}") - - // Recommended logging data for a userdev environment - // The markers can be added/remove as needed separated by commas. - // "SCAN": For mods scan. - // "REGISTRIES": For firing of registry events. - // "REGISTRYDUMP": For getting the contents of all registries. - property 'forge.logging.markers', 'REGISTRIES' - - // Recommended logging level for the console - // You can set various levels here. - // Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels - property 'forge.logging.console.level', 'debug' - - mods { - "${mod_id}" { - source sourceSets.main - } - } - } - - client { - // Comma-separated list of namespaces to load gametests from. Empty = all namespaces. - property 'forge.enabledGameTestNamespaces', mod_id - } - - server { - property 'forge.enabledGameTestNamespaces', mod_id - args '--nogui' - } - - // This run config launches GameTestServer and runs all registered gametests, then exits. - // By default, the server will crash when no gametests are provided. - // The gametest system is also enabled by default for other run configs under the /test command. - gameTestServer { - property 'forge.enabledGameTestNamespaces', mod_id - } - - data { - // example of overriding the workingDirectory set in configureEach above, uncomment if you want to use it - // workingDirectory project.file('run-data') - - // Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources. - args '--mod', mod_id, '--all', '--output', file('src/generated/resources/'), '--existing', file('src/main/resources/') - } - } -} - -// Include resources generated by data generators. -sourceSets.main.resources { srcDir 'src/generated/resources' } - -configurations { - // configuration that holds jars to include in the jar - extraLibs -} - -repositories { - // Put repositories for dependencies here - // NeoGradle automatically adds the Forge maven and Maven Central for you - - // If you have mod jar dependencies in ./libs, you can declare them as a repository like so. - // See https://docs.gradle.org/current/userguide/declaring_repositories.html#sub:flat_dir_resolver - // flatDir { - // dir 'libs' - // } -} - -dependencies { - // Specify the version of Minecraft to use. - // Any artifact can be supplied so long as it has a "userdev" classifier artifact and is a compatible patcher artifact. - // The "userdev" classifier will be requested and setup by NeoGradle. - // If the group id is "net.minecraft" and the artifact id is one of ["client", "server", "joined"], - // then special handling is done to allow a setup of a vanilla dependency without the use of an external repository. - minecraft "net.minecraftforge:forge:${minecraft_version}-${forge_version}" - - // Example mod dependency with JEI - using fg.deobf() ensures the dependency is remapped to your development mappings - // The JEI API is declared for compile time use, while the full JEI artifact is used at runtime - // compileOnly fg.deobf("mezz.jei:jei-${mc_version}-common-api:${jei_version}") - // compileOnly fg.deobf("mezz.jei:jei-${mc_version}-forge-api:${jei_version}") - // runtimeOnly fg.deobf("mezz.jei:jei-${mc_version}-forge:${jei_version}") - - // Example mod dependency using a mod jar from ./libs with a flat dir repository - // This maps to ./libs/coolmod-${mc_version}-${coolmod_version}.jar - // The group id is ignored when searching -- in this case, it is "blank" - // implementation fg.deobf("blank:coolmod-${mc_version}:${coolmod_version}") - - minecraftLibrary files ('advancedbackups-corelib.jar') - extraLibs files ('advancedbackups-corelib.jar') - - // For more info: - // http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html - // http://www.gradle.org/docs/current/userguide/dependency_management.html -} - -// This block of code expands all declared replace properties in the specified resource targets. -// A missing property will result in an error. Properties are expanded using ${} Groovy notation. -// When "copyIdeResources" is enabled, this will also run before the game launches in IDE environments. -// See https://docs.gradle.org/current/dsl/org.gradle.language.jvm.tasks.ProcessResources.html -tasks.withType(ProcessResources).configureEach { - var replaceProperties = [ - minecraft_version: minecraft_version, minecraft_version_range: minecraft_version_range, - forge_version: forge_version, forge_version_range: forge_version_range, - loader_version_range: loader_version_range, - mod_id: mod_id, mod_name: mod_name, mod_license: mod_license, mod_version: version, - mod_authors: mod_authors, mod_description: mod_description, - ] - inputs.properties replaceProperties - - filesMatching(['META-INF/mods.toml', 'pack.mcmeta']) { - expand replaceProperties + [project: project] - } -} - -// Example for how to get properties into the manifest for reading at runtime. -tasks.named('jar', Jar).configure { - manifest { - attributes([ - "Main-Class" : "co.uk.mommyheather.advancedbackups.cli.AdvancedBackupsCLI", - "Specification-Title" : "advancedbackups", - "Specification-Vendor" : "mommyheather", - "Specification-Version" : "1", // We are version 1 of ourselves - "Implementation-Title" : project.name, - "Implementation-Version" : project.jar.archiveVersion, - "Implementation-Vendor" : "mommyheather", - "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ") - ]) - } - from { - configurations.extraLibs.collect { it.isDirectory() ? it : zipTree(it) } - } - // This is the preferred method to reobfuscate your jar file - finalizedBy 'reobfJar' -} - -// However if you are in a multi-project build, dev time needs unobfed jar files, so you can delay the obfuscation until publishing by doing: -// tasks.named('publish').configure { -// dependsOn 'reobfJar' -// } - -// Example configuration to allow publishing using the maven-publish plugin -publishing { - publications { - register('mavenJava', MavenPublication) { - artifact jar - } - } - repositories { - maven { - url "file://${project.projectDir}/mcmodsrepo" - } - } -} - -tasks.withType(JavaCompile).configureEach { - options.encoding = 'UTF-8' // Use the UTF-8 charset for Java compilation -} +plugins { + id 'eclipse' + id 'idea' + id 'maven-publish' + id 'net.minecraftforge.gradle' version '[6.0.14,6.2)' + id 'org.spongepowered.mixin' version '0.7.+' +} + +group = mod_group_id + +base { + archivesName = 'AdvancedBackups-' + modloaderName + "-" + minecraftVersion +} + +task copyVSCodeResources (dependsOn: 'processResources', type: Copy) { + from 'build/resources' + into 'bin/' +} + +// Mojang ships Java 17 to end users in 1.18+, so your mod should target Java 17. +java.toolchain.languageVersion = JavaLanguageVersion.of(17) + +println "Java: ${System.getProperty 'java.version'}, JVM: ${System.getProperty 'java.vm.version'} (${System.getProperty 'java.vendor'}), Arch: ${System.getProperty 'os.arch'}" +minecraft { + // The mappings can be changed at any time and must be in the following format. + // Channel: Version: + // official MCVersion Official field/method names from Mojang mapping files + // parchment YYYY.MM.DD-MCVersion Open community-sourced parameter names and javadocs layered on top of official + // + // You must be aware of the Mojang license when using the 'official' or 'parchment' mappings. + // See more information here: https://github.com/NeoForged/NeoForm/blob/main/Mojang.md + // + // Parchment is an unofficial project maintained by ParchmentMC, separate from MinecraftForge + // Additional setup is needed to use their mappings: https://parchmentmc.org/docs/getting-started + // + // Use non-default mappings at your own risk. They may not always work. + // Simply re-run your setup task after changing the mappings to update your workspace. + mappings channel: mapping_channel, version: mapping_version + + // When true, this property will have all Eclipse/IntelliJ IDEA run configurations run the "prepareX" task for the given run configuration before launching the game. + // In most cases, it is not necessary to enable. + // enableEclipsePrepareRuns = true + // enableIdeaPrepareRuns = true + + // This property allows configuring Gradle's ProcessResources task(s) to run on IDE output locations before launching the game. + // It is REQUIRED to be set to true for this template to function. + // See https://docs.gradle.org/current/dsl/org.gradle.language.jvm.tasks.ProcessResources.html + copyIdeResources = true + + // When true, this property will add the folder name of all declared run configurations to generated IDE run configurations. + // The folder name can be set on a run configuration using the "folderName" property. + // By default, the folder name of a run configuration is the name of the Gradle project containing it. + // generateRunFolders = true + + // This property enables access transformers for use in development. + // They will be applied to the Minecraft artifact. + // The access transformer file can be anywhere in the project. + // However, it must be at "META-INF/accesstransformer.cfg" in the final mod jar to be loaded by Forge. + // This default location is a best practice to automatically put the file in the right place in the final jar. + // See https://docs.neoforged.net/docs/1.20.x/advanced/accesstransformers/ for more information. + + accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg') + + // Default run configurations. + // These can be tweaked, removed, or duplicated as needed. + runs { + // applies to all the run configs below + configureEach { + workingDirectory project.file("run/${it.name}") + + // Recommended logging data for a userdev environment + // The markers can be added/remove as needed separated by commas. + // "SCAN": For mods scan. + // "REGISTRIES": For firing of registry events. + // "REGISTRYDUMP": For getting the contents of all registries. + property 'forge.logging.markers', 'REGISTRIES' + + // Recommended logging level for the console + // You can set various levels here. + // Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels + property 'forge.logging.console.level', 'debug' + + mods { + "${mod_id}" { + source sourceSets.main + } + } + } + + client { + // Comma-separated list of namespaces to load gametests from. Empty = all namespaces. + property 'forge.enabledGameTestNamespaces', mod_id + } + + server { + property 'forge.enabledGameTestNamespaces', mod_id + args '--nogui' + } + + // This run config launches GameTestServer and runs all registered gametests, then exits. + // By default, the server will crash when no gametests are provided. + // The gametest system is also enabled by default for other run configs under the /test command. + gameTestServer { + property 'forge.enabledGameTestNamespaces', mod_id + } + + data { + // example of overriding the workingDirectory set in configureEach above, uncomment if you want to use it + // workingDirectory project.file('run-data') + + // Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources. + args '--mod', mod_id, '--all', '--output', file('src/generated/resources/'), '--existing', file('src/main/resources/') + } + } +} + +// Include resources generated by data generators. +sourceSets.main.resources { srcDir 'src/generated/resources' } + +configurations { + // configuration that holds jars to include in the jar + extraLibs +} + +repositories { + // Put repositories for dependencies here + // NeoGradle automatically adds the Forge maven and Maven Central for you + + // If you have mod jar dependencies in ./libs, you can declare them as a repository like so. + // See https://docs.gradle.org/current/userguide/declaring_repositories.html#sub:flat_dir_resolver + // flatDir { + // dir 'libs' + // } +} + +dependencies { + // Specify the version of Minecraft to use. + // Any artifact can be supplied so long as it has a "userdev" classifier artifact and is a compatible patcher artifact. + // The "userdev" classifier will be requested and setup by NeoGradle. + // If the group id is "net.minecraft" and the artifact id is one of ["client", "server", "joined"], + // then special handling is done to allow a setup of a vanilla dependency without the use of an external repository. + minecraft "net.minecraftforge:forge:${minecraft_version}-${forge_version}" + + // Example mod dependency with JEI - using fg.deobf() ensures the dependency is remapped to your development mappings + // The JEI API is declared for compile time use, while the full JEI artifact is used at runtime + // compileOnly fg.deobf("mezz.jei:jei-${mc_version}-common-api:${jei_version}") + // compileOnly fg.deobf("mezz.jei:jei-${mc_version}-forge-api:${jei_version}") + // runtimeOnly fg.deobf("mezz.jei:jei-${mc_version}-forge:${jei_version}") + + // Example mod dependency using a mod jar from ./libs with a flat dir repository + // This maps to ./libs/coolmod-${mc_version}-${coolmod_version}.jar + // The group id is ignored when searching -- in this case, it is "blank" + // implementation fg.deobf("blank:coolmod-${mc_version}:${coolmod_version}") + + minecraftLibrary files ('advancedbackups-corelib.jar') + extraLibs files ('advancedbackups-corelib.jar') + + // For more info: + // http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html + // http://www.gradle.org/docs/current/userguide/dependency_management.html +} + +// This block of code expands all declared replace properties in the specified resource targets. +// A missing property will result in an error. Properties are expanded using ${} Groovy notation. +// When "copyIdeResources" is enabled, this will also run before the game launches in IDE environments. +// See https://docs.gradle.org/current/dsl/org.gradle.language.jvm.tasks.ProcessResources.html +tasks.withType(ProcessResources).configureEach { + var replaceProperties = [ + minecraft_version: minecraft_version, minecraft_version_range: minecraft_version_range, + forge_version: forge_version, forge_version_range: forge_version_range, + loader_version_range: loader_version_range, + mod_id: mod_id, mod_name: mod_name, mod_license: mod_license, mod_version: version, + mod_authors: mod_authors, mod_description: mod_description, + ] + inputs.properties replaceProperties + + filesMatching(['META-INF/mods.toml', 'pack.mcmeta']) { + expand replaceProperties + [project: project] + } +} + +// Example for how to get properties into the manifest for reading at runtime. +tasks.named('jar', Jar).configure { + manifest { + attributes([ + "Main-Class" : "co.uk.mommyheather.advancedbackups.cli.AdvancedBackupsCLI", + "Specification-Title" : "advancedbackups", + "Specification-Vendor" : "mommyheather", + "Specification-Version" : "1", // We are version 1 of ourselves + "Implementation-Title" : project.name, + "Implementation-Version" : project.jar.archiveVersion, + "Implementation-Vendor" : "mommyheather", + "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ") + ]) + } + from { + configurations.extraLibs.collect { it.isDirectory() ? it : zipTree(it) } + } + // This is the preferred method to reobfuscate your jar file + finalizedBy 'reobfJar' +} + +// However if you are in a multi-project build, dev time needs unobfed jar files, so you can delay the obfuscation until publishing by doing: +// tasks.named('publish').configure { +// dependsOn 'reobfJar' +// } + +// Example configuration to allow publishing using the maven-publish plugin +publishing { + publications { + register('mavenJava', MavenPublication) { + artifact jar + } + } + repositories { + maven { + url "file://${project.projectDir}/mcmodsrepo" + } + } +} + +tasks.withType(JavaCompile).configureEach { + options.encoding = 'UTF-8' // Use the UTF-8 charset for Java compilation +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 681f3c26..a72d4e40 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -1,164 +1,175 @@ -package co.uk.mommyheather.advancedbackups; - -import java.util.List; -import java.util.function.Consumer; - -import org.slf4j.Logger; - -import com.mojang.logging.LogUtils; - -import co.uk.mommyheather.advancedbackups.client.ClientContactor; -import co.uk.mommyheather.advancedbackups.core.ABCore; -import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; -import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; -import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; -import co.uk.mommyheather.advancedbackups.network.NetworkHandler; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.level.storage.LevelResource; -import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.event.RegisterCommandsEvent; -import net.minecraftforge.event.TickEvent; -import net.minecraftforge.event.entity.player.PlayerEvent; -import net.minecraftforge.event.server.ServerStartedEvent; -import net.minecraftforge.event.server.ServerStartingEvent; -import net.minecraftforge.event.server.ServerStoppingEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.ModList; -import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.server.ServerLifecycleHooks; - -@Mod("advancedbackups") -public class AdvancedBackups -{ - - private static final Logger LOGGER = LogUtils.getLogger(); - - public static final Consumer infoLogger = LOGGER::info; - public static final Consumer warningLogger = LOGGER::warn; - public static final Consumer errorLogger = LOGGER::error; - - - public AdvancedBackups() - { - // Register ourselves for server and other game events we are interested in - MinecraftForge.EVENT_BUS.register(this); - NetworkHandler.register(); - } - - @SubscribeEvent - public void onServerStarting(ServerStartingEvent event) - { - // Do something when the server starts - ABCore.worldName = event.getServer().getWorldData().getLevelName(); - ABCore.worldDir = event.getServer().getWorldPath(LevelResource.ROOT); - - ABCore.disableSaving = AdvancedBackups::disableSaving; - ABCore.enableSaving = AdvancedBackups::enableSaving; - ABCore.saveOnce = AdvancedBackups::saveOnce; - - ABCore.infoLogger = infoLogger; - ABCore.warningLogger = warningLogger; - ABCore.errorLogger = errorLogger; - - ABCore.resetActivity = AdvancedBackups::resetActivity; - - - ABCore.clientContactor = new ClientContactor(); - ABCore.modJar = ModList.get().getModFileById("advancedbackups").getFile().getFilePath().toFile(); - - - ConfigManager.loadOrCreateConfig(); - LOGGER.info("Config loaded!!"); - - } - - @SubscribeEvent - public void onServerStarted(ServerStartedEvent event) { - BackupWrapper.checkStartupBackups(); - } - - @SubscribeEvent - public void onServerStopping(ServerStoppingEvent event) { - BackupWrapper.checkShutdownBackups(); - } - - - @SubscribeEvent - public void onPlayerJoined(PlayerEvent.PlayerLoggedInEvent event) { - ABCore.setActivity(true); - } - - @SubscribeEvent - public void registerCommands(RegisterCommandsEvent event){ - AdvancedBackupsCommand.register(event.getDispatcher()); - } - - - @SubscribeEvent - public void onPostTick(TickEvent.ServerTickEvent event) { - if (!event.phase.equals(TickEvent.Phase.END)) return; - BackupTimer.check(); - } - - - public static final String savesDisabledMessage = """ - - - *************************************** - SAVING DISABLED - PREPARING FOR BACKUP! - *************************************** - """; - public static final String savesEnabledMessage = """ - - - ********************************* - SAVING ENABLED - BACKUP COMPLETE! - ********************************* - """; - public static final String saveCompleteMessage = """ - - - ************************************* - SAVE COMPLETE - PREPARING FOR BACKUP! - ************************************* - """; - - - public static void disableSaving() { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - for (ServerLevel level : server.getAllLevels()) { - if (level != null && !level.noSave) { - level.noSave = true; - } - } - if (ConfigManager.silent.get()) return; - warningLogger.accept(savesDisabledMessage); - } - - public static void enableSaving() { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - for (ServerLevel level : server.getAllLevels()) { - if (level != null && level.noSave) { - level.noSave = false; - } - } - if (ConfigManager.silent.get()) return; - warningLogger.accept(savesEnabledMessage); - } - - public static void saveOnce(boolean flush) { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - server.saveEverything(true, flush, true); - if (ConfigManager.silent.get()) return; - warningLogger.accept(saveCompleteMessage); - } - - public static void resetActivity() { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - List players = server.getPlayerList().getPlayers(); - ABCore.setActivity(!players.isEmpty()); - } - -} +package co.uk.mommyheather.advancedbackups; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; + +import org.slf4j.Logger; + +import com.mojang.logging.LogUtils; + +import co.uk.mommyheather.advancedbackups.client.ClientContactor; +import co.uk.mommyheather.advancedbackups.client.ClientWrapper; +import co.uk.mommyheather.advancedbackups.core.ABCore; +import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; +import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; +import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.level.storage.LevelResource; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.RegisterCommandsEvent; +import net.minecraftforge.event.TickEvent; +import net.minecraftforge.event.entity.player.PlayerEvent; +import net.minecraftforge.event.server.ServerStartedEvent; +import net.minecraftforge.event.server.ServerStartingEvent; +import net.minecraftforge.event.server.ServerStoppingEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.ModList; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; +import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; +import net.minecraftforge.server.ServerLifecycleHooks; + +@Mod("advancedbackups") +public class AdvancedBackups +{ + + private static final Logger LOGGER = LogUtils.getLogger(); + + public static final Consumer infoLogger = LOGGER::info; + public static final Consumer warningLogger = LOGGER::warn; + public static final Consumer errorLogger = LOGGER::error; + + public static final ArrayList players = new ArrayList<>(); + + + public AdvancedBackups() + { + // Register ourselves for server and other game events we are interested in + MinecraftForge.EVENT_BUS.register(this); + FMLJavaModLoadingContext.get().getModEventBus().addListener(this::clientSetup); + NetworkHandler.register(); + + ABCore.infoLogger = infoLogger; + ABCore.warningLogger = warningLogger; + ABCore.errorLogger = errorLogger; + } + + @SubscribeEvent + public void onServerStarting(ServerStartingEvent event) + { + // Do something when the server starts + ABCore.worldName = event.getServer().getWorldData().getLevelName(); + ABCore.worldDir = event.getServer().getWorldPath(LevelResource.ROOT); + + ABCore.disableSaving = AdvancedBackups::disableSaving; + ABCore.enableSaving = AdvancedBackups::enableSaving; + ABCore.saveOnce = AdvancedBackups::saveOnce; + + ABCore.resetActivity = AdvancedBackups::resetActivity; + + + ABCore.clientContactor = new ClientContactor(); + ABCore.modJar = ModList.get().getModFileById("advancedbackups").getFile().getFilePath().toFile(); + + + ConfigManager.loadOrCreateConfig(); + LOGGER.info("Config loaded!!"); + + } + + public void clientSetup(FMLClientSetupEvent e) { + ClientWrapper.init(e); + } + + @SubscribeEvent + public void onServerStarted(ServerStartedEvent event) { + BackupWrapper.checkStartupBackups(); + } + + @SubscribeEvent + public void onServerStopping(ServerStoppingEvent event) { + BackupWrapper.checkShutdownBackups(); + } + + + @SubscribeEvent + public void onPlayerJoined(PlayerEvent.PlayerLoggedInEvent event) { + ABCore.setActivity(true); + } + + @SubscribeEvent + public void registerCommands(RegisterCommandsEvent event){ + AdvancedBackupsCommand.register(event.getDispatcher()); + } + + + @SubscribeEvent + public void onPostTick(TickEvent.ServerTickEvent event) { + if (!event.phase.equals(TickEvent.Phase.END)) return; + BackupTimer.check(); + } + + + public static final String savesDisabledMessage = """ + + + *************************************** + SAVING DISABLED - PREPARING FOR BACKUP! + *************************************** + """; + public static final String savesEnabledMessage = """ + + + ********************************* + SAVING ENABLED - BACKUP COMPLETE! + ********************************* + """; + public static final String saveCompleteMessage = """ + + + ************************************* + SAVE COMPLETE - PREPARING FOR BACKUP! + ************************************* + """; + + + public static void disableSaving() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + for (ServerLevel level : server.getAllLevels()) { + if (level != null && !level.noSave) { + level.noSave = true; + } + } + if (ConfigManager.silent.get()) return; + warningLogger.accept(savesDisabledMessage); + } + + public static void enableSaving() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + for (ServerLevel level : server.getAllLevels()) { + if (level != null && level.noSave) { + level.noSave = false; + } + } + if (ConfigManager.silent.get()) return; + warningLogger.accept(savesEnabledMessage); + } + + public static void saveOnce(boolean flush) { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + server.saveEverything(true, flush, true); + if (ConfigManager.silent.get()) return; + warningLogger.accept(saveCompleteMessage); + } + + public static void resetActivity() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + ABCore.setActivity(!players.isEmpty()); + } + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index 5fa3344e..9800b90a 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -1,55 +1,71 @@ -package co.uk.mommyheather.advancedbackups; - -import com.mojang.brigadier.CommandDispatcher; - -import co.uk.mommyheather.advancedbackups.core.CoreCommandSystem; -import net.minecraft.commands.CommandSourceStack; -import net.minecraft.commands.Commands; -import net.minecraft.network.chat.Component; -import net.minecraftforge.server.ServerLifecycleHooks; - -public class AdvancedBackupsCommand { - public static void register(CommandDispatcher stack) { - stack.register(Commands.literal("backup").requires((runner) -> { - return !ServerLifecycleHooks.getCurrentServer().isDedicatedServer() || runner.hasPermission(3); - }).then(Commands.literal("start").executes((runner) -> { - CoreCommandSystem.startBackup((response) -> { - runner.getSource().sendSuccess(() -> { - return Component.literal(response) ; - }, true); - }); - return 1; - })) - - .then(Commands.literal("reload-config").executes((runner) -> { - CoreCommandSystem.reloadConfig((response) -> { - runner.getSource().sendSuccess(() -> { - return Component.literal(response) ; - }, true); - }); - return 1; - })) - - .then(Commands.literal("reset-chain").executes((runner) -> { - CoreCommandSystem.resetChainLength((response) -> { - runner.getSource().sendSuccess(() -> { - return Component.literal(response) ; - }, true); - }); - return 1; - })) - - .then(Commands.literal("snapshot").executes((runner) -> { - CoreCommandSystem.snapshot((response) -> { - runner.getSource().sendSuccess(() -> { - return Component.literal(response) ; - }, true); - }); - return 1; - })) - - ); - } - - -} +package co.uk.mommyheather.advancedbackups; + +import com.mojang.brigadier.CommandDispatcher; + +import co.uk.mommyheather.advancedbackups.core.CoreCommandSystem; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.commands.Commands; +import net.minecraft.network.chat.Component; +import net.minecraftforge.server.ServerLifecycleHooks; + +public class AdvancedBackupsCommand { + public static void register(CommandDispatcher stack) { + stack.register(Commands.literal("backup").requires((runner) -> { + return !ServerLifecycleHooks.getCurrentServer().isDedicatedServer() || runner.hasPermission(3); + }).then(Commands.literal("start").executes((runner) -> { + CoreCommandSystem.startBackup((response) -> { + runner.getSource().sendSuccess(() -> { + return Component.literal(response) ; + }, true); + }); + return 1; + })) + + .then(Commands.literal("reload-config").executes((runner) -> { + CoreCommandSystem.reloadConfig((response) -> { + runner.getSource().sendSuccess(() -> { + return Component.literal(response) ; + }, true); + }); + return 1; + })) + + .then(Commands.literal("reset-chain").executes((runner) -> { + CoreCommandSystem.resetChainLength((response) -> { + runner.getSource().sendSuccess(() -> { + return Component.literal(response) ; + }, true); + }); + return 1; + })) + + .then(Commands.literal("snapshot").executes((runner) -> { + CoreCommandSystem.snapshot((response) -> { + runner.getSource().sendSuccess(() -> { + return Component.literal(response) ; + }, true); + }); + return 1; + })) + + .then(Commands.literal("cancel").executes((runner) -> { + CoreCommandSystem.cancelBackup((response) -> { + runner.getSource().sendSuccess(() -> { + return Component.literal(response) ; + }, true); + }); + return 1; + })) + + .then(Commands.literal("reload-client-config").executes((runner) -> { + runner.getSource().sendSuccess(() -> { + return Component.literal("This command can only be ran on the client!"); + }, true); + return 1; + })) + + ); + } + + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java new file mode 100644 index 00000000..6352c467 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java @@ -0,0 +1,75 @@ +package co.uk.mommyheather.advancedbackups.client; + +import java.time.Instant; + +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; + +import co.uk.mommyheather.advancedbackups.core.CoreCommandSystem; +import net.minecraft.client.Minecraft; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.commands.arguments.ArgumentSignatures; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.LastSeenMessages.Update; +import net.minecraft.network.protocol.game.ServerboundChatCommandPacket; +import net.minecraftforge.client.ClientCommandSourceStack; +import net.minecraftforge.server.ServerLifecycleHooks; + +public class AdvancedBackupsClientCommand { + public static void register(CommandDispatcher commandDispatcher) { + commandDispatcher.register(literal("backup").requires((runner) -> { + return !ServerLifecycleHooks.getCurrentServer().isDedicatedServer() || runner.hasPermission(3); + }).then(literal("start").executes((runner) -> { + Update acknowledgment = Minecraft.getInstance().player.connection.lastSeenMessages.generateAndApplyUpdate().update(); + Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup start", Instant.now(), 0, + ArgumentSignatures.EMPTY, acknowledgment)); + return 1; + })) + + .then(literal("reload-config").executes((runner) -> { + Update acknowledgment = Minecraft.getInstance().player.connection.lastSeenMessages.generateAndApplyUpdate().update(); + Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup reload-config", Instant.now(), 0, + ArgumentSignatures.EMPTY, acknowledgment)); + return 1; + })) + + .then(literal("reset-chain").executes((runner) -> { + Update acknowledgment = Minecraft.getInstance().player.connection.lastSeenMessages.generateAndApplyUpdate().update(); + Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup reset-chain", Instant.now(), 0, + ArgumentSignatures.EMPTY, acknowledgment)); + return 1; + })) + + .then(literal("snapshot").executes((runner) -> { + Update acknowledgment = Minecraft.getInstance().player.connection.lastSeenMessages.generateAndApplyUpdate().update(); + Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup snapshot", Instant.now(), 0, + ArgumentSignatures.EMPTY, acknowledgment)); + return 1; + })) + + .then(literal("cancel").executes((runner) -> { + Update acknowledgment = Minecraft.getInstance().player.connection.lastSeenMessages.generateAndApplyUpdate().update(); + Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup cancel", Instant.now(), 0, + ArgumentSignatures.EMPTY, acknowledgment)); + return 1; + })) + + .then(literal("reload-client-config").executes((runner) -> { + CoreCommandSystem.reloadClientConfig((response) -> { + runner.getSource().sendSuccess(() -> { + return Component.literal(response); + }, true); + }); + return 1; + })) + + ); + } + + //I'm no fan of having this here but it seems required + public static LiteralArgumentBuilder literal(String literal) { + return LiteralArgumentBuilder.literal(literal); + } + + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java index 0b02c295..a7b7414b 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java @@ -1,101 +1,124 @@ -package co.uk.mommyheather.advancedbackups.client; - -import net.minecraft.ChatFormatting; -import net.minecraft.client.gui.GuiGraphics; -import net.minecraft.client.gui.components.toasts.Toast; -import net.minecraft.client.gui.components.toasts.ToastComponent; -import net.minecraft.client.resources.language.I18n; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Items; - -public class BackupToast implements Toast { - - public static boolean starting; - public static boolean started; - public static boolean failed; - public static boolean finished; - - public static int progress; - public static int max; - - public static boolean exists = false; - - private static long time; - private static boolean timeSet = false; - - public static final ItemStack stack = new ItemStack(Items.PAPER); - private static final ResourceLocation TEXTURE = new ResourceLocation("toast/advancement"); - - - - @Override - public Visibility render(GuiGraphics graphics, ToastComponent toastGui, long delta) { - graphics.blitSprite(TEXTURE, 0, 0, this.width(), this.height()); - graphics.renderFakeItem(stack, 8, 8); - - - float percent = finished ? 100 : (float) progress / (float) max; - - graphics.fill(3, 28, 156, 29, -1); - float f = Math.min(156, ( - 156 * percent - )); - - - if (!exists) { - graphics.drawString(toastGui.getMinecraft().font, ChatFormatting.GREEN + I18n.get("advancedbackups.backup_finished"), 25, 11, -11534256); - graphics.fill(3, 28, 156, 29, -10948014); - return Visibility.HIDE; - } - - String title = "You shouldn't see this!"; - - - if (starting) { - title = ChatFormatting.GREEN + I18n.get("advancedbackups.backup_starting"); - } - else if (started) { - title = ChatFormatting.GREEN + I18n.get("advancedbackups.progress", round(percent * 100)); - } - else if (failed) { - title = ChatFormatting.RED + I18n.get("advancedbackups.backup_failed"); - if (!timeSet) { - time = System.currentTimeMillis(); - timeSet = true; - } - } - else if (finished) { - title = ChatFormatting.GREEN + I18n.get("advancedbackups.backup_finished"); - if (!timeSet) { - time = System.currentTimeMillis(); - timeSet = true; - } - } - - graphics.drawString(toastGui.getMinecraft().font, title, 25, 11, -11534256); - - if (timeSet && System.currentTimeMillis() >= time + 5000) { - starting = false; - started = false; - failed = false; - finished = false; - progress = 0; - max = 0; - timeSet = false; - exists = false; - return Visibility.HIDE; - } - - graphics.fill(3, 28, Math.max(3, (int) f), 29, -10948014); - - return Visibility.SHOW; - - } - - - private static String round (float value) { - return String.format("%.1f", value); - } - -} +package co.uk.mommyheather.advancedbackups.client; + +import co.uk.mommyheather.advancedbackups.core.config.ClientConfigManager; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.components.toasts.Toast; +import net.minecraft.client.gui.components.toasts.ToastComponent; +import net.minecraft.client.resources.language.I18n; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; + +public class BackupToast implements Toast { + + public static boolean starting; + public static boolean started; + public static boolean failed; + public static boolean finished; + public static boolean cancelled; + + public static int progress; + public static int max; + + public static boolean exists = false; + + private static long time; + private static boolean timeSet = false; + + public static final ItemStack stack = new ItemStack(Items.PAPER); + private static final ResourceLocation TEXTURE = new ResourceLocation("toast/advancement"); + + private int textColour; + private String title = "You shouldn't see this!"; + + + @Override + public Visibility render(GuiGraphics graphics, ToastComponent toastGui, long delta) { + graphics.blitSprite(TEXTURE, 0, ClientConfigManager.darkMode.get() ? 0 : this.height(), this.width(), this.height()); + graphics.renderFakeItem(stack, 8, 8); + + + float percent = finished ? 100 : (float) progress / (float) max; + + graphics.fill(4, 28, 156, 29, ColourHelper.colour + (255, (int) ClientConfigManager.progressBackgroundRed.get(), (int) ClientConfigManager.progressBackgroundGreen.get(), (int) ClientConfigManager.progressBackgroundBlue.get())); + + float f = Math.min(156, ( + 156 * percent + )); + + if (!exists) { + if (title.equals(I18n.get("advancedbackups.backup_finished"))){ + textColour = ColourHelper.colour(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); + graphics.drawString(toastGui.getMinecraft().font, I18n.get(title), 25, 11, textColour); + graphics.fill(3, 28, 156, 29, ColourHelper.colour + (255, (int) ClientConfigManager.progressBarRed.get(), (int) ClientConfigManager.progressBarGreen.get(), (int) ClientConfigManager.progressBarBlue.get())); + } + else { + textColour = ColourHelper.colour(255, (int) ClientConfigManager.errorTextRed.get(), (int) ClientConfigManager.errorTextGreen.get(), (int) ClientConfigManager.errorTextBlue.get()); + graphics.drawString(toastGui.getMinecraft().font, I18n.get(title), 25, 11, textColour); + } + return Visibility.HIDE; + } + + + if (starting) { + textColour = ColourHelper.colour(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); + title = I18n.get("advancedbackups.backup_starting"); + } + else if (started) { + textColour = ColourHelper.colour(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); + title = I18n.get("advancedbackups.progress", round(percent * 100)); + } + else if (failed) { + textColour = ColourHelper.colour(255, (int) ClientConfigManager.errorTextRed.get(), (int) ClientConfigManager.errorTextGreen.get(), (int) ClientConfigManager.errorTextBlue.get()); + title = I18n.get("advancedbackups.backup_failed"); + if (!timeSet) { + time = System.currentTimeMillis(); + timeSet = true; + } + } + else if (finished) { + textColour = ColourHelper.colour(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); + title = I18n.get("advancedbackups.backup_finished"); + if (!timeSet) { + time = System.currentTimeMillis(); + timeSet = true; + } + } + else if (cancelled) { + textColour = ColourHelper.colour(255, (int) ClientConfigManager.errorTextRed.get(), (int) ClientConfigManager.errorTextGreen.get(), (int) ClientConfigManager.errorTextBlue.get()); + title = I18n.get("advancedbackups.backup_cancelled"); + if (!timeSet) { + time = System.currentTimeMillis(); + timeSet = true; + } + } + + graphics.drawString(toastGui.getMinecraft().font, title, 25, 11, textColour); + + if (timeSet && System.currentTimeMillis() >= time + 5000) { + starting = false; + started = false; + failed = false; + finished = false; + progress = 0; + max = 0; + timeSet = false; + exists = false; + return Visibility.HIDE; + } + + graphics.fill(4, 28, Math.max(4, (int) f), 29, ColourHelper.colour + (255, (int) ClientConfigManager.progressBarRed.get(), (int) ClientConfigManager.progressBarGreen.get(), (int) ClientConfigManager.progressBarBlue.get())); + + return Visibility.SHOW; + + } + + + private static String round (float value) { + return String.format("%.1f", value); + } + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java index 2c72a8c7..69fd4eb0 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java @@ -1,61 +1,79 @@ -package co.uk.mommyheather.advancedbackups.client; - -import java.util.List; - -import co.uk.mommyheather.advancedbackups.interfaces.IClientContactor; -import co.uk.mommyheather.advancedbackups.network.NetworkHandler; -import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ServerPlayer; -import net.minecraftforge.server.ServerLifecycleHooks; - -public class ClientContactor implements IClientContactor { - - @Override - public void backupComplete() { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - List players = server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, 0, 0); - for (ServerPlayer player : players) { - if (!server.isDedicatedServer() || player.hasPermissions(3)) { - NetworkHandler.sendToClient(player, packet); - } - } - } - - @Override - public void backupFailed() { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - List players = server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, 0, 0); - for (ServerPlayer player : players) { - if (!server.isDedicatedServer() || player.hasPermissions(3)) { - NetworkHandler.sendToClient(player, packet); - } - } - } - - @Override - public void backupProgress(int progress, int max) { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - List players = server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, progress, max); - for (ServerPlayer player : players) { - if (!server.isDedicatedServer() || player.hasPermissions(3)) { - NetworkHandler.sendToClient(player, packet); - } - } - } - - @Override - public void backupStarting() { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - List players = server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, 0, 0); - for (ServerPlayer player : players) { - if (!server.isDedicatedServer() || player.hasPermissions(3)) { - NetworkHandler.sendToClient(player, packet); - } - } - } -} +package co.uk.mommyheather.advancedbackups.client; + +import java.util.List; + +import co.uk.mommyheather.advancedbackups.AdvancedBackups; +import co.uk.mommyheather.advancedbackups.interfaces.IClientContactor; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; +import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerPlayer; +import net.minecraftforge.server.ServerLifecycleHooks; + +public class ClientContactor implements IClientContactor { + + @Override + public void backupComplete() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, false, 0, 0); + for (ServerPlayer player : players) { + if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; + if (!server.isDedicatedServer() || player.hasPermissions(3)) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupFailed() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, false, 0, 0); + for (ServerPlayer player : players) { + if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; + if (!server.isDedicatedServer() || player.hasPermissions(3)) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupProgress(int progress, int max) { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, false, progress, max); + for (ServerPlayer player : players) { + if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; + if (!server.isDedicatedServer() || player.hasPermissions(3)) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupStarting() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, false, 0, 0); + for (ServerPlayer player : players) { + if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; + if (!server.isDedicatedServer() || player.hasPermissions(3)) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupCancelled() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, false, false, true, 0, 0); + for (ServerPlayer player : players) { + if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; + if (!server.isDedicatedServer() || player.hasPermissions(3)) { + NetworkHandler.sendToClient(player, packet); + } + } + } +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java index 990f3f85..a350e4a5 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java @@ -1,24 +1,47 @@ -package co.uk.mommyheather.advancedbackups.client; - -import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; -import net.minecraft.client.Minecraft; - -public class ClientWrapper { - - public static void handle(PacketBackupStatus message) { - - BackupToast.starting = message.starting; - BackupToast.started = message.started; - BackupToast.failed = message.failed; - BackupToast.finished = message.finished; - - BackupToast.progress = message.progress; - BackupToast.max = message.max; - - if (!BackupToast.exists) { - BackupToast.exists = true; - Minecraft.getInstance().getToasts().addToast(new BackupToast()); - } - } - -} +package co.uk.mommyheather.advancedbackups.client; + +import co.uk.mommyheather.advancedbackups.core.config.ClientConfigManager; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; +import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; +import co.uk.mommyheather.advancedbackups.network.PacketToastSubscribe; +import net.minecraft.client.Minecraft; +import net.minecraftforge.client.event.ClientPlayerNetworkEvent; +import net.minecraftforge.client.event.RegisterClientCommandsEvent; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; + +public class ClientWrapper { + + public static void handle(PacketBackupStatus message) { + + BackupToast.starting = message.starting; + BackupToast.started = message.started; + BackupToast.failed = message.failed; + BackupToast.finished = message.finished; + BackupToast.cancelled = message.cancelled; + + BackupToast.progress = message.progress; + BackupToast.max = message.max; + + if (!BackupToast.exists) { + BackupToast.exists = true; + Minecraft.getInstance().getToasts().addToast(new BackupToast()); + } + } + + public static void init(FMLClientSetupEvent e) { + MinecraftForge.EVENT_BUS.addListener(ClientWrapper::registerClientCommands); + MinecraftForge.EVENT_BUS.addListener(ClientWrapper::onServerConnected); + ClientConfigManager.loadOrCreateConfig(); + } + + public static void registerClientCommands(RegisterClientCommandsEvent event) { + AdvancedBackupsClientCommand.register(event.getDispatcher()); + } + + public static void onServerConnected(ClientPlayerNetworkEvent.LoggingIn event) { + NetworkHandler.INSTANCE.send(new PacketToastSubscribe(ClientConfigManager.showProgress.get()), Minecraft.getInstance().getConnection().getConnection()); + //NetworkHandler.sendToServer(new PacketToastSubscribe(ClientConfigManager.showProgress.get())); + } + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ColourHelper.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ColourHelper.java new file mode 100644 index 00000000..1392023c --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ColourHelper.java @@ -0,0 +1,31 @@ +package co.uk.mommyheather.advancedbackups.client; + +//A colour helper, loosely based on that of vanilla 1.16. +//Where is it in modern? +public class ColourHelper { + + public static int alpha(int in) { + return in >>> 24; + } + + public static int red(int in) { + return in >> 16 & 255; + } + + public static int green(int in) { + return in >> 8 & 255; + } + + public static int blue(int in) { + return in & 255; + } + + public static int colour(int a, int r, int g, int b) { + return a << 24 | r << 16 | g << 8 | b; + } + + public static int colour(int a, long r, long g, long b) { + return colour(a, (int) r, (int) g, (int) b); + } + +} \ No newline at end of file diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java index 95145741..f5c208e6 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java @@ -1,33 +1,38 @@ -package co.uk.mommyheather.advancedbackups.network; - -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.level.ServerPlayer; -import net.minecraftforge.network.ChannelBuilder; -import net.minecraftforge.network.NetworkDirection; -import net.minecraftforge.network.NetworkRegistry; -import net.minecraftforge.network.SimpleChannel; - -public class NetworkHandler { - - private static final String PROTOCOL_VERSION = "1"; - private static int id = 0; - private static int id() { - return id++; - } - - public static final SimpleChannel INSTANCE = ChannelBuilder.named(new ResourceLocation("advancedbackups", "main")).clientAcceptedVersions((status, version) -> true).simpleChannel(); - - - public static void register() { - INSTANCE.messageBuilder(PacketBackupStatus.class, id()) - .encoder(PacketBackupStatus::toBytes) - .decoder(buf -> new PacketBackupStatus(buf)) - .consumerNetworkThread(PacketBackupStatus::handle) - .add(); - } - - public static void sendToClient(ServerPlayer player, Object packet) { - INSTANCE.send(packet, player.connection.getConnection()); - } - -} +package co.uk.mommyheather.advancedbackups.network; + +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerPlayer; +import net.minecraftforge.network.ChannelBuilder; +import net.minecraftforge.network.NetworkDirection; +import net.minecraftforge.network.NetworkRegistry; +import net.minecraftforge.network.SimpleChannel; + +public class NetworkHandler { + + private static final String PROTOCOL_VERSION = "1"; + private static int id = 0; + private static int id() { + return id++; + } + + public static final SimpleChannel INSTANCE = ChannelBuilder.named(new ResourceLocation("advancedbackups", "main")).clientAcceptedVersions((status, version) -> true).simpleChannel(); + + + public static void register() { + INSTANCE.messageBuilder(PacketBackupStatus.class, id()) + .encoder(PacketBackupStatus::toBytes) + .decoder(buf -> new PacketBackupStatus(buf)) + .consumerNetworkThread(PacketBackupStatus::handle) + .add(); + INSTANCE.messageBuilder(PacketToastSubscribe.class, id()) + .encoder(PacketToastSubscribe::toBytes) + .decoder(buf -> new PacketToastSubscribe(buf)) + .consumerNetworkThread(PacketToastSubscribe::handle) + .add(); + } + + public static void sendToClient(ServerPlayer player, Object packet) { + INSTANCE.send(packet, player.connection.getConnection()); + } + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java index c5baad0e..bdfdfa80 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java @@ -1,67 +1,66 @@ -package co.uk.mommyheather.advancedbackups.network; - -import java.util.function.Supplier; - -import co.uk.mommyheather.advancedbackups.client.BackupToast; -import co.uk.mommyheather.advancedbackups.client.ClientWrapper; -import net.minecraft.client.Minecraft; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraftforge.event.network.CustomPayloadEvent; -import net.minecraftforge.fml.LogicalSide; -import net.minecraftforge.network.NetworkContext; - -public class PacketBackupStatus { - - public boolean starting; - public boolean started; - - public boolean failed; - public boolean finished; - - public int progress; - public int max; - - - public PacketBackupStatus(boolean starting, boolean started, boolean failed, boolean finished, int progress, - int max) { - this.starting = starting; - this.started = started; - this.failed = failed; - this.finished = finished; - this.progress = progress; - this.max = max; - } - - - public PacketBackupStatus(FriendlyByteBuf buf) { - starting = buf.readBoolean(); - started = buf.readBoolean(); - failed = buf.readBoolean(); - finished = buf.readBoolean(); - - progress = buf.readInt(); - max = buf.readInt(); - } - - public void toBytes(FriendlyByteBuf buf) { - buf.writeBoolean(starting); - buf.writeBoolean(started); - buf.writeBoolean(failed); - buf.writeBoolean(finished); - - buf.writeInt(progress); - buf.writeInt(max); - } - - public static boolean handle(PacketBackupStatus message, CustomPayloadEvent.Context ctx) { - ctx.enqueueWork(() -> { - if (ctx.getDirection().getReceptionSide() == LogicalSide.CLIENT) { - ClientWrapper.handle(message); - } - }); - ctx.setPacketHandled(true); - return true; - - } - -} +package co.uk.mommyheather.advancedbackups.network; + +import co.uk.mommyheather.advancedbackups.client.ClientWrapper; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraftforge.event.network.CustomPayloadEvent; +import net.minecraftforge.fml.LogicalSide; + +public class PacketBackupStatus { + + public boolean starting; + public boolean started; + + public boolean failed; + public boolean finished; + public boolean cancelled; + + public int progress; + public int max; + + + public PacketBackupStatus(boolean starting, boolean started, boolean failed, boolean finished, boolean cancelled, int progress, + int max) { + this.starting = starting; + this.started = started; + this.failed = failed; + this.finished = finished; + this.cancelled = cancelled; + this.progress = progress; + this.max = max; + } + + + public PacketBackupStatus(FriendlyByteBuf buf) { + starting = buf.readBoolean(); + started = buf.readBoolean(); + failed = buf.readBoolean(); + finished = buf.readBoolean(); + cancelled = buf.readBoolean(); + + progress = buf.readInt(); + max = buf.readInt(); + } + + public void toBytes(FriendlyByteBuf buf) { + buf.writeBoolean(starting); + buf.writeBoolean(started); + buf.writeBoolean(failed); + buf.writeBoolean(finished); + buf.writeBoolean(cancelled); + + buf.writeInt(progress); + buf.writeInt(max); + } + + public static boolean handle(PacketBackupStatus message, CustomPayloadEvent.Context ctx) { + ctx.enqueueWork(() -> { + if (ctx.getDirection().getReceptionSide() == LogicalSide.CLIENT) { + ClientWrapper.handle(message); + } + }); + ctx.setPacketHandled(true); + return true; + + } + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java new file mode 100644 index 00000000..896d0292 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java @@ -0,0 +1,40 @@ +package co.uk.mommyheather.advancedbackups.network; + +import co.uk.mommyheather.advancedbackups.AdvancedBackups; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraftforge.event.network.CustomPayloadEvent; + +public class PacketToastSubscribe { + + public boolean enable; + + + public PacketToastSubscribe(boolean enable) { + this.enable = enable; + } + + + public PacketToastSubscribe(FriendlyByteBuf buf) { + enable = buf.readBoolean(); + } + + public void toBytes(FriendlyByteBuf buf) { + buf.writeBoolean(enable); + } + + public static boolean handle(PacketToastSubscribe message, CustomPayloadEvent.Context ctx) { + ctx.enqueueWork(() -> { + if (ctx.getSender() == null) return; + if (message.enable && !AdvancedBackups.players.contains(ctx.getSender().getStringUUID())) { + AdvancedBackups.players.add(ctx.getSender().getStringUUID()); + } + else if (!message.enable) { + AdvancedBackups.players.remove(ctx.getSender().getStringUUID()); + } + }); + ctx.setPacketHandled(true); + return true; + + } + +} diff --git a/src/main/resources/META-INF/accesstransformer.cfg b/src/main/resources/META-INF/accesstransformer.cfg new file mode 100644 index 00000000..e456e70b --- /dev/null +++ b/src/main/resources/META-INF/accesstransformer.cfg @@ -0,0 +1 @@ +public net.minecraft.client.multiplayer.ClientPacketListener f_244346_ # lastSeenMessages \ No newline at end of file diff --git a/src/main/resources/assets/advancedbackups/lang/en_us.json b/src/main/resources/assets/advancedbackups/lang/en_us.json index cc68dae1..9a59cd17 100644 --- a/src/main/resources/assets/advancedbackups/lang/en_us.json +++ b/src/main/resources/assets/advancedbackups/lang/en_us.json @@ -1,6 +1,7 @@ -{ - "advancedbackups.backup_starting" : "Backup starting!", - "advancedbackups.progress": "Backup ongoing: %1$s%%", - "advancedbackups.backup_failed": "Backup failed!\nCheck log for more info.", - "advancedbackups.backup_finished": "Backup complete!" +{ + "advancedbackups.backup_starting" : "Backup starting!", + "advancedbackups.progress": "Backup ongoing: %1$s%%", + "advancedbackups.backup_failed": "Backup failed!\nCheck log for more info.", + "advancedbackups.backup_finished": "Backup complete!", + "advancedbackups.backup_cancelled": "Backup cancelled!" } \ No newline at end of file From 01f7dbca03d9ca11af30ffcbb0b8ce70bc207577 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Mon, 8 Apr 2024 17:00:46 +0100 Subject: [PATCH 465/580] #65 for 1.18 fabric --- .../client/AdvancedBackupsClientCommand.java | 101 +++++++++--------- 1 file changed, 51 insertions(+), 50 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java index 0a5ad252..57ea9b1b 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java @@ -1,50 +1,51 @@ -package co.uk.mommyheather.advancedbackups.client; - - -import co.uk.mommyheather.advancedbackups.core.CoreCommandSystem; -import net.fabricmc.fabric.api.client.command.v1.ClientCommandManager; -import net.minecraft.client.MinecraftClient; -import net.minecraft.network.packet.c2s.play.ChatMessageC2SPacket; -import net.minecraft.text.Text; - -public class AdvancedBackupsClientCommand { - public static void register() { - ClientCommandManager.DISPATCHER.register(ClientCommandManager.literal("backup").requires((runner) -> { - return runner.hasPermissionLevel(0); - }).then(ClientCommandManager.literal("start").executes((runner) -> { - MinecraftClient.getInstance().player.networkHandler.sendPacket(new ChatMessageC2SPacket("/backup start")); - return 1; - })) - - .then(ClientCommandManager.literal("reload-config").executes((runner) -> { - MinecraftClient.getInstance().player.networkHandler.sendPacket(new ChatMessageC2SPacket("/backup reload-config")); - return 1; - })) - - .then(ClientCommandManager.literal("reset-chain").executes((runner) -> { - MinecraftClient.getInstance().player.networkHandler.sendPacket(new ChatMessageC2SPacket("/backup reset-chain")); - return 1; - })) - - .then(ClientCommandManager.literal("snapshot").executes((runner) -> { - MinecraftClient.getInstance().player.networkHandler.sendPacket(new ChatMessageC2SPacket("/backup snapshot")); - return 1; - })) - - .then(ClientCommandManager.literal("cancel").executes((runner) -> { - MinecraftClient.getInstance().player.networkHandler.sendPacket(new ChatMessageC2SPacket("/backup cancel")); - return 1; - })) - - .then(ClientCommandManager.literal("reload-client-config").executes((runner) -> { - CoreCommandSystem.reloadClientConfig((response) -> { - runner.getSource().sendFeedback(Text.of(response)); - }); - return 1; - })) - - ); - } - - -} +package co.uk.mommyheather.advancedbackups.client; + + +import co.uk.mommyheather.advancedbackups.core.CoreCommandSystem; +import net.fabricmc.fabric.api.client.command.v1.ClientCommandManager; +import net.minecraft.client.MinecraftClient; +import net.minecraft.network.packet.c2s.play.ChatMessageC2SPacket; +import net.minecraft.text.Text; + +public class AdvancedBackupsClientCommand { + public static void register() { + ClientCommandManager.DISPATCHER.register(ClientCommandManager.literal("backup").requires((runner) -> { + return true; + //Originally checked for permission level 0. No point checking whether that caused the issue when just a return true here works + }).then(ClientCommandManager.literal("start").executes((runner) -> { + MinecraftClient.getInstance().player.networkHandler.sendPacket(new ChatMessageC2SPacket("/backup start")); + return 1; + })) + + .then(ClientCommandManager.literal("reload-config").executes((runner) -> { + MinecraftClient.getInstance().player.networkHandler.sendPacket(new ChatMessageC2SPacket("/backup reload-config")); + return 1; + })) + + .then(ClientCommandManager.literal("reset-chain").executes((runner) -> { + MinecraftClient.getInstance().player.networkHandler.sendPacket(new ChatMessageC2SPacket("/backup reset-chain")); + return 1; + })) + + .then(ClientCommandManager.literal("snapshot").executes((runner) -> { + MinecraftClient.getInstance().player.networkHandler.sendPacket(new ChatMessageC2SPacket("/backup snapshot")); + return 1; + })) + + .then(ClientCommandManager.literal("cancel").executes((runner) -> { + MinecraftClient.getInstance().player.networkHandler.sendPacket(new ChatMessageC2SPacket("/backup cancel")); + return 1; + })) + + .then(ClientCommandManager.literal("reload-client-config").executes((runner) -> { + CoreCommandSystem.reloadClientConfig((response) -> { + runner.getSource().sendFeedback(Text.of(response)); + }); + return 1; + })) + + ); + } + + +} From 66dea32799909410a12c56bb3a37cc8861254986 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Mon, 8 Apr 2024 17:22:12 +0100 Subject: [PATCH 466/580] # 65 on 1.19.2 fabric --- .../client/AdvancedBackupsClientCommand.java | 123 +++++++++--------- 1 file changed, 62 insertions(+), 61 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java index 75d758d0..1a268be2 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java @@ -1,62 +1,63 @@ -package co.uk.mommyheather.advancedbackups.client; - - -import java.time.Instant; - -import com.mojang.brigadier.CommandDispatcher; - -import co.uk.mommyheather.advancedbackups.core.CoreCommandSystem; -import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; -import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; -import net.minecraft.client.MinecraftClient; -import net.minecraft.network.message.ArgumentSignatureDataMap; -import net.minecraft.network.message.LastSeenMessageList.Acknowledgment; -import net.minecraft.network.packet.c2s.play.CommandExecutionC2SPacket; -import net.minecraft.text.Text; - -public class AdvancedBackupsClientCommand { - public static void register(CommandDispatcher dispatcher) { - dispatcher.register(ClientCommandManager.literal("backup").requires((runner) -> { - return runner.hasPermissionLevel(0); - }).then(ClientCommandManager.literal("start").executes((runner) -> { - Acknowledgment acknowledgment = MinecraftClient.getInstance().player.networkHandler.consumeAcknowledgment(); - MinecraftClient.getInstance().player.networkHandler.sendPacket(new CommandExecutionC2SPacket("backup start", Instant.now(), 0L, ArgumentSignatureDataMap.EMPTY, false, acknowledgment)); - return 1; - })) - - .then(ClientCommandManager.literal("reload-config").executes((runner) -> { - Acknowledgment acknowledgment = MinecraftClient.getInstance().player.networkHandler.consumeAcknowledgment(); - MinecraftClient.getInstance().player.networkHandler.sendPacket(new CommandExecutionC2SPacket("backup reload-config", Instant.now(), 0L, ArgumentSignatureDataMap.EMPTY, false, acknowledgment)); - return 1; - })) - - .then(ClientCommandManager.literal("reset-chain").executes((runner) -> { - Acknowledgment acknowledgment = MinecraftClient.getInstance().player.networkHandler.consumeAcknowledgment(); - MinecraftClient.getInstance().player.networkHandler.sendPacket(new CommandExecutionC2SPacket("backup reset-chain", Instant.now(), 0L, ArgumentSignatureDataMap.EMPTY, false, acknowledgment)); - return 1; - })) - - .then(ClientCommandManager.literal("snapshot").executes((runner) -> { - Acknowledgment acknowledgment = MinecraftClient.getInstance().player.networkHandler.consumeAcknowledgment(); - MinecraftClient.getInstance().player.networkHandler.sendPacket(new CommandExecutionC2SPacket("backup snapshot", Instant.now(), 0L, ArgumentSignatureDataMap.EMPTY, false, acknowledgment)); - return 1; - })) - - .then(ClientCommandManager.literal("cancel").executes((runner) -> { - Acknowledgment acknowledgment = MinecraftClient.getInstance().player.networkHandler.consumeAcknowledgment(); - MinecraftClient.getInstance().player.networkHandler.sendPacket(new CommandExecutionC2SPacket("backup cancel", Instant.now(), 0L, ArgumentSignatureDataMap.EMPTY, false, acknowledgment)); - return 1; - })) - - .then(ClientCommandManager.literal("reload-client-config").executes((runner) -> { - CoreCommandSystem.reloadClientConfig((response) -> { - runner.getSource().sendFeedback(Text.of(response)); - }); - return 1; - })) - - ); - } - - +package co.uk.mommyheather.advancedbackups.client; + + +import java.time.Instant; + +import com.mojang.brigadier.CommandDispatcher; + +import co.uk.mommyheather.advancedbackups.core.CoreCommandSystem; +import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; +import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; +import net.minecraft.client.MinecraftClient; +import net.minecraft.network.message.ArgumentSignatureDataMap; +import net.minecraft.network.message.LastSeenMessageList.Acknowledgment; +import net.minecraft.network.packet.c2s.play.CommandExecutionC2SPacket; +import net.minecraft.text.Text; + +public class AdvancedBackupsClientCommand { + public static void register(CommandDispatcher dispatcher) { + dispatcher.register(ClientCommandManager.literal("backup").requires((runner) -> { + //Originally checked for permission level 0, no point checking if that actually caused problems + return true; + }).then(ClientCommandManager.literal("start").executes((runner) -> { + Acknowledgment acknowledgment = MinecraftClient.getInstance().player.networkHandler.consumeAcknowledgment(); + MinecraftClient.getInstance().player.networkHandler.sendPacket(new CommandExecutionC2SPacket("backup start", Instant.now(), 0L, ArgumentSignatureDataMap.EMPTY, false, acknowledgment)); + return 1; + })) + + .then(ClientCommandManager.literal("reload-config").executes((runner) -> { + Acknowledgment acknowledgment = MinecraftClient.getInstance().player.networkHandler.consumeAcknowledgment(); + MinecraftClient.getInstance().player.networkHandler.sendPacket(new CommandExecutionC2SPacket("backup reload-config", Instant.now(), 0L, ArgumentSignatureDataMap.EMPTY, false, acknowledgment)); + return 1; + })) + + .then(ClientCommandManager.literal("reset-chain").executes((runner) -> { + Acknowledgment acknowledgment = MinecraftClient.getInstance().player.networkHandler.consumeAcknowledgment(); + MinecraftClient.getInstance().player.networkHandler.sendPacket(new CommandExecutionC2SPacket("backup reset-chain", Instant.now(), 0L, ArgumentSignatureDataMap.EMPTY, false, acknowledgment)); + return 1; + })) + + .then(ClientCommandManager.literal("snapshot").executes((runner) -> { + Acknowledgment acknowledgment = MinecraftClient.getInstance().player.networkHandler.consumeAcknowledgment(); + MinecraftClient.getInstance().player.networkHandler.sendPacket(new CommandExecutionC2SPacket("backup snapshot", Instant.now(), 0L, ArgumentSignatureDataMap.EMPTY, false, acknowledgment)); + return 1; + })) + + .then(ClientCommandManager.literal("cancel").executes((runner) -> { + Acknowledgment acknowledgment = MinecraftClient.getInstance().player.networkHandler.consumeAcknowledgment(); + MinecraftClient.getInstance().player.networkHandler.sendPacket(new CommandExecutionC2SPacket("backup cancel", Instant.now(), 0L, ArgumentSignatureDataMap.EMPTY, false, acknowledgment)); + return 1; + })) + + .then(ClientCommandManager.literal("reload-client-config").executes((runner) -> { + CoreCommandSystem.reloadClientConfig((response) -> { + runner.getSource().sendFeedback(Text.of(response)); + }); + return 1; + })) + + ); + } + + } \ No newline at end of file From 90f781188a677e321effe32d3f42a4455dc4af3b Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Mon, 8 Apr 2024 17:45:25 +0100 Subject: [PATCH 467/580] #65, forge 1.19.2 --- .../client/AdvancedBackupsClientCommand.java | 134 +++++++++--------- 1 file changed, 67 insertions(+), 67 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java index 826903a1..d78418af 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java @@ -1,67 +1,67 @@ -package co.uk.mommyheather.advancedbackups.client; - -import java.time.Instant; - -import com.mojang.brigadier.CommandDispatcher; -import com.mojang.brigadier.builder.LiteralArgumentBuilder; - -import co.uk.mommyheather.advancedbackups.core.CoreCommandSystem; -import net.minecraft.client.Minecraft; -import net.minecraft.commands.CommandSourceStack; -import net.minecraft.commands.arguments.ArgumentSignatures; -import net.minecraft.network.chat.Component; -import net.minecraft.network.protocol.game.ServerboundChatCommandPacket; -import net.minecraftforge.client.ClientCommandSourceStack; -import net.minecraftforge.server.ServerLifecycleHooks; - -public class AdvancedBackupsClientCommand { - public static void register(CommandDispatcher commandDispatcher) { - commandDispatcher.register(literal("backup").requires((runner) -> { - return !ServerLifecycleHooks.getCurrentServer().isDedicatedServer() || runner.hasPermission(3); - }).then(literal("start").executes((runner) -> { - Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup start", Instant.now(), 0, - ArgumentSignatures.EMPTY, false, Minecraft.getInstance().player.connection.generateMessageAcknowledgements())); - return 1; - })) - - .then(literal("reload-config").executes((runner) -> { - Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup reload-config", Instant.now(), 0, - ArgumentSignatures.EMPTY, false, Minecraft.getInstance().player.connection.generateMessageAcknowledgements())); - return 1; - })) - - .then(literal("reset-chain").executes((runner) -> { - Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup reset-chain", Instant.now(), 0, - ArgumentSignatures.EMPTY, false, Minecraft.getInstance().player.connection.generateMessageAcknowledgements())); - return 1; - })) - - .then(literal("snapshot").executes((runner) -> { - Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup snapshot", Instant.now(), 0, - ArgumentSignatures.EMPTY, false, Minecraft.getInstance().player.connection.generateMessageAcknowledgements())); - return 1; - })) - - .then(literal("cancel").executes((runner) -> { - Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup cancel", Instant.now(), 0, - ArgumentSignatures.EMPTY, false, Minecraft.getInstance().player.connection.generateMessageAcknowledgements())); - return 1; - })) - - .then(literal("reload-client-config").executes((runner) -> { - CoreCommandSystem.reloadClientConfig((response) -> { - runner.getSource().sendSuccess(Component.literal(response), true); - }); - return 1; - })) - - ); - } - - //I'm no fan of having this here but it seems required - public static LiteralArgumentBuilder literal(String literal) { - return LiteralArgumentBuilder.literal(literal); - } - - -} +package co.uk.mommyheather.advancedbackups.client; + +import java.time.Instant; + +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; + +import co.uk.mommyheather.advancedbackups.core.CoreCommandSystem; +import net.minecraft.client.Minecraft; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.commands.arguments.ArgumentSignatures; +import net.minecraft.network.chat.Component; +import net.minecraft.network.protocol.game.ServerboundChatCommandPacket; +import net.minecraftforge.client.ClientCommandSourceStack; +import net.minecraftforge.server.ServerLifecycleHooks; + +public class AdvancedBackupsClientCommand { + public static void register(CommandDispatcher commandDispatcher) { + commandDispatcher.register(literal("backup").requires((runner) -> { + return true; + }).then(literal("start").executes((runner) -> { + Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup start", Instant.now(), 0, + ArgumentSignatures.EMPTY, false, Minecraft.getInstance().player.connection.generateMessageAcknowledgements())); + return 1; + })) + + .then(literal("reload-config").executes((runner) -> { + Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup reload-config", Instant.now(), 0, + ArgumentSignatures.EMPTY, false, Minecraft.getInstance().player.connection.generateMessageAcknowledgements())); + return 1; + })) + + .then(literal("reset-chain").executes((runner) -> { + Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup reset-chain", Instant.now(), 0, + ArgumentSignatures.EMPTY, false, Minecraft.getInstance().player.connection.generateMessageAcknowledgements())); + return 1; + })) + + .then(literal("snapshot").executes((runner) -> { + Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup snapshot", Instant.now(), 0, + ArgumentSignatures.EMPTY, false, Minecraft.getInstance().player.connection.generateMessageAcknowledgements())); + return 1; + })) + + .then(literal("cancel").executes((runner) -> { + Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup cancel", Instant.now(), 0, + ArgumentSignatures.EMPTY, false, Minecraft.getInstance().player.connection.generateMessageAcknowledgements())); + return 1; + })) + + .then(literal("reload-client-config").executes((runner) -> { + CoreCommandSystem.reloadClientConfig((response) -> { + runner.getSource().sendSuccess(Component.literal(response), true); + }); + return 1; + })) + + ); + } + + //I'm no fan of having this here but it seems required + public static LiteralArgumentBuilder literal(String literal) { + return LiteralArgumentBuilder.literal(literal); + } + + +} From c123c1ce12f8d7387f63006918ec6ad187f946f5 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Mon, 8 Apr 2024 17:47:49 +0100 Subject: [PATCH 468/580] #65, 1.19.3 fabric --- .../client/AdvancedBackupsClientCommand.java | 122 +++++++++--------- 1 file changed, 61 insertions(+), 61 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java index f3f18fdf..78b4f858 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java @@ -1,62 +1,62 @@ -package co.uk.mommyheather.advancedbackups.client; - - -import java.time.Instant; - -import com.mojang.brigadier.CommandDispatcher; - -import co.uk.mommyheather.advancedbackups.core.CoreCommandSystem; -import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; -import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; -import net.minecraft.client.MinecraftClient; -import net.minecraft.network.message.ArgumentSignatureDataMap; -import net.minecraft.network.message.LastSeenMessageList.Acknowledgment; -import net.minecraft.network.packet.c2s.play.CommandExecutionC2SPacket; -import net.minecraft.text.Text; - -public class AdvancedBackupsClientCommand { - public static void register(CommandDispatcher dispatcher) { - dispatcher.register(ClientCommandManager.literal("backup").requires((runner) -> { - return runner.hasPermissionLevel(0); - }).then(ClientCommandManager.literal("start").executes((runner) -> { - Acknowledgment acknowledgment = MinecraftClient.getInstance().player.networkHandler.lastSeenMessagesCollector.collect().update(); - MinecraftClient.getInstance().player.networkHandler.sendPacket(new CommandExecutionC2SPacket("backup start", Instant.now(), 0L, ArgumentSignatureDataMap.EMPTY, acknowledgment)); - return 1; - })) - - .then(ClientCommandManager.literal("reload-config").executes((runner) -> { - Acknowledgment acknowledgment = MinecraftClient.getInstance().player.networkHandler.lastSeenMessagesCollector.collect().update(); - MinecraftClient.getInstance().player.networkHandler.sendPacket(new CommandExecutionC2SPacket("backup reload-config", Instant.now(), 0L, ArgumentSignatureDataMap.EMPTY, acknowledgment)); - return 1; - })) - - .then(ClientCommandManager.literal("reset-chain").executes((runner) -> { - Acknowledgment acknowledgment = MinecraftClient.getInstance().player.networkHandler.lastSeenMessagesCollector.collect().update(); - MinecraftClient.getInstance().player.networkHandler.sendPacket(new CommandExecutionC2SPacket("backup reset-chain", Instant.now(), 0L, ArgumentSignatureDataMap.EMPTY, acknowledgment)); - return 1; - })) - - .then(ClientCommandManager.literal("snapshot").executes((runner) -> { - Acknowledgment acknowledgment = MinecraftClient.getInstance().player.networkHandler.lastSeenMessagesCollector.collect().update(); - MinecraftClient.getInstance().player.networkHandler.sendPacket(new CommandExecutionC2SPacket("backup snapshot", Instant.now(), 0L, ArgumentSignatureDataMap.EMPTY, acknowledgment)); - return 1; - })) - - .then(ClientCommandManager.literal("cancel").executes((runner) -> { - Acknowledgment acknowledgment = MinecraftClient.getInstance().player.networkHandler.lastSeenMessagesCollector.collect().update(); - MinecraftClient.getInstance().player.networkHandler.sendPacket(new CommandExecutionC2SPacket("backup cancel", Instant.now(), 0L, ArgumentSignatureDataMap.EMPTY, acknowledgment)); - return 1; - })) - - .then(ClientCommandManager.literal("reload-client-config").executes((runner) -> { - CoreCommandSystem.reloadClientConfig((response) -> { - runner.getSource().sendFeedback(Text.of(response)); - }); - return 1; - })) - - ); - } - - +package co.uk.mommyheather.advancedbackups.client; + + +import java.time.Instant; + +import com.mojang.brigadier.CommandDispatcher; + +import co.uk.mommyheather.advancedbackups.core.CoreCommandSystem; +import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; +import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; +import net.minecraft.client.MinecraftClient; +import net.minecraft.network.message.ArgumentSignatureDataMap; +import net.minecraft.network.message.LastSeenMessageList.Acknowledgment; +import net.minecraft.network.packet.c2s.play.CommandExecutionC2SPacket; +import net.minecraft.text.Text; + +public class AdvancedBackupsClientCommand { + public static void register(CommandDispatcher dispatcher) { + dispatcher.register(ClientCommandManager.literal("backup").requires((runner) -> { + return true; + }).then(ClientCommandManager.literal("start").executes((runner) -> { + Acknowledgment acknowledgment = MinecraftClient.getInstance().player.networkHandler.lastSeenMessagesCollector.collect().update(); + MinecraftClient.getInstance().player.networkHandler.sendPacket(new CommandExecutionC2SPacket("backup start", Instant.now(), 0L, ArgumentSignatureDataMap.EMPTY, acknowledgment)); + return 1; + })) + + .then(ClientCommandManager.literal("reload-config").executes((runner) -> { + Acknowledgment acknowledgment = MinecraftClient.getInstance().player.networkHandler.lastSeenMessagesCollector.collect().update(); + MinecraftClient.getInstance().player.networkHandler.sendPacket(new CommandExecutionC2SPacket("backup reload-config", Instant.now(), 0L, ArgumentSignatureDataMap.EMPTY, acknowledgment)); + return 1; + })) + + .then(ClientCommandManager.literal("reset-chain").executes((runner) -> { + Acknowledgment acknowledgment = MinecraftClient.getInstance().player.networkHandler.lastSeenMessagesCollector.collect().update(); + MinecraftClient.getInstance().player.networkHandler.sendPacket(new CommandExecutionC2SPacket("backup reset-chain", Instant.now(), 0L, ArgumentSignatureDataMap.EMPTY, acknowledgment)); + return 1; + })) + + .then(ClientCommandManager.literal("snapshot").executes((runner) -> { + Acknowledgment acknowledgment = MinecraftClient.getInstance().player.networkHandler.lastSeenMessagesCollector.collect().update(); + MinecraftClient.getInstance().player.networkHandler.sendPacket(new CommandExecutionC2SPacket("backup snapshot", Instant.now(), 0L, ArgumentSignatureDataMap.EMPTY, acknowledgment)); + return 1; + })) + + .then(ClientCommandManager.literal("cancel").executes((runner) -> { + Acknowledgment acknowledgment = MinecraftClient.getInstance().player.networkHandler.lastSeenMessagesCollector.collect().update(); + MinecraftClient.getInstance().player.networkHandler.sendPacket(new CommandExecutionC2SPacket("backup cancel", Instant.now(), 0L, ArgumentSignatureDataMap.EMPTY, acknowledgment)); + return 1; + })) + + .then(ClientCommandManager.literal("reload-client-config").executes((runner) -> { + CoreCommandSystem.reloadClientConfig((response) -> { + runner.getSource().sendFeedback(Text.of(response)); + }); + return 1; + })) + + ); + } + + } \ No newline at end of file From bab437d422d951e4b4c43c7e91b8bbc8705924cb Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Mon, 8 Apr 2024 17:53:31 +0100 Subject: [PATCH 469/580] #65 on forge 1.20 --- .../advancedbackups/client/AdvancedBackupsClientCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java index 6352c467..c03423b6 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java @@ -18,7 +18,7 @@ public class AdvancedBackupsClientCommand { public static void register(CommandDispatcher commandDispatcher) { commandDispatcher.register(literal("backup").requires((runner) -> { - return !ServerLifecycleHooks.getCurrentServer().isDedicatedServer() || runner.hasPermission(3); + return true; //no point fucking with the check }).then(literal("start").executes((runner) -> { Update acknowledgment = Minecraft.getInstance().player.connection.lastSeenMessages.generateAndApplyUpdate().update(); Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup start", Instant.now(), 0, From ddc4b65f03cc83ad7a72d3248290725755dba1a4 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Mon, 8 Apr 2024 18:00:53 +0100 Subject: [PATCH 470/580] #65, for forge 1.19.3 --- .../client/AdvancedBackupsClientCommand.java | 146 +++++++++--------- 1 file changed, 73 insertions(+), 73 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java index b1e6038c..87e34b08 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java @@ -1,73 +1,73 @@ -package co.uk.mommyheather.advancedbackups.client; - -import java.time.Instant; - -import com.mojang.brigadier.CommandDispatcher; -import com.mojang.brigadier.builder.LiteralArgumentBuilder; - -import co.uk.mommyheather.advancedbackups.core.CoreCommandSystem; -import net.minecraft.client.Minecraft; -import net.minecraft.commands.CommandSourceStack; -import net.minecraft.commands.arguments.ArgumentSignatures; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.LastSeenMessages.Update; -import net.minecraft.network.protocol.game.ServerboundChatCommandPacket; -import net.minecraftforge.client.ClientCommandSourceStack; -import net.minecraftforge.server.ServerLifecycleHooks; - -public class AdvancedBackupsClientCommand { - public static void register(CommandDispatcher commandDispatcher) { - commandDispatcher.register(literal("backup").requires((runner) -> { - return !ServerLifecycleHooks.getCurrentServer().isDedicatedServer() || runner.hasPermission(3); - }).then(literal("start").executes((runner) -> { - Update acknowledgment = Minecraft.getInstance().player.connection.lastSeenMessages.generateAndApplyUpdate().update(); - Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup start", Instant.now(), 0, - ArgumentSignatures.EMPTY, acknowledgment)); - return 1; - })) - - .then(literal("reload-config").executes((runner) -> { - Update acknowledgment = Minecraft.getInstance().player.connection.lastSeenMessages.generateAndApplyUpdate().update(); - Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup reload-config", Instant.now(), 0, - ArgumentSignatures.EMPTY, acknowledgment)); - return 1; - })) - - .then(literal("reset-chain").executes((runner) -> { - Update acknowledgment = Minecraft.getInstance().player.connection.lastSeenMessages.generateAndApplyUpdate().update(); - Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup reset-chain", Instant.now(), 0, - ArgumentSignatures.EMPTY, acknowledgment)); - return 1; - })) - - .then(literal("snapshot").executes((runner) -> { - Update acknowledgment = Minecraft.getInstance().player.connection.lastSeenMessages.generateAndApplyUpdate().update(); - Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup snapshot", Instant.now(), 0, - ArgumentSignatures.EMPTY, acknowledgment)); - return 1; - })) - - .then(literal("cancel").executes((runner) -> { - Update acknowledgment = Minecraft.getInstance().player.connection.lastSeenMessages.generateAndApplyUpdate().update(); - Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup cancel", Instant.now(), 0, - ArgumentSignatures.EMPTY, acknowledgment)); - return 1; - })) - - .then(literal("reload-client-config").executes((runner) -> { - CoreCommandSystem.reloadClientConfig((response) -> { - runner.getSource().sendSuccess(Component.literal(response), true); - }); - return 1; - })) - - ); - } - - //I'm no fan of having this here but it seems required - public static LiteralArgumentBuilder literal(String literal) { - return LiteralArgumentBuilder.literal(literal); - } - - -} +package co.uk.mommyheather.advancedbackups.client; + +import java.time.Instant; + +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; + +import co.uk.mommyheather.advancedbackups.core.CoreCommandSystem; +import net.minecraft.client.Minecraft; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.commands.arguments.ArgumentSignatures; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.LastSeenMessages.Update; +import net.minecraft.network.protocol.game.ServerboundChatCommandPacket; +import net.minecraftforge.client.ClientCommandSourceStack; +import net.minecraftforge.server.ServerLifecycleHooks; + +public class AdvancedBackupsClientCommand { + public static void register(CommandDispatcher commandDispatcher) { + commandDispatcher.register(literal("backup").requires((runner) -> { + return true; + }).then(literal("start").executes((runner) -> { + Update acknowledgment = Minecraft.getInstance().player.connection.lastSeenMessages.generateAndApplyUpdate().update(); + Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup start", Instant.now(), 0, + ArgumentSignatures.EMPTY, acknowledgment)); + return 1; + })) + + .then(literal("reload-config").executes((runner) -> { + Update acknowledgment = Minecraft.getInstance().player.connection.lastSeenMessages.generateAndApplyUpdate().update(); + Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup reload-config", Instant.now(), 0, + ArgumentSignatures.EMPTY, acknowledgment)); + return 1; + })) + + .then(literal("reset-chain").executes((runner) -> { + Update acknowledgment = Minecraft.getInstance().player.connection.lastSeenMessages.generateAndApplyUpdate().update(); + Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup reset-chain", Instant.now(), 0, + ArgumentSignatures.EMPTY, acknowledgment)); + return 1; + })) + + .then(literal("snapshot").executes((runner) -> { + Update acknowledgment = Minecraft.getInstance().player.connection.lastSeenMessages.generateAndApplyUpdate().update(); + Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup snapshot", Instant.now(), 0, + ArgumentSignatures.EMPTY, acknowledgment)); + return 1; + })) + + .then(literal("cancel").executes((runner) -> { + Update acknowledgment = Minecraft.getInstance().player.connection.lastSeenMessages.generateAndApplyUpdate().update(); + Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup cancel", Instant.now(), 0, + ArgumentSignatures.EMPTY, acknowledgment)); + return 1; + })) + + .then(literal("reload-client-config").executes((runner) -> { + CoreCommandSystem.reloadClientConfig((response) -> { + runner.getSource().sendSuccess(Component.literal(response), true); + }); + return 1; + })) + + ); + } + + //I'm no fan of having this here but it seems required + public static LiteralArgumentBuilder literal(String literal) { + return LiteralArgumentBuilder.literal(literal); + } + + +} From 3b946d0725b5d25feb5014961b5987aa1e99f3fc Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Mon, 8 Apr 2024 18:03:43 +0100 Subject: [PATCH 471/580] #65, fabric 1.20 --- .../advancedbackups/client/AdvancedBackupsClientCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java index c6316e9e..78b4f858 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java @@ -17,7 +17,7 @@ public class AdvancedBackupsClientCommand { public static void register(CommandDispatcher dispatcher) { dispatcher.register(ClientCommandManager.literal("backup").requires((runner) -> { - return runner.hasPermissionLevel(0); + return true; }).then(ClientCommandManager.literal("start").executes((runner) -> { Acknowledgment acknowledgment = MinecraftClient.getInstance().player.networkHandler.lastSeenMessagesCollector.collect().update(); MinecraftClient.getInstance().player.networkHandler.sendPacket(new CommandExecutionC2SPacket("backup start", Instant.now(), 0L, ArgumentSignatureDataMap.EMPTY, acknowledgment)); From 5cc6560e12362650b3bd592f60f6d4cdad1debe6 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Mon, 8 Apr 2024 18:08:48 +0100 Subject: [PATCH 472/580] #65, fabric 1.20.2 --- .../advancedbackups/client/AdvancedBackupsClientCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java index c6316e9e..78b4f858 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java @@ -17,7 +17,7 @@ public class AdvancedBackupsClientCommand { public static void register(CommandDispatcher dispatcher) { dispatcher.register(ClientCommandManager.literal("backup").requires((runner) -> { - return runner.hasPermissionLevel(0); + return true; }).then(ClientCommandManager.literal("start").executes((runner) -> { Acknowledgment acknowledgment = MinecraftClient.getInstance().player.networkHandler.lastSeenMessagesCollector.collect().update(); MinecraftClient.getInstance().player.networkHandler.sendPacket(new CommandExecutionC2SPacket("backup start", Instant.now(), 0L, ArgumentSignatureDataMap.EMPTY, acknowledgment)); From 70aca03d832ac66b097305523569e01fde50dc10 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Mon, 8 Apr 2024 18:16:31 +0100 Subject: [PATCH 473/580] #65, forge 1.20.2 --- .../advancedbackups/client/AdvancedBackupsClientCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java index 6352c467..36d678c1 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java @@ -18,7 +18,7 @@ public class AdvancedBackupsClientCommand { public static void register(CommandDispatcher commandDispatcher) { commandDispatcher.register(literal("backup").requires((runner) -> { - return !ServerLifecycleHooks.getCurrentServer().isDedicatedServer() || runner.hasPermission(3); + return true; }).then(literal("start").executes((runner) -> { Update acknowledgment = Minecraft.getInstance().player.connection.lastSeenMessages.generateAndApplyUpdate().update(); Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup start", Instant.now(), 0, From ba6d326bcd27a4ad539b6299dde51d22887eddc8 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Mon, 8 Apr 2024 23:40:59 +0100 Subject: [PATCH 474/580] support #65 and version 3.5 in neoforge 1.20.2! --- .../advancedbackups/AdvancedBackups.java | 340 +++++++++--------- .../AdvancedBackupsCommand.java | 126 ++++--- .../client/AdvancedBackupsClientCommand.java | 74 ++++ .../advancedbackups/client/BackupToast.java | 224 ++++++------ .../client/ClientContactor.java | 140 ++++---- .../advancedbackups/client/ClientWrapper.java | 60 +++- .../advancedbackups/client/ColourHelper.java | 31 ++ .../network/NetworkHandler.java | 83 +++-- .../network/PacketBackupStatus.java | 141 ++++---- .../network/PacketToastSubscribe.java | 41 +++ .../resources/META-INF/accesstransformer.cfg | 1 + src/main/resources/META-INF/mods.toml | 3 + .../assets/advancedbackups/lang/en_us.json | 11 +- 13 files changed, 767 insertions(+), 508 deletions(-) create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/client/ColourHelper.java create mode 100644 src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java create mode 100644 src/main/resources/META-INF/accesstransformer.cfg diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 60b7cd90..792dbbcc 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -1,164 +1,176 @@ -package co.uk.mommyheather.advancedbackups; - -import java.util.List; -import java.util.function.Consumer; - -import org.slf4j.Logger; - -import com.mojang.logging.LogUtils; - -import co.uk.mommyheather.advancedbackups.client.ClientContactor; -import co.uk.mommyheather.advancedbackups.core.ABCore; -import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; -import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; -import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; -import co.uk.mommyheather.advancedbackups.network.NetworkHandler; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.level.storage.LevelResource; -import net.neoforged.bus.api.SubscribeEvent; -import net.neoforged.fml.ModList; -import net.neoforged.fml.common.Mod; -import net.neoforged.neoforge.common.NeoForge; -import net.neoforged.neoforge.event.RegisterCommandsEvent; -import net.neoforged.neoforge.event.TickEvent; -import net.neoforged.neoforge.event.entity.player.PlayerEvent; -import net.neoforged.neoforge.event.server.ServerStartedEvent; -import net.neoforged.neoforge.event.server.ServerStartingEvent; -import net.neoforged.neoforge.event.server.ServerStoppingEvent; -import net.neoforged.neoforge.server.ServerLifecycleHooks; - -@Mod("advancedbackups") -public class AdvancedBackups -{ - - private static final Logger LOGGER = LogUtils.getLogger(); - - public static final Consumer infoLogger = LOGGER::info; - public static final Consumer warningLogger = LOGGER::warn; - public static final Consumer errorLogger = LOGGER::error; - - - public AdvancedBackups() - { - // Register ourselves for server and other game events we are interested in - NeoForge.EVENT_BUS.register(this); - NetworkHandler.register(); - } - - @SubscribeEvent - public void onServerStarting(ServerStartingEvent event) - { - // Do something when the server starts - ABCore.worldName = event.getServer().getWorldData().getLevelName(); - ABCore.worldDir = event.getServer().getWorldPath(LevelResource.ROOT); - - ABCore.disableSaving = AdvancedBackups::disableSaving; - ABCore.enableSaving = AdvancedBackups::enableSaving; - ABCore.saveOnce = AdvancedBackups::saveOnce; - - ABCore.infoLogger = infoLogger; - ABCore.warningLogger = warningLogger; - ABCore.errorLogger = errorLogger; - - ABCore.resetActivity = AdvancedBackups::resetActivity; - - ABCore.clientContactor = new ClientContactor(); - ABCore.modJar = ModList.get().getModFileById("advancedbackups").getFile().getFilePath().toFile(); - - - ConfigManager.loadOrCreateConfig(); - LOGGER.info("Config loaded!!"); - - } - - @SubscribeEvent - public void onServerStarted(ServerStartedEvent event) { - BackupWrapper.checkStartupBackups(); - } - - @SubscribeEvent - public void onServerStopping(ServerStoppingEvent event) { - BackupWrapper.checkShutdownBackups(); - } - - - @SubscribeEvent - public void onPlayerJoined(PlayerEvent.PlayerLoggedInEvent event) { - ABCore.setActivity(true); - } - - @SubscribeEvent - public void registerCommands(RegisterCommandsEvent event){ - AdvancedBackupsCommand.register(event.getDispatcher()); - } - - - @SubscribeEvent - public void onPostTick(TickEvent.ServerTickEvent event) { - if (!event.phase.equals(TickEvent.Phase.END)) return; - BackupTimer.check(); - } - - - public static final String savesDisabledMessage = """ - - - *************************************** - SAVING DISABLED - PREPARING FOR BACKUP! - *************************************** - """; - public static final String savesEnabledMessage = """ - - - ********************************* - SAVING ENABLED - BACKUP COMPLETE! - ********************************* - """; - public static final String saveCompleteMessage = """ - - - ************************************* - SAVE COMPLETE - PREPARING FOR BACKUP! - ************************************* - """; - - - public static void disableSaving() { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - for (ServerLevel level : server.getAllLevels()) { - if (level != null && !level.noSave) { - level.noSave = true; - } - } - if (ConfigManager.silent.get()) return; - warningLogger.accept(savesDisabledMessage); - } - - public static void enableSaving() { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - for (ServerLevel level : server.getAllLevels()) { - if (level != null && level.noSave) { - level.noSave = false; - } - } - if (ConfigManager.silent.get()) return; - warningLogger.accept(savesEnabledMessage); - } - - public static void saveOnce(boolean flush) { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - server.saveEverything(true, flush, true); - if (ConfigManager.silent.get()) return; - warningLogger.accept(saveCompleteMessage); - } - - - public static void resetActivity() { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - List players = server.getPlayerList().getPlayers(); - ABCore.setActivity(!players.isEmpty()); - } - -} +package co.uk.mommyheather.advancedbackups; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; + +import org.slf4j.Logger; + +import com.mojang.logging.LogUtils; + +import co.uk.mommyheather.advancedbackups.client.ClientContactor; +import co.uk.mommyheather.advancedbackups.client.ClientWrapper; +import co.uk.mommyheather.advancedbackups.core.ABCore; +import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; +import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; +import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.level.storage.LevelResource; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.ModList; +import net.neoforged.fml.common.Mod; +import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent; +import net.neoforged.fml.javafmlmod.FMLJavaModLoadingContext; +import net.neoforged.neoforge.common.NeoForge; +import net.neoforged.neoforge.event.RegisterCommandsEvent; +import net.neoforged.neoforge.event.TickEvent; +import net.neoforged.neoforge.event.entity.player.PlayerEvent; +import net.neoforged.neoforge.event.server.ServerStartedEvent; +import net.neoforged.neoforge.event.server.ServerStartingEvent; +import net.neoforged.neoforge.event.server.ServerStoppingEvent; +import net.neoforged.neoforge.server.ServerLifecycleHooks; + +@Mod("advancedbackups") +public class AdvancedBackups +{ + + private static final Logger LOGGER = LogUtils.getLogger(); + + public static final Consumer infoLogger = LOGGER::info; + public static final Consumer warningLogger = LOGGER::warn; + public static final Consumer errorLogger = LOGGER::error; + + public static final ArrayList players = new ArrayList<>(); + + + public AdvancedBackups() + { + // Register ourselves for server and other game events we are interested in + NeoForge.EVENT_BUS.register(this); + NetworkHandler.register(); + FMLJavaModLoadingContext.get().getModEventBus().addListener(this::clientSetup); + + ABCore.infoLogger = infoLogger; + ABCore.warningLogger = warningLogger; + ABCore.errorLogger = errorLogger; + } + + @SubscribeEvent + public void onServerStarting(ServerStartingEvent event) + { + // Do something when the server starts + ABCore.worldName = event.getServer().getWorldData().getLevelName(); + ABCore.worldDir = event.getServer().getWorldPath(LevelResource.ROOT); + + ABCore.disableSaving = AdvancedBackups::disableSaving; + ABCore.enableSaving = AdvancedBackups::enableSaving; + ABCore.saveOnce = AdvancedBackups::saveOnce; + + ABCore.resetActivity = AdvancedBackups::resetActivity; + + ABCore.clientContactor = new ClientContactor(); + ABCore.modJar = ModList.get().getModFileById("advancedbackups").getFile().getFilePath().toFile(); + + + ConfigManager.loadOrCreateConfig(); + LOGGER.info("Config loaded!!"); + + } + + public void clientSetup(FMLClientSetupEvent e) { + ClientWrapper.init(e); + } + + + @SubscribeEvent + public void onServerStarted(ServerStartedEvent event) { + BackupWrapper.checkStartupBackups(); + } + + @SubscribeEvent + public void onServerStopping(ServerStoppingEvent event) { + BackupWrapper.checkShutdownBackups(); + } + + + @SubscribeEvent + public void onPlayerJoined(PlayerEvent.PlayerLoggedInEvent event) { + ABCore.setActivity(true); + } + + @SubscribeEvent + public void registerCommands(RegisterCommandsEvent event){ + AdvancedBackupsCommand.register(event.getDispatcher()); + } + + + @SubscribeEvent + public void onPostTick(TickEvent.ServerTickEvent event) { + if (!event.phase.equals(TickEvent.Phase.END)) return; + BackupTimer.check(); + } + + + public static final String savesDisabledMessage = """ + + + *************************************** + SAVING DISABLED - PREPARING FOR BACKUP! + *************************************** + """; + public static final String savesEnabledMessage = """ + + + ********************************* + SAVING ENABLED - BACKUP COMPLETE! + ********************************* + """; + public static final String saveCompleteMessage = """ + + + ************************************* + SAVE COMPLETE - PREPARING FOR BACKUP! + ************************************* + """; + + + public static void disableSaving() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + for (ServerLevel level : server.getAllLevels()) { + if (level != null && !level.noSave) { + level.noSave = true; + } + } + if (ConfigManager.silent.get()) return; + warningLogger.accept(savesDisabledMessage); + } + + public static void enableSaving() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + for (ServerLevel level : server.getAllLevels()) { + if (level != null && level.noSave) { + level.noSave = false; + } + } + if (ConfigManager.silent.get()) return; + warningLogger.accept(savesEnabledMessage); + } + + public static void saveOnce(boolean flush) { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + server.saveEverything(true, flush, true); + if (ConfigManager.silent.get()) return; + warningLogger.accept(saveCompleteMessage); + } + + + public static void resetActivity() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + ABCore.setActivity(!players.isEmpty()); + } + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java index 4a0f1512..f8c93e76 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackupsCommand.java @@ -1,55 +1,71 @@ -package co.uk.mommyheather.advancedbackups; - -import com.mojang.brigadier.CommandDispatcher; - -import co.uk.mommyheather.advancedbackups.core.CoreCommandSystem; -import net.minecraft.commands.CommandSourceStack; -import net.minecraft.commands.Commands; -import net.minecraft.network.chat.Component; -import net.neoforged.neoforge.server.ServerLifecycleHooks; - -public class AdvancedBackupsCommand { - public static void register(CommandDispatcher stack) { - stack.register(Commands.literal("backup").requires((runner) -> { - return !ServerLifecycleHooks.getCurrentServer().isDedicatedServer() || runner.hasPermission(3); - }).then(Commands.literal("start").executes((runner) -> { - CoreCommandSystem.startBackup((response) -> { - runner.getSource().sendSuccess(() -> { - return Component.literal(response) ; - }, true); - }); - return 1; - })) - - .then(Commands.literal("reload-config").executes((runner) -> { - CoreCommandSystem.reloadConfig((response) -> { - runner.getSource().sendSuccess(() -> { - return Component.literal(response) ; - }, true); - }); - return 1; - })) - - .then(Commands.literal("reset-chain").executes((runner) -> { - CoreCommandSystem.resetChainLength((response) -> { - runner.getSource().sendSuccess(() -> { - return Component.literal(response) ; - }, true); - }); - return 1; - })) - - .then(Commands.literal("snapshot").executes((runner) -> { - CoreCommandSystem.snapshot((response) -> { - runner.getSource().sendSuccess(() -> { - return Component.literal(response) ; - }, true); - }); - return 1; - })) - - ); - } - - -} +package co.uk.mommyheather.advancedbackups; + +import com.mojang.brigadier.CommandDispatcher; + +import co.uk.mommyheather.advancedbackups.core.CoreCommandSystem; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.commands.Commands; +import net.minecraft.network.chat.Component; +import net.neoforged.neoforge.server.ServerLifecycleHooks; + +public class AdvancedBackupsCommand { + public static void register(CommandDispatcher stack) { + stack.register(Commands.literal("backup").requires((runner) -> { + return !ServerLifecycleHooks.getCurrentServer().isDedicatedServer() || runner.hasPermission(3); + }).then(Commands.literal("start").executes((runner) -> { + CoreCommandSystem.startBackup((response) -> { + runner.getSource().sendSuccess(() -> { + return Component.literal(response) ; + }, true); + }); + return 1; + })) + + .then(Commands.literal("reload-config").executes((runner) -> { + CoreCommandSystem.reloadConfig((response) -> { + runner.getSource().sendSuccess(() -> { + return Component.literal(response) ; + }, true); + }); + return 1; + })) + + .then(Commands.literal("reset-chain").executes((runner) -> { + CoreCommandSystem.resetChainLength((response) -> { + runner.getSource().sendSuccess(() -> { + return Component.literal(response) ; + }, true); + }); + return 1; + })) + + .then(Commands.literal("snapshot").executes((runner) -> { + CoreCommandSystem.snapshot((response) -> { + runner.getSource().sendSuccess(() -> { + return Component.literal(response) ; + }, true); + }); + return 1; + })) + + .then(Commands.literal("cancel").executes((runner) -> { + CoreCommandSystem.cancelBackup((response) -> { + runner.getSource().sendSuccess(() -> { + return Component.literal(response) ; + }, true); + }); + return 1; + })) + + .then(Commands.literal("reload-client-config").executes((runner) -> { + runner.getSource().sendSuccess(() -> { + return Component.literal("This command can only be ran on the client!") ; + }, true); + return 1; + })) + + ); + } + + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java new file mode 100644 index 00000000..8271dc91 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java @@ -0,0 +1,74 @@ +package co.uk.mommyheather.advancedbackups.client; + +import java.time.Instant; + +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; + +import co.uk.mommyheather.advancedbackups.core.CoreCommandSystem; +import net.minecraft.client.Minecraft; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.commands.arguments.ArgumentSignatures; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.LastSeenMessages.Update; +import net.minecraft.network.protocol.game.ServerboundChatCommandPacket; +import net.neoforged.neoforge.server.ServerLifecycleHooks; + +public class AdvancedBackupsClientCommand { + public static void register(CommandDispatcher commandDispatcher) { + commandDispatcher.register(literal("backup").requires((runner) -> { + return true; + }).then(literal("start").executes((runner) -> { + Update acknowledgment = Minecraft.getInstance().player.connection.lastSeenMessages.generateAndApplyUpdate().update(); + Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup start", Instant.now(), 0, + ArgumentSignatures.EMPTY, acknowledgment)); + return 1; + })) + + .then(literal("reload-config").executes((runner) -> { + Update acknowledgment = Minecraft.getInstance().player.connection.lastSeenMessages.generateAndApplyUpdate().update(); + Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup reload-config", Instant.now(), 0, + ArgumentSignatures.EMPTY, acknowledgment)); + return 1; + })) + + .then(literal("reset-chain").executes((runner) -> { + Update acknowledgment = Minecraft.getInstance().player.connection.lastSeenMessages.generateAndApplyUpdate().update(); + Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup reset-chain", Instant.now(), 0, + ArgumentSignatures.EMPTY, acknowledgment)); + return 1; + })) + + .then(literal("snapshot").executes((runner) -> { + Update acknowledgment = Minecraft.getInstance().player.connection.lastSeenMessages.generateAndApplyUpdate().update(); + Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup snapshot", Instant.now(), 0, + ArgumentSignatures.EMPTY, acknowledgment)); + return 1; + })) + + .then(literal("cancel").executes((runner) -> { + Update acknowledgment = Minecraft.getInstance().player.connection.lastSeenMessages.generateAndApplyUpdate().update(); + Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup cancel", Instant.now(), 0, + ArgumentSignatures.EMPTY, acknowledgment)); + return 1; + })) + + .then(literal("reload-client-config").executes((runner) -> { + CoreCommandSystem.reloadClientConfig((response) -> { + runner.getSource().sendSuccess(() -> { + return Component.literal(response); + }, true); + }); + return 1; + })) + + ); + } + + //I'm no fan of having this here but it seems required + public static LiteralArgumentBuilder literal(String literal) { + return LiteralArgumentBuilder.literal(literal); + } + + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java index b355ca6d..a7b7414b 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java @@ -1,100 +1,124 @@ -package co.uk.mommyheather.advancedbackups.client; - -import net.minecraft.ChatFormatting; -import net.minecraft.client.gui.GuiGraphics; -import net.minecraft.client.gui.components.toasts.Toast; -import net.minecraft.client.gui.components.toasts.ToastComponent; -import net.minecraft.client.resources.language.I18n; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Items; - -public class BackupToast implements Toast { - - public static boolean starting; - public static boolean started; - public static boolean failed; - public static boolean finished; - - public static int progress; - public static int max; - - public static boolean exists = false; - - private static long time; - private static boolean timeSet = false; - - public static final ItemStack stack = new ItemStack(Items.PAPER); - private static final ResourceLocation TEXTURE = new ResourceLocation("toast/advancement"); - - - @Override - public Visibility render(GuiGraphics graphics, ToastComponent toastGui, long delta) { - graphics.blitSprite(TEXTURE, 0, 0, this.width(), this.height()); - graphics.renderFakeItem(stack, 8, 8); - - - float percent = finished ? 100 : (float) progress / (float) max; - - graphics.fill(3, 28, 156, 29, -1); - float f = Math.min(156, ( - 156 * percent - )); - - - if (!exists) { - graphics.drawString(toastGui.getMinecraft().font, ChatFormatting.GREEN + I18n.get("advancedbackups.backup_finished"), 25, 11, -11534256); - graphics.fill(3, 28, 156, 29, -10948014); - return Visibility.HIDE; - } - - String title = "You shouldn't see this!"; - - - if (starting) { - title = ChatFormatting.GREEN + I18n.get("advancedbackups.backup_starting"); - } - else if (started) { - title = ChatFormatting.GREEN + I18n.get("advancedbackups.progress", round(percent * 100)); - } - else if (failed) { - title = ChatFormatting.RED + I18n.get("advancedbackups.backup_failed"); - if (!timeSet) { - time = System.currentTimeMillis(); - timeSet = true; - } - } - else if (finished) { - title = ChatFormatting.GREEN + I18n.get("advancedbackups.backup_finished"); - if (!timeSet) { - time = System.currentTimeMillis(); - timeSet = true; - } - } - - graphics.drawString(toastGui.getMinecraft().font, title, 25, 11, -11534256); - - if (timeSet && System.currentTimeMillis() >= time + 5000) { - starting = false; - started = false; - failed = false; - finished = false; - progress = 0; - max = 0; - timeSet = false; - exists = false; - return Visibility.HIDE; - } - - graphics.fill(3, 28, Math.max(3, (int) f), 29, -10948014); - - return Visibility.SHOW; - - } - - - private static String round (float value) { - return String.format("%.1f", value); - } - -} +package co.uk.mommyheather.advancedbackups.client; + +import co.uk.mommyheather.advancedbackups.core.config.ClientConfigManager; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.components.toasts.Toast; +import net.minecraft.client.gui.components.toasts.ToastComponent; +import net.minecraft.client.resources.language.I18n; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; + +public class BackupToast implements Toast { + + public static boolean starting; + public static boolean started; + public static boolean failed; + public static boolean finished; + public static boolean cancelled; + + public static int progress; + public static int max; + + public static boolean exists = false; + + private static long time; + private static boolean timeSet = false; + + public static final ItemStack stack = new ItemStack(Items.PAPER); + private static final ResourceLocation TEXTURE = new ResourceLocation("toast/advancement"); + + private int textColour; + private String title = "You shouldn't see this!"; + + + @Override + public Visibility render(GuiGraphics graphics, ToastComponent toastGui, long delta) { + graphics.blitSprite(TEXTURE, 0, ClientConfigManager.darkMode.get() ? 0 : this.height(), this.width(), this.height()); + graphics.renderFakeItem(stack, 8, 8); + + + float percent = finished ? 100 : (float) progress / (float) max; + + graphics.fill(4, 28, 156, 29, ColourHelper.colour + (255, (int) ClientConfigManager.progressBackgroundRed.get(), (int) ClientConfigManager.progressBackgroundGreen.get(), (int) ClientConfigManager.progressBackgroundBlue.get())); + + float f = Math.min(156, ( + 156 * percent + )); + + if (!exists) { + if (title.equals(I18n.get("advancedbackups.backup_finished"))){ + textColour = ColourHelper.colour(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); + graphics.drawString(toastGui.getMinecraft().font, I18n.get(title), 25, 11, textColour); + graphics.fill(3, 28, 156, 29, ColourHelper.colour + (255, (int) ClientConfigManager.progressBarRed.get(), (int) ClientConfigManager.progressBarGreen.get(), (int) ClientConfigManager.progressBarBlue.get())); + } + else { + textColour = ColourHelper.colour(255, (int) ClientConfigManager.errorTextRed.get(), (int) ClientConfigManager.errorTextGreen.get(), (int) ClientConfigManager.errorTextBlue.get()); + graphics.drawString(toastGui.getMinecraft().font, I18n.get(title), 25, 11, textColour); + } + return Visibility.HIDE; + } + + + if (starting) { + textColour = ColourHelper.colour(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); + title = I18n.get("advancedbackups.backup_starting"); + } + else if (started) { + textColour = ColourHelper.colour(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); + title = I18n.get("advancedbackups.progress", round(percent * 100)); + } + else if (failed) { + textColour = ColourHelper.colour(255, (int) ClientConfigManager.errorTextRed.get(), (int) ClientConfigManager.errorTextGreen.get(), (int) ClientConfigManager.errorTextBlue.get()); + title = I18n.get("advancedbackups.backup_failed"); + if (!timeSet) { + time = System.currentTimeMillis(); + timeSet = true; + } + } + else if (finished) { + textColour = ColourHelper.colour(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); + title = I18n.get("advancedbackups.backup_finished"); + if (!timeSet) { + time = System.currentTimeMillis(); + timeSet = true; + } + } + else if (cancelled) { + textColour = ColourHelper.colour(255, (int) ClientConfigManager.errorTextRed.get(), (int) ClientConfigManager.errorTextGreen.get(), (int) ClientConfigManager.errorTextBlue.get()); + title = I18n.get("advancedbackups.backup_cancelled"); + if (!timeSet) { + time = System.currentTimeMillis(); + timeSet = true; + } + } + + graphics.drawString(toastGui.getMinecraft().font, title, 25, 11, textColour); + + if (timeSet && System.currentTimeMillis() >= time + 5000) { + starting = false; + started = false; + failed = false; + finished = false; + progress = 0; + max = 0; + timeSet = false; + exists = false; + return Visibility.HIDE; + } + + graphics.fill(4, 28, Math.max(4, (int) f), 29, ColourHelper.colour + (255, (int) ClientConfigManager.progressBarRed.get(), (int) ClientConfigManager.progressBarGreen.get(), (int) ClientConfigManager.progressBarBlue.get())); + + return Visibility.SHOW; + + } + + + private static String round (float value) { + return String.format("%.1f", value); + } + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java index f3fd1905..c8bd4203 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java @@ -1,61 +1,79 @@ -package co.uk.mommyheather.advancedbackups.client; - -import java.util.List; - -import co.uk.mommyheather.advancedbackups.interfaces.IClientContactor; -import co.uk.mommyheather.advancedbackups.network.NetworkHandler; -import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ServerPlayer; -import net.neoforged.neoforge.server.ServerLifecycleHooks; - -public class ClientContactor implements IClientContactor { - - @Override - public void backupComplete() { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - List players = server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, 0, 0); - for (ServerPlayer player : players) { - if (!server.isDedicatedServer() || player.hasPermissions(3)) { - NetworkHandler.sendToClient(player, packet); - } - } - } - - @Override - public void backupFailed() { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - List players = server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, 0, 0); - for (ServerPlayer player : players) { - if (!server.isDedicatedServer() || player.hasPermissions(3)) { - NetworkHandler.sendToClient(player, packet); - } - } - } - - @Override - public void backupProgress(int progress, int max) { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - List players = server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, progress, max); - for (ServerPlayer player : players) { - if (!server.isDedicatedServer() || player.hasPermissions(3)) { - NetworkHandler.sendToClient(player, packet); - } - } - } - - @Override - public void backupStarting() { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - List players = server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, 0, 0); - for (ServerPlayer player : players) { - if (!server.isDedicatedServer() || player.hasPermissions(3)) { - NetworkHandler.sendToClient(player, packet); - } - } - } -} +package co.uk.mommyheather.advancedbackups.client; + +import java.util.List; + +import co.uk.mommyheather.advancedbackups.AdvancedBackups; +import co.uk.mommyheather.advancedbackups.interfaces.IClientContactor; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; +import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerPlayer; +import net.neoforged.neoforge.server.ServerLifecycleHooks; + +public class ClientContactor implements IClientContactor { + + @Override + public void backupComplete() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, false, 0, 0); + for (ServerPlayer player : players) { + if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; + if (!server.isDedicatedServer() || player.hasPermissions(3)) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupFailed() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, false, 0, 0); + for (ServerPlayer player : players) { + if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; + if (!server.isDedicatedServer() || player.hasPermissions(3)) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupProgress(int progress, int max) { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, false, progress, max); + for (ServerPlayer player : players) { + if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; + if (!server.isDedicatedServer() || player.hasPermissions(3)) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupStarting() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, false, 0, 0); + for (ServerPlayer player : players) { + if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; + if (!server.isDedicatedServer() || player.hasPermissions(3)) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupCancelled() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, false, false, true, 0, 0); + for (ServerPlayer player : players) { + if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; + if (!server.isDedicatedServer() || player.hasPermissions(3)) { + NetworkHandler.sendToClient(player, packet); + } + } + } +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java index 8d0d63ee..e1c86f56 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java @@ -1,15 +1,45 @@ -package co.uk.mommyheather.advancedbackups.client; - -import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; -import net.minecraft.client.Minecraft; - -public class ClientWrapper { - - public static void handle(PacketBackupStatus packetBackupStatus) { - if (!BackupToast.exists) { - BackupToast.exists = true; - Minecraft.getInstance().getToasts().addToast(new BackupToast()); - } - } - -} +package co.uk.mommyheather.advancedbackups.client; + +import co.uk.mommyheather.advancedbackups.core.config.ClientConfigManager; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; +import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; +import co.uk.mommyheather.advancedbackups.network.PacketToastSubscribe; +import net.minecraft.client.Minecraft; +import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent; +import net.neoforged.neoforge.client.event.ClientPlayerNetworkEvent; +import net.neoforged.neoforge.client.event.RegisterClientCommandsEvent; +import net.neoforged.neoforge.common.NeoForge; + +public class ClientWrapper { + + public static void handle(PacketBackupStatus packet) { + BackupToast.starting = packet.starting; + BackupToast.started = packet.started; + BackupToast.failed = packet.failed; + BackupToast.finished = packet.finished; + BackupToast.cancelled = packet.cancelled; + + BackupToast.progress = packet.progress; + BackupToast.max = packet.max; + + if (!BackupToast.exists) { + BackupToast.exists = true; + Minecraft.getInstance().getToasts().addToast(new BackupToast()); + } + } + + public static void init(FMLClientSetupEvent e) { + NeoForge.EVENT_BUS.addListener(ClientWrapper::registerClientCommands); + NeoForge.EVENT_BUS.addListener(ClientWrapper::onServerConnected); + ClientConfigManager.loadOrCreateConfig(); + } + + public static void registerClientCommands(RegisterClientCommandsEvent event) { + AdvancedBackupsClientCommand.register(event.getDispatcher()); + } + + public static void onServerConnected(ClientPlayerNetworkEvent.LoggingIn event) { + NetworkHandler.sendToServer(new PacketToastSubscribe(ClientConfigManager.showProgress.get())); + } + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ColourHelper.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ColourHelper.java new file mode 100644 index 00000000..1392023c --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ColourHelper.java @@ -0,0 +1,31 @@ +package co.uk.mommyheather.advancedbackups.client; + +//A colour helper, loosely based on that of vanilla 1.16. +//Where is it in modern? +public class ColourHelper { + + public static int alpha(int in) { + return in >>> 24; + } + + public static int red(int in) { + return in >> 16 & 255; + } + + public static int green(int in) { + return in >> 8 & 255; + } + + public static int blue(int in) { + return in & 255; + } + + public static int colour(int a, int r, int g, int b) { + return a << 24 | r << 16 | g << 8 | b; + } + + public static int colour(int a, long r, long g, long b) { + return colour(a, (int) r, (int) g, (int) b); + } + +} \ No newline at end of file diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java index 2f754cab..c9ebb9e7 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java @@ -1,37 +1,46 @@ -package co.uk.mommyheather.advancedbackups.network; - -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.level.ServerPlayer; -import net.neoforged.neoforge.network.NetworkRegistry; -import net.neoforged.neoforge.network.PlayNetworkDirection; -import net.neoforged.neoforge.network.simple.SimpleChannel; - -public class NetworkHandler { - - private static final String PROTOCOL_VERSION = "1"; - private static int id = 0; - private static int id() { - return id++; - } - - public static final SimpleChannel INSTANCE = NetworkRegistry.newSimpleChannel( - new ResourceLocation("advancedbackups", "main"), - () -> PROTOCOL_VERSION, - (version) -> true, - (version) -> true - ); - - - public static void register() { - INSTANCE.messageBuilder(PacketBackupStatus.class, id()) - .encoder(PacketBackupStatus::toBytes) - .decoder(buf -> new PacketBackupStatus(buf)) - .consumerNetworkThread(PacketBackupStatus::handle) - .add(); - } - - public static void sendToClient(ServerPlayer player, Object packet) { - INSTANCE.sendTo(packet, player.connection.connection, PlayNetworkDirection.PLAY_TO_CLIENT); - } - -} +package co.uk.mommyheather.advancedbackups.network; + +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerPlayer; +import net.neoforged.neoforge.network.NetworkRegistry; +import net.neoforged.neoforge.network.PlayNetworkDirection; +import net.neoforged.neoforge.network.simple.SimpleChannel; + +public class NetworkHandler { + + private static final String PROTOCOL_VERSION = "1"; + private static int id = 0; + private static int id() { + return id++; + } + + public static final SimpleChannel INSTANCE = NetworkRegistry.newSimpleChannel( + new ResourceLocation("advancedbackups", "main"), + () -> PROTOCOL_VERSION, + (version) -> true, + (version) -> true + ); + + + public static void register() { + INSTANCE.messageBuilder(PacketBackupStatus.class, id()) + .encoder(PacketBackupStatus::toBytes) + .decoder(buf -> new PacketBackupStatus(buf)) + .consumerNetworkThread(PacketBackupStatus::handle) + .add(); + INSTANCE.messageBuilder(PacketToastSubscribe.class, id()) + .encoder(PacketToastSubscribe::toBytes) + .decoder(buf -> new PacketToastSubscribe(buf)) + .consumerNetworkThread(PacketToastSubscribe::handle) + .add(); + } + + public static void sendToClient(ServerPlayer player, Object packet) { + INSTANCE.sendTo(packet, player.connection.connection, PlayNetworkDirection.PLAY_TO_CLIENT); + } + + public static void sendToServer(Object packet) { + INSTANCE.sendToServer(packet); + } + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java index 1b520851..99acd262 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java @@ -1,71 +1,70 @@ -package co.uk.mommyheather.advancedbackups.network; - - -import co.uk.mommyheather.advancedbackups.client.BackupToast; -import co.uk.mommyheather.advancedbackups.client.ClientWrapper; -import net.minecraft.network.FriendlyByteBuf; -import net.neoforged.fml.LogicalSide; -import net.neoforged.neoforge.network.NetworkEvent; - -public class PacketBackupStatus { - - public boolean starting; - public boolean started; - - public boolean failed; - public boolean finished; - - public int progress; - public int max; - - - public PacketBackupStatus(boolean starting, boolean started, boolean failed, boolean finished, int progress, - int max) { - this.starting = starting; - this.started = started; - this.failed = failed; - this.finished = finished; - this.progress = progress; - this.max = max; - } - - - public PacketBackupStatus(FriendlyByteBuf buf) { - starting = buf.readBoolean(); - started = buf.readBoolean(); - failed = buf.readBoolean(); - finished = buf.readBoolean(); - - progress = buf.readInt(); - max = buf.readInt(); - } - - public void toBytes(FriendlyByteBuf buf) { - buf.writeBoolean(starting); - buf.writeBoolean(started); - buf.writeBoolean(failed); - buf.writeBoolean(finished); - - buf.writeInt(progress); - buf.writeInt(max); - } - - public static boolean handle(PacketBackupStatus packet, NetworkEvent.Context ctx) { - BackupToast.starting = packet.starting; - BackupToast.started = packet.started; - BackupToast.failed = packet.failed; - BackupToast.finished = packet.finished; - - BackupToast.progress = packet.progress; - BackupToast.max = packet.max; - ctx.enqueueWork(() -> { - if (ctx.getDirection().getReceptionSide() == LogicalSide.CLIENT) { - ClientWrapper.handle(packet); - } - }); - ctx.setPacketHandled(true); - return true; - - } - -} +package co.uk.mommyheather.advancedbackups.network; + +import java.util.function.Supplier; + +import co.uk.mommyheather.advancedbackups.client.BackupToast; +import co.uk.mommyheather.advancedbackups.client.ClientWrapper; +import net.minecraft.client.Minecraft; +import net.minecraft.network.FriendlyByteBuf; +import net.neoforged.fml.LogicalSide; +import net.neoforged.neoforge.network.NetworkEvent; + +public class PacketBackupStatus { + + public boolean starting; + public boolean started; + + public boolean failed; + public boolean finished; + public boolean cancelled; + + public int progress; + public int max; + + + public PacketBackupStatus(boolean starting, boolean started, boolean failed, boolean finished, boolean cancelled, int progress, + int max) { + this.starting = starting; + this.started = started; + this.failed = failed; + this.finished = finished; + this.cancelled = cancelled; + this.progress = progress; + this.max = max; + } + + + public PacketBackupStatus(FriendlyByteBuf buf) { + starting = buf.readBoolean(); + started = buf.readBoolean(); + failed = buf.readBoolean(); + finished = buf.readBoolean(); + cancelled = buf.readBoolean(); + + progress = buf.readInt(); + max = buf.readInt(); + } + + public void toBytes(FriendlyByteBuf buf) { + buf.writeBoolean(starting); + buf.writeBoolean(started); + buf.writeBoolean(failed); + buf.writeBoolean(finished); + buf.writeBoolean(cancelled); + + buf.writeInt(progress); + buf.writeInt(max); + } + + public boolean handle(NetworkEvent.Context ctx) { + ctx.enqueueWork(() -> { + if (ctx.getDirection().getReceptionSide() == LogicalSide.CLIENT) { + ClientWrapper.handle(this); + } + }); + ctx.setPacketHandled(true); + return true; + + } + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java new file mode 100644 index 00000000..4e9224f5 --- /dev/null +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java @@ -0,0 +1,41 @@ +package co.uk.mommyheather.advancedbackups.network; + +import java.util.function.Supplier; + +import co.uk.mommyheather.advancedbackups.AdvancedBackups; +import net.minecraft.network.FriendlyByteBuf; +import net.neoforged.neoforge.network.NetworkEvent; + +public class PacketToastSubscribe { + + private boolean enable; + + public PacketToastSubscribe(boolean enable) { + this.enable = enable; + } + + + public PacketToastSubscribe(FriendlyByteBuf buf) { + enable = buf.readBoolean(); + } + + public void toBytes(FriendlyByteBuf buf) { + buf.writeBoolean(enable); + } + + public boolean handle(NetworkEvent.Context ctx) { + ctx.enqueueWork(() -> { + if (ctx.getSender() == null) return; + if (enable && !AdvancedBackups.players.contains(ctx.getSender().getStringUUID())) { + AdvancedBackups.players.add(ctx.getSender().getStringUUID()); + } + else if (!enable) { + AdvancedBackups.players.remove(ctx.getSender().getStringUUID()); + } + }); + + return true; + + } + +} diff --git a/src/main/resources/META-INF/accesstransformer.cfg b/src/main/resources/META-INF/accesstransformer.cfg new file mode 100644 index 00000000..9d2bce8b --- /dev/null +++ b/src/main/resources/META-INF/accesstransformer.cfg @@ -0,0 +1 @@ +public net.minecraft.client.multiplayer.ClientPacketListener lastSeenMessages # lastSeenMessages \ No newline at end of file diff --git a/src/main/resources/META-INF/mods.toml b/src/main/resources/META-INF/mods.toml index b0ad9f84..3435b2b2 100644 --- a/src/main/resources/META-INF/mods.toml +++ b/src/main/resources/META-INF/mods.toml @@ -38,6 +38,9 @@ authors="${mod_authors}" #optional # IMPORTANT NOTE: this is NOT an instruction as to which environments (CLIENT or DEDICATED SERVER) your mod loads on. Your mod should load (and maybe do nothing!) whereever it finds itself. #displayTest="MATCH_VERSION" # MATCH_VERSION is the default if nothing is specified (#optional) +[[accessTransformers]] +file="META-INF/accesstransformer.cfg" + # The description text for the mod (multi line!) (#mandatory) description='''${mod_description}''' # A dependency - use the . to indicate dependency for a specific modid. Dependencies are optional. diff --git a/src/main/resources/assets/advancedbackups/lang/en_us.json b/src/main/resources/assets/advancedbackups/lang/en_us.json index cc68dae1..9a59cd17 100644 --- a/src/main/resources/assets/advancedbackups/lang/en_us.json +++ b/src/main/resources/assets/advancedbackups/lang/en_us.json @@ -1,6 +1,7 @@ -{ - "advancedbackups.backup_starting" : "Backup starting!", - "advancedbackups.progress": "Backup ongoing: %1$s%%", - "advancedbackups.backup_failed": "Backup failed!\nCheck log for more info.", - "advancedbackups.backup_finished": "Backup complete!" +{ + "advancedbackups.backup_starting" : "Backup starting!", + "advancedbackups.progress": "Backup ongoing: %1$s%%", + "advancedbackups.backup_failed": "Backup failed!\nCheck log for more info.", + "advancedbackups.backup_finished": "Backup complete!", + "advancedbackups.backup_cancelled": "Backup cancelled!" } \ No newline at end of file From 7e6976826cf81111d6b8fafae87b8c9699155b82 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Mon, 8 Apr 2024 23:42:31 +0100 Subject: [PATCH 475/580] previous commit --- build.gradle | 348 ++++++++++++++++++++++++++------------------------- 1 file changed, 177 insertions(+), 171 deletions(-) diff --git a/build.gradle b/build.gradle index 792aba25..eff2ead4 100644 --- a/build.gradle +++ b/build.gradle @@ -1,172 +1,178 @@ -plugins { - id 'java-library' - id 'eclipse' - id 'idea' - id 'maven-publish' - id 'net.neoforged.gradle.userdev' version '7.0.26' -} - -group = mod_group_id - -version = "${version != 'unspecified' ? version : '0.1-dev'}" //debuggins sake -configurations { - // configuration that holds jars to include in the jar - extraLibs -} - -repositories { - mavenLocal() -} - -base { - archivesName = 'AdvancedBackups-' + modloaderName + "-" + minecraftVersion -} - - - -// Mojang ships Java 17 to end users in 1.18+, so your mod should target Java 17. -java.toolchain.languageVersion = JavaLanguageVersion.of(17) - -//minecraft.accessTransformers.file rootProject.file('src/main/resources/META-INF/accesstransformer.cfg') -//minecraft.accessTransformers.entry public net.minecraft.client.Minecraft textureManager # textureManager - -// Default run configurations. -// These can be tweaked, removed, or duplicated as needed. -runs { - // applies to all the run configs below - configureEach { - // Recommended logging data for a userdev environment - // The markers can be added/remove as needed separated by commas. - // "SCAN": For mods scan. - // "REGISTRIES": For firing of registry events. - // "REGISTRYDUMP": For getting the contents of all registries. - systemProperty 'forge.logging.markers', 'REGISTRIES' - - // Recommended logging level for the console - // You can set various levels here. - // Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels - systemProperty 'forge.logging.console.level', 'debug' - - modSource project.sourceSets.main - } - - client { - // Comma-separated list of namespaces to load gametests from. Empty = all namespaces. - systemProperty 'forge.enabledGameTestNamespaces', project.mod_id - } - - server { - systemProperty 'forge.enabledGameTestNamespaces', project.mod_id - programArgument '--nogui' - } - - // This run config launches GameTestServer and runs all registered gametests, then exits. - // By default, the server will crash when no gametests are provided. - // The gametest system is also enabled by default for other run configs under the /test command. - gameTestServer { - systemProperty 'forge.enabledGameTestNamespaces', project.mod_id - } - - data { - // example of overriding the workingDirectory set in configureEach above, uncomment if you want to use it - // workingDirectory project.file('run-data') - - // Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources. - programArguments.addAll '--mod', project.mod_id, '--all', '--output', file('src/generated/resources/').getAbsolutePath(), '--existing', file('src/main/resources/').getAbsolutePath() - } -} - -// Include resources generated by data generators. -sourceSets.main.resources { srcDir 'src/generated/resources' } - - -dependencies { - // Specify the version of Minecraft to use. - // Depending on the plugin applied there are several options. We will assume you applied the userdev plugin as shown above. - // The group for userdev is net.neoforged, the module name is neoforge, and the version is the same as the neoforge version. - // You can however also use the vanilla plugin (net.neoforged.gradle.vanilla) to use a version of Minecraft without the neoforge loader. - // And its provides the option to then use net.minecraft as the group, and one of; client, server or joined as the module name, plus the game version as version. - // For all intends and purposes: You can treat this dependency as if it is a normal library you would use. - implementation "net.neoforged:neoforge:${neo_version}" - - - implementation files ('advancedbackups-corelib.jar') - extraLibs files ('advancedbackups-corelib.jar') - - // Example mod dependency with JEI - // The JEI API is declared for compile time use, while the full JEI artifact is used at runtime - // compileOnly "mezz.jei:jei-${mc_version}-common-api:${jei_version}" - // compileOnly "mezz.jei:jei-${mc_version}-forge-api:${jei_version}" - // runtimeOnly "mezz.jei:jei-${mc_version}-forge:${jei_version}" - - // Example mod dependency using a mod jar from ./libs with a flat dir repository - // This maps to ./libs/coolmod-${mc_version}-${coolmod_version}.jar - // The group id is ignored when searching -- in this case, it is "blank" - // implementation "blank:coolmod-${mc_version}:${coolmod_version}" - - // Example mod dependency using a file as dependency - // implementation files("libs/coolmod-${mc_version}-${coolmod_version}.jar") - - // Example project dependency using a sister or child project: - // implementation project(":myproject") - - // For more info: - // http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html - // http://www.gradle.org/docs/current/userguide/dependency_management.html -} - -// This block of code expands all declared replace properties in the specified resource targets. -// A missing property will result in an error. Properties are expanded using ${} Groovy notation. -// When "copyIdeResources" is enabled, this will also run before the game launches in IDE environments. -// See https://docs.gradle.org/current/dsl/org.gradle.language.jvm.tasks.ProcessResources.html -tasks.withType(ProcessResources).configureEach { - var replaceProperties = [ - minecraft_version : minecraft_version, minecraft_version_range: minecraft_version_range, - neo_version : neo_version, neo_version_range: neo_version_range, - loader_version_range: loader_version_range, - mod_id : mod_id, mod_name: mod_name, mod_license: mod_license, mod_version: version, - mod_authors : mod_authors, mod_description: mod_description, pack_format_number: pack_format_number, - ] - inputs.properties replaceProperties - - filesMatching(['META-INF/mods.toml', 'pack.mcmeta']) { - expand replaceProperties + [project: project] - } -} - -// Example for how to get properties into the manifest for reading at runtime. -tasks.named('jar', Jar).configure { - manifest { - attributes([ - "Main-Class" : "co.uk.mommyheather.advancedbackups.cli.AdvancedBackupsCLI", - "Specification-Title" : "advancedbackups", - "Specification-Vendor" : "mommyheather", - "Specification-Version" : "1", // We are version 1 of ourselves - "Implementation-Title" : project.name, - "Implementation-Version" : project.jar.archiveVersion, - "Implementation-Vendor" : "mommyheather", - "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ") - ]) - } - from { - configurations.extraLibs.collect { it.isDirectory() ? it : zipTree(it) } - } -} - -// Example configuration to allow publishing using the maven-publish plugin -publishing { - publications { - register('mavenJava', MavenPublication) { - from components.java - } - } - repositories { - maven { - url "file://${project.projectDir}/repo" - } - } -} - -tasks.withType(JavaCompile).configureEach { - options.encoding = 'UTF-8' // Use the UTF-8 charset for Java compilation +plugins { + id 'java-library' + id 'eclipse' + id 'idea' + id 'maven-publish' + id 'net.neoforged.gradle.userdev' version '7.0.26' +} + +group = mod_group_id + +version = "${version != 'unspecified' ? version : '0.1-dev'}" //debuggins sake +configurations { + // configuration that holds jars to include in the jar + extraLibs +} + +repositories { + mavenLocal() +} + +base { + archivesName = 'AdvancedBackups-' + modloaderName + "-" + minecraftVersion +} + + + +// Mojang ships Java 17 to end users in 1.18+, so your mod should target Java 17. +java.toolchain.languageVersion = JavaLanguageVersion.of(17) + +//minecraft.accessTransformers.file rootProject.file('src/main/resources/META-INF/accesstransformer.cfg') +//minecraft.accessTransformers.entry public net.minecraft.client.Minecraft textureManager # textureManager + +// Default run configurations. +// These can be tweaked, removed, or duplicated as needed. +runs { + // applies to all the run configs below + configureEach { + // Recommended logging data for a userdev environment + // The markers can be added/remove as needed separated by commas. + // "SCAN": For mods scan. + // "REGISTRIES": For firing of registry events. + // "REGISTRYDUMP": For getting the contents of all registries. + systemProperty 'forge.logging.markers', 'REGISTRIES' + + // Recommended logging level for the console + // You can set various levels here. + // Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels + systemProperty 'forge.logging.console.level', 'debug' + + modSource project.sourceSets.main + } + + client { + // Comma-separated list of namespaces to load gametests from. Empty = all namespaces. + systemProperty 'forge.enabledGameTestNamespaces', project.mod_id + } + + server { + systemProperty 'forge.enabledGameTestNamespaces', project.mod_id + programArgument '--nogui' + } + + // This run config launches GameTestServer and runs all registered gametests, then exits. + // By default, the server will crash when no gametests are provided. + // The gametest system is also enabled by default for other run configs under the /test command. + gameTestServer { + systemProperty 'forge.enabledGameTestNamespaces', project.mod_id + } + + data { + // example of overriding the workingDirectory set in configureEach above, uncomment if you want to use it + // workingDirectory project.file('run-data') + + // Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources. + programArguments.addAll '--mod', project.mod_id, '--all', '--output', file('src/generated/resources/').getAbsolutePath(), '--existing', file('src/main/resources/').getAbsolutePath() + } +} + +// Include resources generated by data generators. +sourceSets.main.resources { srcDir 'src/generated/resources' } + + +minecraft { + accessTransformers { + file('src/main/resources/META-INF/accesstransformer.cfg') + } +} + +dependencies { + // Specify the version of Minecraft to use. + // Depending on the plugin applied there are several options. We will assume you applied the userdev plugin as shown above. + // The group for userdev is net.neoforged, the module name is neoforge, and the version is the same as the neoforge version. + // You can however also use the vanilla plugin (net.neoforged.gradle.vanilla) to use a version of Minecraft without the neoforge loader. + // And its provides the option to then use net.minecraft as the group, and one of; client, server or joined as the module name, plus the game version as version. + // For all intends and purposes: You can treat this dependency as if it is a normal library you would use. + implementation "net.neoforged:neoforge:${neo_version}" + + + implementation files ('advancedbackups-corelib.jar') + extraLibs files ('advancedbackups-corelib.jar') + + // Example mod dependency with JEI + // The JEI API is declared for compile time use, while the full JEI artifact is used at runtime + // compileOnly "mezz.jei:jei-${mc_version}-common-api:${jei_version}" + // compileOnly "mezz.jei:jei-${mc_version}-forge-api:${jei_version}" + // runtimeOnly "mezz.jei:jei-${mc_version}-forge:${jei_version}" + + // Example mod dependency using a mod jar from ./libs with a flat dir repository + // This maps to ./libs/coolmod-${mc_version}-${coolmod_version}.jar + // The group id is ignored when searching -- in this case, it is "blank" + // implementation "blank:coolmod-${mc_version}:${coolmod_version}" + + // Example mod dependency using a file as dependency + // implementation files("libs/coolmod-${mc_version}-${coolmod_version}.jar") + + // Example project dependency using a sister or child project: + // implementation project(":myproject") + + // For more info: + // http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html + // http://www.gradle.org/docs/current/userguide/dependency_management.html +} + +// This block of code expands all declared replace properties in the specified resource targets. +// A missing property will result in an error. Properties are expanded using ${} Groovy notation. +// When "copyIdeResources" is enabled, this will also run before the game launches in IDE environments. +// See https://docs.gradle.org/current/dsl/org.gradle.language.jvm.tasks.ProcessResources.html +tasks.withType(ProcessResources).configureEach { + var replaceProperties = [ + minecraft_version : minecraft_version, minecraft_version_range: minecraft_version_range, + neo_version : neo_version, neo_version_range: neo_version_range, + loader_version_range: loader_version_range, + mod_id : mod_id, mod_name: mod_name, mod_license: mod_license, mod_version: version, + mod_authors : mod_authors, mod_description: mod_description, pack_format_number: pack_format_number, + ] + inputs.properties replaceProperties + + filesMatching(['META-INF/mods.toml', 'pack.mcmeta']) { + expand replaceProperties + [project: project] + } +} + +// Example for how to get properties into the manifest for reading at runtime. +tasks.named('jar', Jar).configure { + manifest { + attributes([ + "Main-Class" : "co.uk.mommyheather.advancedbackups.cli.AdvancedBackupsCLI", + "Specification-Title" : "advancedbackups", + "Specification-Vendor" : "mommyheather", + "Specification-Version" : "1", // We are version 1 of ourselves + "Implementation-Title" : project.name, + "Implementation-Version" : project.jar.archiveVersion, + "Implementation-Vendor" : "mommyheather", + "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ") + ]) + } + from { + configurations.extraLibs.collect { it.isDirectory() ? it : zipTree(it) } + } +} + +// Example configuration to allow publishing using the maven-publish plugin +publishing { + publications { + register('mavenJava', MavenPublication) { + from components.java + } + } + repositories { + maven { + url "file://${project.projectDir}/repo" + } + } +} + +tasks.withType(JavaCompile).configureEach { + options.encoding = 'UTF-8' // Use the UTF-8 charset for Java compilation } \ No newline at end of file From a26951175861b8eb5180a61965c3a01ffaae4293 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 9 Apr 2024 06:59:39 +0100 Subject: [PATCH 476/580] #57 - gradle versioning, 1.12 --- build.gradle | 271 ++++++++++++++++++---------------- src/main/resources/mcmod.info | 2 +- 2 files changed, 142 insertions(+), 131 deletions(-) diff --git a/build.gradle b/build.gradle index ed67bad4..76dcba57 100644 --- a/build.gradle +++ b/build.gradle @@ -1,130 +1,141 @@ -plugins { - id 'eclipse' - id 'maven-publish' - id 'net.minecraftforge.gradle' version '5.1.+' -} - - -group = 'co.uk.mommyheather.advancedbackups' // http://maven.apache.org/guides/mini/guide-naming-conventions.html -archivesBaseName = 'AdvancedBackups-' + modloaderName + "-" + minecraftVersion - -sourceCompatibility = targetCompatibility = compileJava.sourceCompatibility = compileJava.targetCompatibility = '1.8' // Need this here so eclipse task generates correctly. - - - -task prepareVSCodeRun(type: Copy) { - from jar - into "run/mods" - rename (".*", "advancedbackups-vscode.jar") - //output of the jar task is copied into run/mods, with the name "advancedbackups-vscode.jar", overwriting any existing one -} - -prepareVSCodeRun.mustRunAfter jar - - -minecraft { - // The mappings can be changed at any time, and must be in the following format. - // snapshot_YYYYMMDD Snapshot are built nightly. - // stable_# Stables are built at the discretion of the MCP team. - // Use non-default mappings at your own risk. they may not always work. - // Simply re-run your setup task after changing the mappings to update your workspace. - //mappings channel: 'snapshot', version: '20171003-1.12' - mappings channel: 'snapshot', version: '20171003-1.12' - // makeObfSourceJar = false // an Srg named sources jar is made by default. uncomment this to disable. - - // accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg') - - // Default run configurations. - // These can be tweaked, removed, or duplicated as needed. - runs { - client { - workingDirectory project.file('run') - - // Recommended logging data for a userdev environment - property 'forge.logging.markers', 'SCAN,REGISTRIES,REGISTRYDUMP' - - // Recommended logging level for the console - property 'forge.logging.console.level', 'debug' - } - - server { - - // Recommended logging data for a userdev environment - property 'forge.logging.markers', 'SCAN,REGISTRIES,REGISTRYDUMP' - - // Recommended logging level for the console - property 'forge.logging.console.level', 'debug' - } - } -} - -configurations { - // configuration that holds jars to include in the jar - extraLibs -} - -dependencies { - // Specify the version of Minecraft to use, If this is any group other then 'net.minecraft' it is assumed - // that the dep is a ForgeGradle 'patcher' dependency. And it's patches will be applied. - // The userdev artifact is a special name and will get all sorts of transformations applied to it. - minecraft 'net.minecraftforge:forge:1.12.2-14.23.5.2855' - implementation files ('advancedbackups-corelib.jar') - extraLibs files ('advancedbackups-corelib.jar') - - // You may put jars on which you depend on in ./libs or you may define them like so.. - // compile "some.group:artifact:version:classifier" - // compile "some.group:artifact:version" - - // Real examples - // compile 'com.mod-buildcraft:buildcraft:6.0.8:dev' // adds buildcraft to the dev env - // compile 'com.googlecode.efficient-java-matrix-library:ejml:0.24' // adds ejml to the dev env - - // The 'provided' configuration is for optional dependencies that exist at compile-time but might not at runtime. - // provided 'com.mod-buildcraft:buildcraft:6.0.8:dev' - - // These dependencies get remapped to your current MCP mappings - // deobf 'com.mod-buildcraft:buildcraft:6.0.8:dev' - - // For more info... - // http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html - // http://www.gradle.org/docs/current/userguide/dependency_management.html - -} - -// Example for how to get properties into the manifest for reading by the runtime.. -jar { - manifest { - attributes([ - "Main-Class" : "co.uk.mommyheather.advancedbackups.cli.AdvancedBackupsCLI", - "Specification-Title" : "advancedbackups", - "Specification-Vendor" : "mommyheather", - "Specification-Version" : "1", // We are version 1 of ourselves - "Implementation-Title" : project.name, - "Implementation-Version": "${version}", - "Implementation-Vendor" :"mommyheather", - "Implementation-Vendor" : "mommyheather", - "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ") - ]) - } - from { - configurations.extraLibs.collect { it.isDirectory() ? it : zipTree(it) } - } -} -// Example configuration to allow publishing using the maven-publish task -// This is the preferred method to reobfuscate your jar file -jar.finalizedBy('reobfJar') -// However if you are in a multi-project build, dev time needs unobfed jar files, so you can delay the obfuscation until publishing by doing -//publish.dependsOn('reobfJar') - -publishing { - publications { - mavenJava(MavenPublication) { - artifact jar - } - } - repositories { - maven { - url "file:///${project.projectDir}/mcmodsrepo" - } - } -} +plugins { + id 'eclipse' + id 'maven-publish' + id 'net.minecraftforge.gradle' version '5.1.+' +} + + +group = 'co.uk.mommyheather.advancedbackups' // http://maven.apache.org/guides/mini/guide-naming-conventions.html +archivesBaseName = 'AdvancedBackups-' + modloaderName + "-" + minecraftVersion + +sourceCompatibility = targetCompatibility = compileJava.sourceCompatibility = compileJava.targetCompatibility = '1.8' // Need this here so eclipse task generates correctly. + + + +task prepareVSCodeRun(type: Copy) { + from jar + into "run/mods" + rename (".*", "advancedbackups-vscode.jar") + //output of the jar task is copied into run/mods, with the name "advancedbackups-vscode.jar", overwriting any existing one +} + +prepareVSCodeRun.mustRunAfter jar + + +minecraft { + // The mappings can be changed at any time, and must be in the following format. + // snapshot_YYYYMMDD Snapshot are built nightly. + // stable_# Stables are built at the discretion of the MCP team. + // Use non-default mappings at your own risk. they may not always work. + // Simply re-run your setup task after changing the mappings to update your workspace. + //mappings channel: 'snapshot', version: '20171003-1.12' + mappings channel: 'snapshot', version: '20171003-1.12' + // makeObfSourceJar = false // an Srg named sources jar is made by default. uncomment this to disable. + + // accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg') + + // Default run configurations. + // These can be tweaked, removed, or duplicated as needed. + runs { + client { + workingDirectory project.file('run') + + // Recommended logging data for a userdev environment + property 'forge.logging.markers', 'SCAN,REGISTRIES,REGISTRYDUMP' + + // Recommended logging level for the console + property 'forge.logging.console.level', 'debug' + } + + server { + + // Recommended logging data for a userdev environment + property 'forge.logging.markers', 'SCAN,REGISTRIES,REGISTRYDUMP' + + // Recommended logging level for the console + property 'forge.logging.console.level', 'debug' + } + } +} + +configurations { + // configuration that holds jars to include in the jar + extraLibs +} + +dependencies { + // Specify the version of Minecraft to use, If this is any group other then 'net.minecraft' it is assumed + // that the dep is a ForgeGradle 'patcher' dependency. And it's patches will be applied. + // The userdev artifact is a special name and will get all sorts of transformations applied to it. + minecraft 'net.minecraftforge:forge:1.12.2-14.23.5.2855' + implementation files ('advancedbackups-corelib.jar') + extraLibs files ('advancedbackups-corelib.jar') + + // You may put jars on which you depend on in ./libs or you may define them like so.. + // compile "some.group:artifact:version:classifier" + // compile "some.group:artifact:version" + + // Real examples + // compile 'com.mod-buildcraft:buildcraft:6.0.8:dev' // adds buildcraft to the dev env + // compile 'com.googlecode.efficient-java-matrix-library:ejml:0.24' // adds ejml to the dev env + + // The 'provided' configuration is for optional dependencies that exist at compile-time but might not at runtime. + // provided 'com.mod-buildcraft:buildcraft:6.0.8:dev' + + // These dependencies get remapped to your current MCP mappings + // deobf 'com.mod-buildcraft:buildcraft:6.0.8:dev' + + // For more info... + // http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html + // http://www.gradle.org/docs/current/userguide/dependency_management.html + +} + +// Example for how to get properties into the manifest for reading by the runtime.. +tasks.withType(ProcessResources).configureEach { + var replaceProperties = [ + mod_version: version + ] + inputs.properties replaceProperties + + filesMatching(['mcmod.info']) { + expand replaceProperties + [project: project] + } +} + +jar { + manifest { + attributes([ + "Main-Class" : "co.uk.mommyheather.advancedbackups.cli.AdvancedBackupsCLI", + "Specification-Title" : "advancedbackups", + "Specification-Vendor" : "mommyheather", + "Specification-Version" : "1", // We are version 1 of ourselves + "Implementation-Title" : project.name, + "Implementation-Version": "${version}", + "Implementation-Vendor" :"mommyheather", + "Implementation-Vendor" : "mommyheather", + "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ") + ]) + } + from { + configurations.extraLibs.collect { it.isDirectory() ? it : zipTree(it) } + } +} +// Example configuration to allow publishing using the maven-publish task +// This is the preferred method to reobfuscate your jar file +jar.finalizedBy('reobfJar') +// However if you are in a multi-project build, dev time needs unobfed jar files, so you can delay the obfuscation until publishing by doing +//publish.dependsOn('reobfJar') + +publishing { + publications { + mavenJava(MavenPublication) { + artifact jar + } + } + repositories { + maven { + url "file:///${project.projectDir}/mcmodsrepo" + } + } +} diff --git a/src/main/resources/mcmod.info b/src/main/resources/mcmod.info index e576d9e0..5e32ad6c 100644 --- a/src/main/resources/mcmod.info +++ b/src/main/resources/mcmod.info @@ -3,7 +3,7 @@ "modid": "advancedbackups", "name": "Advanced Backups", "description": "Powerful backup mod.", - "version": "${version}", + "version": "${mod_version}", "url": "https://github.com/MommyHeather/AdvancedBackups", "updateUrl": "", "authorList": ["MommyHeather"], From 519ae54aef6727ccd2afef136d0814b9eccc672d Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 9 Apr 2024 07:10:00 +0100 Subject: [PATCH 477/580] ( # 57 ) gradle versioning in mods.toml sorted --- build.gradle | 381 +++++++++++++------------- src/main/resources/META-INF/mods.toml | 116 ++++---- 2 files changed, 254 insertions(+), 243 deletions(-) diff --git a/build.gradle b/build.gradle index 739a9157..b2a1065c 100644 --- a/build.gradle +++ b/build.gradle @@ -1,185 +1,196 @@ -buildscript { - repositories { - maven { url = 'https://files.minecraftforge.net/maven' } - mavenCentral() - } - dependencies { - classpath group: 'net.minecraftforge.gradle', name: 'ForgeGradle', version: '4.1.+', changing: true - } -} -apply plugin: 'net.minecraftforge.gradle' -// Only edit below this line, the above code adds and enables the necessary things for Forge to be setup. -apply plugin: 'eclipse' -apply plugin: 'maven-publish' - -group = 'co.uk.mommyheather.advancedbackups' // http://maven.apache.org/guides/mini/guide-naming-conventions.html -archivesBaseName = 'AdvancedBackups-' + modloaderName + "-" + minecraftVersion - -java.toolchain.languageVersion = JavaLanguageVersion.of(8) // Mojang ships Java 8 to end users, so your mod should target Java 8. - -println('Java: ' + System.getProperty('java.version') + ' JVM: ' + System.getProperty('java.vm.version') + '(' + System.getProperty('java.vendor') + ') Arch: ' + System.getProperty('os.arch')) -minecraft { - // The mappings can be changed at any time, and must be in the following format. - // Channel: Version: - // snapshot YYYYMMDD Snapshot are built nightly. - // stable # Stables are built at the discretion of the MCP team. - // official MCVersion Official field/method names from Mojang mapping files - // - // You must be aware of the Mojang license when using the 'official' mappings. - // See more information here: https://github.com/MinecraftForge/MCPConfig/blob/master/Mojang.md - // - // Use non-default mappings at your own risk. they may not always work. - // Simply re-run your setup task after changing the mappings to update your workspace. - mappings channel: 'official', version: '1.16.5' - // makeObfSourceJar = false // an Srg named sources jar is made by default. uncomment this to disable. - - accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg') - - // Default run configurations. - // These can be tweaked, removed, or duplicated as needed. - runs { - client { - workingDirectory project.file('run') - - // Recommended logging data for a userdev environment - // The markers can be changed as needed. - // "SCAN": For mods scan. - // "REGISTRIES": For firing of registry events. - // "REGISTRYDUMP": For getting the contents of all registries. - property 'forge.logging.markers', 'REGISTRIES' - - // Recommended logging level for the console - // You can set various levels here. - // Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels - property 'forge.logging.console.level', 'debug' - - mods { - AdvancedBackups { - source sourceSets.main - } - } - } - - server { - workingDirectory project.file('run') - - // Recommended logging data for a userdev environment - // The markers can be changed as needed. - // "SCAN": For mods scan. - // "REGISTRIES": For firing of registry events. - // "REGISTRYDUMP": For getting the contents of all registries. - property 'forge.logging.markers', 'REGISTRIES' - - // Recommended logging level for the console - // You can set various levels here. - // Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels - property 'forge.logging.console.level', 'debug' - - mods { - AdvancedBackups { - source sourceSets.main - } - } - } - - data { - workingDirectory project.file('run') - - // Recommended logging data for a userdev environment - // The markers can be changed as needed. - // "SCAN": For mods scan. - // "REGISTRIES": For firing of registry events. - // "REGISTRYDUMP": For getting the contents of all registries. - property 'forge.logging.markers', 'REGISTRIES' - - // Recommended logging level for the console - // You can set various levels here. - // Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels - property 'forge.logging.console.level', 'debug' - - // Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources. - args '--mod', 'AdvancedBackups', '--all', '--output', file('src/generated/resources/'), '--existing', file('src/main/resources/') - - mods { - AdvancedBackups { - source sourceSets.main - } - } - } - } -} - -// Include resources generated by data generators. -sourceSets.main.resources { srcDir 'src/generated/resources' } - -configurations { - // configuration that holds jars to include in the jar - extraLibs -} - -dependencies { - // Specify the version of Minecraft to use, If this is any group other then 'net.minecraft' it is assumed - // that the dep is a ForgeGradle 'patcher' dependency. And it's patches will be applied. - // The userdev artifact is a special name and will get all sorts of transformations applied to it. - minecraft 'net.minecraftforge:forge:1.16.5-36.1.0' - - implementation files ('advancedbackups-corelib.jar') - extraLibs files ('advancedbackups-corelib.jar') - // You may put jars on which you depend on in ./libs or you may define them like so.. - // compile "some.group:artifact:version:classifier" - // compile "some.group:artifact:version" - - // Real examples - // compile 'com.mod-buildcraft:buildcraft:6.0.8:dev' // adds buildcraft to the dev env - // compile 'com.googlecode.efficient-java-matrix-library:ejml:0.24' // adds ejml to the dev env - - // The 'provided' configuration is for optional dependencies that exist at compile-time but might not at runtime. - // provided 'com.mod-buildcraft:buildcraft:6.0.8:dev' - - // These dependencies get remapped to your current MCP mappings - // deobf 'com.mod-buildcraft:buildcraft:6.0.8:dev' - - // For more info... - // http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html - // http://www.gradle.org/docs/current/userguide/dependency_management.html - -} - -// Example for how to get properties into the manifest for reading by the runtime.. -jar { - manifest { - attributes([ - "Main-Class" : "co.uk.mommyheather.advancedbackups.cli.AdvancedBackupsCLI", - "Specification-Title" : "advancedbackups", - "Specification-Vendor" : "mommyheather", - "Specification-Version" : "1", // We are version 1 of ourselves - "Implementation-Title" : project.name, - "Implementation-Version": "${version}", - "Implementation-Vendor" :"mommyheather", - "Implementation-Vendor" : "mommyheather", - "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ") - ]) - } - from { - configurations.extraLibs.collect { it.isDirectory() ? it : zipTree(it) } - } -} - -// Example configuration to allow publishing using the maven-publish task -// This is the preferred method to reobfuscate your jar file -jar.finalizedBy('reobfJar') -// However if you are in a multi-project build, dev time needs unobfed jar files, so you can delay the obfuscation until publishing by doing -//publish.dependsOn('reobfJar') - -publishing { - publications { - mavenJava(MavenPublication) { - artifact jar - } - } - repositories { - maven { - url "file:///${project.projectDir}/mcmodsrepo" - } - } -} +buildscript { + repositories { + maven { url = 'https://files.minecraftforge.net/maven' } + mavenCentral() + } + dependencies { + classpath group: 'net.minecraftforge.gradle', name: 'ForgeGradle', version: '4.1.+', changing: true + } +} +apply plugin: 'net.minecraftforge.gradle' +// Only edit below this line, the above code adds and enables the necessary things for Forge to be setup. +apply plugin: 'eclipse' +apply plugin: 'maven-publish' + +group = 'co.uk.mommyheather.advancedbackups' // http://maven.apache.org/guides/mini/guide-naming-conventions.html +archivesBaseName = 'AdvancedBackups-' + modloaderName + "-" + minecraftVersion + +java.toolchain.languageVersion = JavaLanguageVersion.of(8) // Mojang ships Java 8 to end users, so your mod should target Java 8. + +println('Java: ' + System.getProperty('java.version') + ' JVM: ' + System.getProperty('java.vm.version') + '(' + System.getProperty('java.vendor') + ') Arch: ' + System.getProperty('os.arch')) +minecraft { + // The mappings can be changed at any time, and must be in the following format. + // Channel: Version: + // snapshot YYYYMMDD Snapshot are built nightly. + // stable # Stables are built at the discretion of the MCP team. + // official MCVersion Official field/method names from Mojang mapping files + // + // You must be aware of the Mojang license when using the 'official' mappings. + // See more information here: https://github.com/MinecraftForge/MCPConfig/blob/master/Mojang.md + // + // Use non-default mappings at your own risk. they may not always work. + // Simply re-run your setup task after changing the mappings to update your workspace. + mappings channel: 'official', version: '1.16.5' + // makeObfSourceJar = false // an Srg named sources jar is made by default. uncomment this to disable. + + accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg') + + // Default run configurations. + // These can be tweaked, removed, or duplicated as needed. + runs { + client { + workingDirectory project.file('run') + + // Recommended logging data for a userdev environment + // The markers can be changed as needed. + // "SCAN": For mods scan. + // "REGISTRIES": For firing of registry events. + // "REGISTRYDUMP": For getting the contents of all registries. + property 'forge.logging.markers', 'REGISTRIES' + + // Recommended logging level for the console + // You can set various levels here. + // Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels + property 'forge.logging.console.level', 'debug' + + mods { + AdvancedBackups { + source sourceSets.main + } + } + } + + server { + workingDirectory project.file('run') + + // Recommended logging data for a userdev environment + // The markers can be changed as needed. + // "SCAN": For mods scan. + // "REGISTRIES": For firing of registry events. + // "REGISTRYDUMP": For getting the contents of all registries. + property 'forge.logging.markers', 'REGISTRIES' + + // Recommended logging level for the console + // You can set various levels here. + // Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels + property 'forge.logging.console.level', 'debug' + + mods { + AdvancedBackups { + source sourceSets.main + } + } + } + + data { + workingDirectory project.file('run') + + // Recommended logging data for a userdev environment + // The markers can be changed as needed. + // "SCAN": For mods scan. + // "REGISTRIES": For firing of registry events. + // "REGISTRYDUMP": For getting the contents of all registries. + property 'forge.logging.markers', 'REGISTRIES' + + // Recommended logging level for the console + // You can set various levels here. + // Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels + property 'forge.logging.console.level', 'debug' + + // Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources. + args '--mod', 'AdvancedBackups', '--all', '--output', file('src/generated/resources/'), '--existing', file('src/main/resources/') + + mods { + AdvancedBackups { + source sourceSets.main + } + } + } + } +} + +// Include resources generated by data generators. +sourceSets.main.resources { srcDir 'src/generated/resources' } + +configurations { + // configuration that holds jars to include in the jar + extraLibs +} + +dependencies { + // Specify the version of Minecraft to use, If this is any group other then 'net.minecraft' it is assumed + // that the dep is a ForgeGradle 'patcher' dependency. And it's patches will be applied. + // The userdev artifact is a special name and will get all sorts of transformations applied to it. + minecraft 'net.minecraftforge:forge:1.16.5-36.1.0' + + implementation files ('advancedbackups-corelib.jar') + extraLibs files ('advancedbackups-corelib.jar') + // You may put jars on which you depend on in ./libs or you may define them like so.. + // compile "some.group:artifact:version:classifier" + // compile "some.group:artifact:version" + + // Real examples + // compile 'com.mod-buildcraft:buildcraft:6.0.8:dev' // adds buildcraft to the dev env + // compile 'com.googlecode.efficient-java-matrix-library:ejml:0.24' // adds ejml to the dev env + + // The 'provided' configuration is for optional dependencies that exist at compile-time but might not at runtime. + // provided 'com.mod-buildcraft:buildcraft:6.0.8:dev' + + // These dependencies get remapped to your current MCP mappings + // deobf 'com.mod-buildcraft:buildcraft:6.0.8:dev' + + // For more info... + // http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html + // http://www.gradle.org/docs/current/userguide/dependency_management.html + +} + +tasks.withType(ProcessResources).configureEach { + def replaceProperties = [ + mod_version: version + ] + inputs.properties replaceProperties + + filesMatching(['META-INF/mods.toml']) { + expand replaceProperties + [project: project] + } +} + +// Example for how to get properties into the manifest for reading by the runtime.. +jar { + manifest { + attributes([ + "Main-Class" : "co.uk.mommyheather.advancedbackups.cli.AdvancedBackupsCLI", + "Specification-Title" : "advancedbackups", + "Specification-Vendor" : "mommyheather", + "Specification-Version" : "1", // We are version 1 of ourselves + "Implementation-Title" : project.name, + "Implementation-Version": "${version}", + "Implementation-Vendor" :"mommyheather", + "Implementation-Vendor" : "mommyheather", + "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ") + ]) + } + from { + configurations.extraLibs.collect { it.isDirectory() ? it : zipTree(it) } + } +} + +// Example configuration to allow publishing using the maven-publish task +// This is the preferred method to reobfuscate your jar file +jar.finalizedBy('reobfJar') +// However if you are in a multi-project build, dev time needs unobfed jar files, so you can delay the obfuscation until publishing by doing +//publish.dependsOn('reobfJar') + +publishing { + publications { + mavenJava(MavenPublication) { + artifact jar + } + } + repositories { + maven { + url "file:///${project.projectDir}/mcmodsrepo" + } + } +} diff --git a/src/main/resources/META-INF/mods.toml b/src/main/resources/META-INF/mods.toml index cdf61fed..645fa28b 100644 --- a/src/main/resources/META-INF/mods.toml +++ b/src/main/resources/META-INF/mods.toml @@ -1,58 +1,58 @@ -# This is an example mods.toml file. It contains the data relating to the loading mods. -# There are several mandatory fields (#mandatory), and many more that are optional (#optional). -# The overall format is standard TOML format, v0.5.0. -# Note that there are a couple of TOML lists in this file. -# Find more information on toml format here: https://github.com/toml-lang/toml -# The name of the mod loader type to load - for regular FML @Mod mods it should be javafml -modLoader="javafml" #mandatory -# A version range to match for said mod loader - for regular FML @Mod it will be the forge version -loaderVersion="[34,)" #mandatory This is typically bumped every Minecraft version by Forge. See our download page for lists of versions. -# The license for you mod. This is mandatory metadata and allows for easier comprehension of your redistributive properties. -# Review your options at https://choosealicense.com/. All rights reserved is the default copyright stance, and is thus the default here. -license="MIT" -# A URL to refer people to when problems occur with this mod -#issueTrackerURL="https://change.me.to.your.issue.tracker.example.invalid/" #optional -# A list of mods - how many allowed here is determined by the individual mod loader -[[mods]] #mandatory -# The modid of the mod -modId="advancedbackups" #mandatory -# The version number of the mod - there's a few well known ${} variables useable here or just hardcode it -# ${file.jarVersion} will substitute the value of the Implementation-Version as read from the mod's JAR file metadata -# see the associated build.gradle script for how to populate this completely automatically during a build -version="${file.jarVersion}" #mandatory - # A display name for the mod -displayName="Advanced Backups" #mandatory -# A URL to query for updates for this mod. See the JSON update specification https://mcforge.readthedocs.io/en/latest/gettingstarted/autoupdate/ -#updateJSONURL="https://change.me.example.invalid/updates.json" #optional -# A URL for the "homepage" for this mod, displayed in the mod UI -#displayURL="https://change.me.to.your.mods.homepage.example.invalid/" #optional -# A file name (in the root of the mod JAR) containing a logo for display -#logoFile="examplemod.png" #optional -# A text field displayed in the mod UI -#credits="Thanks for this example mod goes to Java" #optional -# A text field displayed in the mod UI -authors="Mommy Heather" #optional -# The description text for the mod (multi line!) (#mandatory) -description=''' -A powerful and highly configurable backup mod. Visit https://github.com/MommyHeather/AdvancedBackups for more info. -''' -# A dependency - use the . to indicate dependency for a specific modid. Dependencies are optional. -[[dependencies.advancedbackups]] #optional - # the modid of the dependency - modId="forge" #mandatory - # Does this dependency have to exist - if not, ordering below must be specified - mandatory=true #mandatory - # The version range of the dependency - versionRange="[34,)" #mandatory - # An ordering relationship for the dependency - BEFORE or AFTER required if the relationship is not mandatory - ordering="NONE" - # Side this dependency is applied on - BOTH, CLIENT or SERVER - side="BOTH" -# Here's another dependency -[[dependencies.advancedbackups]] - modId="minecraft" - mandatory=true -# This version range declares a minimum of the current minecraft version up to but not including the next major version - versionRange="[1.16,1.17)" - ordering="NONE" - side="BOTH" +# This is an example mods.toml file. It contains the data relating to the loading mods. +# There are several mandatory fields (#mandatory), and many more that are optional (#optional). +# The overall format is standard TOML format, v0.5.0. +# Note that there are a couple of TOML lists in this file. +# Find more information on toml format here: https://github.com/toml-lang/toml +# The name of the mod loader type to load - for regular FML @Mod mods it should be javafml +modLoader="javafml" #mandatory +# A version range to match for said mod loader - for regular FML @Mod it will be the forge version +loaderVersion="[34,)" #mandatory This is typically bumped every Minecraft version by Forge. See our download page for lists of versions. +# The license for you mod. This is mandatory metadata and allows for easier comprehension of your redistributive properties. +# Review your options at https://choosealicense.com/. All rights reserved is the default copyright stance, and is thus the default here. +license="MIT" +# A URL to refer people to when problems occur with this mod +#issueTrackerURL="https://change.me.to.your.issue.tracker.example.invalid/" #optional +# A list of mods - how many allowed here is determined by the individual mod loader +[[mods]] #mandatory +# The modid of the mod +modId="advancedbackups" #mandatory +# The version number of the mod - there's a few well known ${} variables useable here or just hardcode it +# {file.jarVersion} will substitute the value of the Implementation-Version as read from the mod's JAR file metadata +# see the associated build.gradle script for how to populate this completely automatically during a build +version="${mod_version}" #mandatory + # A display name for the mod +displayName="Advanced Backups" #mandatory +# A URL to query for updates for this mod. See the JSON update specification https://mcforge.readthedocs.io/en/latest/gettingstarted/autoupdate/ +#updateJSONURL="https://change.me.example.invalid/updates.json" #optional +# A URL for the "homepage" for this mod, displayed in the mod UI +#displayURL="https://change.me.to.your.mods.homepage.example.invalid/" #optional +# A file name (in the root of the mod JAR) containing a logo for display +#logoFile="examplemod.png" #optional +# A text field displayed in the mod UI +#credits="Thanks for this example mod goes to Java" #optional +# A text field displayed in the mod UI +authors="Mommy Heather" #optional +# The description text for the mod (multi line!) (#mandatory) +description=''' +A powerful and highly configurable backup mod. Visit https://github.com/MommyHeather/AdvancedBackups for more info. +''' +# A dependency - use the . to indicate dependency for a specific modid. Dependencies are optional. +[[dependencies.advancedbackups]] #optional + # the modid of the dependency + modId="forge" #mandatory + # Does this dependency have to exist - if not, ordering below must be specified + mandatory=true #mandatory + # The version range of the dependency + versionRange="[34,)" #mandatory + # An ordering relationship for the dependency - BEFORE or AFTER required if the relationship is not mandatory + ordering="NONE" + # Side this dependency is applied on - BOTH, CLIENT or SERVER + side="BOTH" +# Here's another dependency +[[dependencies.advancedbackups]] + modId="minecraft" + mandatory=true +# This version range declares a minimum of the current minecraft version up to but not including the next major version + versionRange="[1.16,1.17)" + ordering="NONE" + side="BOTH" From 219537dd83093698fd83e747466511cd9c24ede3 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 9 Apr 2024 07:15:13 +0100 Subject: [PATCH 478/580] ( #57 ) gradle versioning, forge 1.18 --- build.gradle | 445 +++++++++++++------------- src/main/resources/META-INF/mods.toml | 4 +- 2 files changed, 230 insertions(+), 219 deletions(-) diff --git a/build.gradle b/build.gradle index 74f0a710..9b8cacc4 100644 --- a/build.gradle +++ b/build.gradle @@ -1,217 +1,228 @@ -buildscript { - repositories { - // These repositories are only for Gradle plugins, put any other repositories in the repository block further below - maven { url = 'https://maven.minecraftforge.net' } - mavenCentral() - } - dependencies { - classpath group: 'net.minecraftforge.gradle', name: 'ForgeGradle', version: '5.1.+', changing: true - } -} -// Only edit below this line, the above code adds and enables the necessary things for Forge to be setup. -plugins { - id 'eclipse' - id 'maven-publish' -} -apply plugin: 'net.minecraftforge.gradle' - - -group = 'co.uk.mommyheather.advancedbackups' // http://maven.apache.org/guides/mini/guide-naming-conventions.html -archivesBaseName = 'AdvancedBackups-' + modloaderName + "-" + minecraftVersion - -// Mojang ships Java 17 to end users in 1.18+, so your mod should target Java 17. -java.toolchain.languageVersion = JavaLanguageVersion.of(17) - -println "Java: ${System.getProperty 'java.version'}, JVM: ${System.getProperty 'java.vm.version'} (${System.getProperty 'java.vendor'}), Arch: ${System.getProperty 'os.arch'}" -minecraft { - // The mappings can be changed at any time and must be in the following format. - // Channel: Version: - // official MCVersion Official field/method names from Mojang mapping files - // parchment YYYY.MM.DD-MCVersion Open community-sourced parameter names and javadocs layered on top of official - // - // You must be aware of the Mojang license when using the 'official' or 'parchment' mappings. - // See more information here: https://github.com/MinecraftForge/MCPConfig/blob/master/Mojang.md - // - // Parchment is an unofficial project maintained by ParchmentMC, separate from MinecraftForge - // Additional setup is needed to use their mappings: https://github.com/ParchmentMC/Parchment/wiki/Getting-Started - // - // Use non-default mappings at your own risk. They may not always work. - // Simply re-run your setup task after changing the mappings to update your workspace. - mappings channel: 'official', version: '1.18.2' - - // accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg') // Currently, this location cannot be changed from the default. - - // Default run configurations. - // These can be tweaked, removed, or duplicated as needed. - runs { - client { - workingDirectory project.file('run') - - // Recommended logging data for a userdev environment - // The markers can be added/remove as needed separated by commas. - // "SCAN": For mods scan. - // "REGISTRIES": For firing of registry events. - // "REGISTRYDUMP": For getting the contents of all registries. - property 'forge.logging.markers', 'REGISTRIES' - - // Recommended logging level for the console - // You can set various levels here. - // Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels - property 'forge.logging.console.level', 'debug' - - // Comma-separated list of namespaces to load gametests from. Empty = all namespaces. - property 'forge.enabledGameTestNamespaces', 'advancedbackups' - - mods { - advancedbackups { - source sourceSets.main - } - } - } - - server { - workingDirectory project.file('run') - - property 'forge.logging.markers', 'REGISTRIES' - - property 'forge.logging.console.level', 'debug' - - // Comma-separated list of namespaces to load gametests from. Empty = all namespaces. - property 'forge.enabledGameTestNamespaces', 'advancedbackups' - - mods { - advancedbackups { - source sourceSets.main - } - } - } - - // This run config launches GameTestServer and runs all registered gametests, then exits. - // By default, the server will crash when no gametests are provided. - // The gametest system is also enabled by default for other run configs under the /test command. - gameTestServer { - workingDirectory project.file('run') - - // Recommended logging data for a userdev environment - // The markers can be added/remove as needed separated by commas. - // "SCAN": For mods scan. - // "REGISTRIES": For firing of registry events. - // "REGISTRYDUMP": For getting the contents of all registries. - property 'forge.logging.markers', 'REGISTRIES' - - // Recommended logging level for the console - // You can set various levels here. - // Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels - property 'forge.logging.console.level', 'debug' - - // Comma-separated list of namespaces to load gametests from. Empty = all namespaces. - property 'forge.enabledGameTestNamespaces', 'advancedbackups' - - mods { - advancedbackups { - source sourceSets.main - } - } - } - - data { - workingDirectory project.file('run') - - property 'forge.logging.markers', 'REGISTRIES' - - property 'forge.logging.console.level', 'debug' - - // Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources. - args '--mod', 'advancedbackups', '--all', '--output', file('src/generated/resources/'), '--existing', file('src/main/resources/') - - mods { - advancedbackups { - source sourceSets.main - } - } - } - } -} - -// Include resources generated by data generators. -sourceSets.main.resources { srcDir 'src/generated/resources' } - -repositories { - // Put repositories for dependencies here - // ForgeGradle automatically adds the Forge maven and Maven Central for you - - // If you have mod jar dependencies in ./libs, you can declare them as a repository like so: - // flatDir { - // dir 'libs' - // } -} - -configurations { - // configuration that holds jars to include in the jar - extraLibs -} - -dependencies { - // Specify the version of Minecraft to use. If this is any group other than 'net.minecraft', it is assumed - // that the dep is a ForgeGradle 'patcher' dependency, and its patches will be applied. - // The userdev artifact is a special name and will get all sorts of transformations applied to it. - minecraft 'net.minecraftforge:forge:1.18.2-40.2.1' - //extraLibs 'com.sun.jna.platform:5.13.0' - - minecraftLibrary files ('advancedbackups-corelib.jar') - extraLibs files ('advancedbackups-corelib.jar') - - // Real mod deobf dependency examples - these get remapped to your current mappings - // compileOnly fg.deobf("mezz.jei:jei-${mc_version}:${jei_version}:api") // Adds JEI API as a compile dependency - // runtimeOnly fg.deobf("mezz.jei:jei-${mc_version}:${jei_version}") // Adds the full JEI mod as a runtime dependency - // implementation fg.deobf("com.tterrag.registrate:Registrate:MC${mc_version}-${registrate_version}") // Adds registrate as a dependency - - // Examples using mod jars from ./libs - // implementation fg.deobf("blank:coolmod-${mc_version}:${coolmod_version}") - - // For more info... - // http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html - // http://www.gradle.org/docs/current/userguide/dependency_management.html -} - -// Example for how to get properties into the manifest for reading at runtime. -jar { - manifest { - attributes([ - "Main-Class" : "co.uk.mommyheather.advancedbackups.cli.AdvancedBackupsCLI", - "Specification-Title" : "advancedbackups", - "Specification-Vendor" : "mommyheather", - "Specification-Version" : "1", // We are version 1 of ourselves - "Implementation-Title" : project.name, - "Implementation-Version" : project.jar.archiveVersion, - "Implementation-Vendor" : "mommyheather", - "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ") - ]) - } - from { - configurations.extraLibs.collect { it.isDirectory() ? it : zipTree(it) } - } -} - -// Example configuration to allow publishing using the maven-publish plugin -// This is the preferred method to reobfuscate your jar file -jar.finalizedBy('reobfJar') -// However if you are in a multi-project build, dev time needs unobfed jar files, so you can delay the obfuscation until publishing by doing -// publish.dependsOn('reobfJar') - -publishing { - publications { - mavenJava(MavenPublication) { - artifact jar - } - } - repositories { - maven { - url "file://${project.projectDir}/mcmodsrepo" - } - } -} - -tasks.withType(JavaCompile).configureEach { - options.encoding = 'UTF-8' // Use the UTF-8 charset for Java compilation -} +buildscript { + repositories { + // These repositories are only for Gradle plugins, put any other repositories in the repository block further below + maven { url = 'https://maven.minecraftforge.net' } + mavenCentral() + } + dependencies { + classpath group: 'net.minecraftforge.gradle', name: 'ForgeGradle', version: '5.1.+', changing: true + } +} +// Only edit below this line, the above code adds and enables the necessary things for Forge to be setup. +plugins { + id 'eclipse' + id 'maven-publish' +} +apply plugin: 'net.minecraftforge.gradle' + + +group = 'co.uk.mommyheather.advancedbackups' // http://maven.apache.org/guides/mini/guide-naming-conventions.html +archivesBaseName = 'AdvancedBackups-' + modloaderName + "-" + minecraftVersion + +// Mojang ships Java 17 to end users in 1.18+, so your mod should target Java 17. +java.toolchain.languageVersion = JavaLanguageVersion.of(17) + +println "Java: ${System.getProperty 'java.version'}, JVM: ${System.getProperty 'java.vm.version'} (${System.getProperty 'java.vendor'}), Arch: ${System.getProperty 'os.arch'}" +minecraft { + // The mappings can be changed at any time and must be in the following format. + // Channel: Version: + // official MCVersion Official field/method names from Mojang mapping files + // parchment YYYY.MM.DD-MCVersion Open community-sourced parameter names and javadocs layered on top of official + // + // You must be aware of the Mojang license when using the 'official' or 'parchment' mappings. + // See more information here: https://github.com/MinecraftForge/MCPConfig/blob/master/Mojang.md + // + // Parchment is an unofficial project maintained by ParchmentMC, separate from MinecraftForge + // Additional setup is needed to use their mappings: https://github.com/ParchmentMC/Parchment/wiki/Getting-Started + // + // Use non-default mappings at your own risk. They may not always work. + // Simply re-run your setup task after changing the mappings to update your workspace. + mappings channel: 'official', version: '1.18.2' + + // accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg') // Currently, this location cannot be changed from the default. + + // Default run configurations. + // These can be tweaked, removed, or duplicated as needed. + runs { + client { + workingDirectory project.file('run') + + // Recommended logging data for a userdev environment + // The markers can be added/remove as needed separated by commas. + // "SCAN": For mods scan. + // "REGISTRIES": For firing of registry events. + // "REGISTRYDUMP": For getting the contents of all registries. + property 'forge.logging.markers', 'REGISTRIES' + + // Recommended logging level for the console + // You can set various levels here. + // Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels + property 'forge.logging.console.level', 'debug' + + // Comma-separated list of namespaces to load gametests from. Empty = all namespaces. + property 'forge.enabledGameTestNamespaces', 'advancedbackups' + + mods { + advancedbackups { + source sourceSets.main + } + } + } + + server { + workingDirectory project.file('run') + + property 'forge.logging.markers', 'REGISTRIES' + + property 'forge.logging.console.level', 'debug' + + // Comma-separated list of namespaces to load gametests from. Empty = all namespaces. + property 'forge.enabledGameTestNamespaces', 'advancedbackups' + + mods { + advancedbackups { + source sourceSets.main + } + } + } + + // This run config launches GameTestServer and runs all registered gametests, then exits. + // By default, the server will crash when no gametests are provided. + // The gametest system is also enabled by default for other run configs under the /test command. + gameTestServer { + workingDirectory project.file('run') + + // Recommended logging data for a userdev environment + // The markers can be added/remove as needed separated by commas. + // "SCAN": For mods scan. + // "REGISTRIES": For firing of registry events. + // "REGISTRYDUMP": For getting the contents of all registries. + property 'forge.logging.markers', 'REGISTRIES' + + // Recommended logging level for the console + // You can set various levels here. + // Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels + property 'forge.logging.console.level', 'debug' + + // Comma-separated list of namespaces to load gametests from. Empty = all namespaces. + property 'forge.enabledGameTestNamespaces', 'advancedbackups' + + mods { + advancedbackups { + source sourceSets.main + } + } + } + + data { + workingDirectory project.file('run') + + property 'forge.logging.markers', 'REGISTRIES' + + property 'forge.logging.console.level', 'debug' + + // Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources. + args '--mod', 'advancedbackups', '--all', '--output', file('src/generated/resources/'), '--existing', file('src/main/resources/') + + mods { + advancedbackups { + source sourceSets.main + } + } + } + } +} + +// Include resources generated by data generators. +sourceSets.main.resources { srcDir 'src/generated/resources' } + +repositories { + // Put repositories for dependencies here + // ForgeGradle automatically adds the Forge maven and Maven Central for you + + // If you have mod jar dependencies in ./libs, you can declare them as a repository like so: + // flatDir { + // dir 'libs' + // } +} + +configurations { + // configuration that holds jars to include in the jar + extraLibs +} + +dependencies { + // Specify the version of Minecraft to use. If this is any group other than 'net.minecraft', it is assumed + // that the dep is a ForgeGradle 'patcher' dependency, and its patches will be applied. + // The userdev artifact is a special name and will get all sorts of transformations applied to it. + minecraft 'net.minecraftforge:forge:1.18.2-40.2.1' + //extraLibs 'com.sun.jna.platform:5.13.0' + + minecraftLibrary files ('advancedbackups-corelib.jar') + extraLibs files ('advancedbackups-corelib.jar') + + // Real mod deobf dependency examples - these get remapped to your current mappings + // compileOnly fg.deobf("mezz.jei:jei-${mc_version}:${jei_version}:api") // Adds JEI API as a compile dependency + // runtimeOnly fg.deobf("mezz.jei:jei-${mc_version}:${jei_version}") // Adds the full JEI mod as a runtime dependency + // implementation fg.deobf("com.tterrag.registrate:Registrate:MC${mc_version}-${registrate_version}") // Adds registrate as a dependency + + // Examples using mod jars from ./libs + // implementation fg.deobf("blank:coolmod-${mc_version}:${coolmod_version}") + + // For more info... + // http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html + // http://www.gradle.org/docs/current/userguide/dependency_management.html +} + +tasks.withType(ProcessResources).configureEach { + def replaceProperties = [ + mod_version: version + ] + inputs.properties replaceProperties + + filesMatching(['META-INF/mods.toml']) { + expand replaceProperties + [project: project] + } +} + +// Example for how to get properties into the manifest for reading at runtime. +jar { + manifest { + attributes([ + "Main-Class" : "co.uk.mommyheather.advancedbackups.cli.AdvancedBackupsCLI", + "Specification-Title" : "advancedbackups", + "Specification-Vendor" : "mommyheather", + "Specification-Version" : "1", // We are version 1 of ourselves + "Implementation-Title" : project.name, + "Implementation-Version" : project.jar.archiveVersion, + "Implementation-Vendor" : "mommyheather", + "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ") + ]) + } + from { + configurations.extraLibs.collect { it.isDirectory() ? it : zipTree(it) } + } +} + +// Example configuration to allow publishing using the maven-publish plugin +// This is the preferred method to reobfuscate your jar file +jar.finalizedBy('reobfJar') +// However if you are in a multi-project build, dev time needs unobfed jar files, so you can delay the obfuscation until publishing by doing +// publish.dependsOn('reobfJar') + +publishing { + publications { + mavenJava(MavenPublication) { + artifact jar + } + } + repositories { + maven { + url "file://${project.projectDir}/mcmodsrepo" + } + } +} + +tasks.withType(JavaCompile).configureEach { + options.encoding = 'UTF-8' // Use the UTF-8 charset for Java compilation +} diff --git a/src/main/resources/META-INF/mods.toml b/src/main/resources/META-INF/mods.toml index ad0e6ca5..cf04c977 100644 --- a/src/main/resources/META-INF/mods.toml +++ b/src/main/resources/META-INF/mods.toml @@ -17,9 +17,9 @@ license="MIT" # The modid of the mod modId="advancedbackups" #mandatory # The version number of the mod - there's a few well known ${} variables useable here or just hardcode it -# ${file.jarVersion} will substitute the value of the Implementation-Version as read from the mod's JAR file metadata +# {file.jarVersion} will substitute the value of the Implementation-Version as read from the mod's JAR file metadata # see the associated build.gradle script for how to populate this completely automatically during a build -version="${file.jarVersion}" #mandatory +version="${mod_version}" #mandatory # A display name for the mod displayName="Advanced Backups" #mandatory # A URL to query for updates for this mod. See the JSON update specification https://mcforge.readthedocs.io/en/latest/gettingstarted/autoupdate/ From 4ba6c66c0b3c61b1d5a82b4aace9c1dc0ca04303 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 9 Apr 2024 07:24:48 +0100 Subject: [PATCH 479/580] ( #57 ) gradle versioning on 1.19.2 forge --- build.gradle | 371 +++++++++++++------------- src/main/resources/META-INF/mods.toml | 126 ++++----- 2 files changed, 254 insertions(+), 243 deletions(-) diff --git a/build.gradle b/build.gradle index acd8118d..8d7c1c20 100644 --- a/build.gradle +++ b/build.gradle @@ -1,180 +1,191 @@ -plugins { - id 'eclipse' - id 'maven-publish' - id 'net.minecraftforge.gradle' version '5.1.+' -} - - - -group = 'co.uk.mommyheather.advancedbackups' // http://maven.apache.org/guides/mini/guide-naming-conventions.html -archivesBaseName = 'AdvancedBackups-' + modloaderName + "-" + minecraftVersion - -// Mojang ships Java 17 to end users in 1.18+, so your mod should target Java 17. -java.toolchain.languageVersion = JavaLanguageVersion.of(17) - -println "Java: ${System.getProperty 'java.version'}, JVM: ${System.getProperty 'java.vm.version'} (${System.getProperty 'java.vendor'}), Arch: ${System.getProperty 'os.arch'}" -minecraft { - // The mappings can be changed at any time and must be in the following format. - // Channel: Version: - // official MCVersion Official field/method names from Mojang mapping files - // parchment YYYY.MM.DD-MCVersion Open community-sourced parameter names and javadocs layered on top of official - // - // You must be aware of the Mojang license when using the 'official' or 'parchment' mappings. - // See more information here: https://github.com/MinecraftForge/MCPConfig/blob/master/Mojang.md - // - // Parchment is an unofficial project maintained by ParchmentMC, separate from MinecraftForge - // Additional setup is needed to use their mappings: https://github.com/ParchmentMC/Parchment/wiki/Getting-Started - // - // Use non-default mappings at your own risk. They may not always work. - // Simply re-run your setup task after changing the mappings to update your workspace. - mappings channel: 'official', version: '1.19.2' - - // accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg') // Currently, this location cannot be changed from the default. - - // Default run configurations. - // These can be tweaked, removed, or duplicated as needed. - runs { - client { - workingDirectory project.file('run') - - // Recommended logging data for a userdev environment - // The markers can be added/remove as needed separated by commas. - // "SCAN": For mods scan. - // "REGISTRIES": For firing of registry events. - // "REGISTRYDUMP": For getting the contents of all registries. - property 'forge.logging.markers', 'REGISTRIES' - - // Recommended logging level for the console - // You can set various levels here. - // Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels - property 'forge.logging.console.level', 'debug' - - // Comma-separated list of namespaces to load gametests from. Empty = all namespaces. - property 'forge.enabledGameTestNamespaces', 'advancedbackups' - - mods { - advancedbackups { - source sourceSets.main - } - } - } - - server { - workingDirectory project.file('run') - - property 'forge.logging.markers', 'REGISTRIES' - - property 'forge.logging.console.level', 'debug' - - // Comma-separated list of namespaces to load gametests from. Empty = all namespaces. - property 'forge.enabledGameTestNamespaces', 'advancedbackups' - - mods { - advancedbackups { - source sourceSets.main - } - } - } - - data { - workingDirectory project.file('run') - - property 'forge.logging.markers', 'REGISTRIES' - - property 'forge.logging.console.level', 'debug' - - // Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources. - args '--mod', 'advancedbackups', '--all', '--output', file('src/generated/resources/'), '--existing', file('src/main/resources/') - - mods { - advancedbackups { - source sourceSets.main - } - } - } - } -} - -// Include resources generated by data generators. -sourceSets.main.resources { srcDir 'src/generated/resources' } - -configurations { - // configuration that holds jars to include in the jar - extraLibs -} - -repositories { - // Put repositories for dependencies here - // ForgeGradle automatically adds the Forge maven and Maven Central for you - - // If you have mod jar dependencies in ./libs, you can declare them as a repository like so: - // flatDir { - // dir 'libs' - // } -} - -dependencies { - // Specify the version of Minecraft to use. If this is any group other than 'net.minecraft', it is assumed - // that the dep is a ForgeGradle 'patcher' dependency, and its patches will be applied. - // The userdev artifact is a special name and will get all sorts of transformations applied to it. - minecraft 'net.minecraftforge:forge:1.19.2-43.2.0' - //implementation files('dependencies/jansi-2.4.0.jar') - //extraLibs files('dependencies/jansi-2.4.0.jar') - - minecraftLibrary files ('advancedbackups-corelib.jar') - extraLibs files ('advancedbackups-corelib.jar') - - // Real mod deobf dependency examples - these get remapped to your current mappings - // compileOnly fg.deobf("mezz.jei:jei-${mc_version}:${jei_version}:api") // Adds JEI API as a compile dependency - // runtimeOnly fg.deobf("mezz.jei:jei-${mc_version}:${jei_version}") // Adds the full JEI mod as a runtime dependency - // implementation fg.deobf("com.tterrag.registrate:Registrate:MC${mc_version}-${registrate_version}") // Adds registrate as a dependency - - // Examples using mod jars from ./libs - // implementation fg.deobf("blank:coolmod-${mc_version}:${coolmod_version}") - - // For more info... - // http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html - // http://www.gradle.org/docs/current/userguide/dependency_management.html -} - -// Example for how to get properties into the manifest for reading at runtime. -jar { - manifest { - attributes([ - "Main-Class" : "co.uk.mommyheather.advancedbackups.cli.AdvancedBackupsCLI", - "Specification-Title" : "advancedbackups", - "Specification-Vendor" : "mommyheather", - "Specification-Version" : "1", // We are version 1 of ourselves - "Implementation-Title" : project.name, - "Implementation-Version" : project.jar.archiveVersion, - "Implementation-Vendor" : "mommyheather", - "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ") - ]) - } - from { - configurations.extraLibs.collect { it.isDirectory() ? it : zipTree(it) } - } -} - -// Example configuration to allow publishing using the maven-publish plugin -// This is the preferred method to reobfuscate your jar file -jar.finalizedBy('reobfJar') -// However if you are in a multi-project build, dev time needs unobfed jar files, so you can delay the obfuscation until publishing by doing -// publish.dependsOn('reobfJar') - -publishing { - publications { - mavenJava(MavenPublication) { - artifact jar - } - } - repositories { - maven { - url "file://${project.projectDir}/mcmodsrepo" - } - } -} - -tasks.withType(JavaCompile).configureEach { - options.encoding = 'UTF-8' // Use the UTF-8 charset for Java compilation -} +plugins { + id 'eclipse' + id 'maven-publish' + id 'net.minecraftforge.gradle' version '5.1.+' +} + + + +group = 'co.uk.mommyheather.advancedbackups' // http://maven.apache.org/guides/mini/guide-naming-conventions.html +archivesBaseName = 'AdvancedBackups-' + modloaderName + "-" + minecraftVersion + +// Mojang ships Java 17 to end users in 1.18+, so your mod should target Java 17. +java.toolchain.languageVersion = JavaLanguageVersion.of(17) + +println "Java: ${System.getProperty 'java.version'}, JVM: ${System.getProperty 'java.vm.version'} (${System.getProperty 'java.vendor'}), Arch: ${System.getProperty 'os.arch'}" +minecraft { + // The mappings can be changed at any time and must be in the following format. + // Channel: Version: + // official MCVersion Official field/method names from Mojang mapping files + // parchment YYYY.MM.DD-MCVersion Open community-sourced parameter names and javadocs layered on top of official + // + // You must be aware of the Mojang license when using the 'official' or 'parchment' mappings. + // See more information here: https://github.com/MinecraftForge/MCPConfig/blob/master/Mojang.md + // + // Parchment is an unofficial project maintained by ParchmentMC, separate from MinecraftForge + // Additional setup is needed to use their mappings: https://github.com/ParchmentMC/Parchment/wiki/Getting-Started + // + // Use non-default mappings at your own risk. They may not always work. + // Simply re-run your setup task after changing the mappings to update your workspace. + mappings channel: 'official', version: '1.19.2' + + // accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg') // Currently, this location cannot be changed from the default. + + // Default run configurations. + // These can be tweaked, removed, or duplicated as needed. + runs { + client { + workingDirectory project.file('run') + + // Recommended logging data for a userdev environment + // The markers can be added/remove as needed separated by commas. + // "SCAN": For mods scan. + // "REGISTRIES": For firing of registry events. + // "REGISTRYDUMP": For getting the contents of all registries. + property 'forge.logging.markers', 'REGISTRIES' + + // Recommended logging level for the console + // You can set various levels here. + // Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels + property 'forge.logging.console.level', 'debug' + + // Comma-separated list of namespaces to load gametests from. Empty = all namespaces. + property 'forge.enabledGameTestNamespaces', 'advancedbackups' + + mods { + advancedbackups { + source sourceSets.main + } + } + } + + server { + workingDirectory project.file('run') + + property 'forge.logging.markers', 'REGISTRIES' + + property 'forge.logging.console.level', 'debug' + + // Comma-separated list of namespaces to load gametests from. Empty = all namespaces. + property 'forge.enabledGameTestNamespaces', 'advancedbackups' + + mods { + advancedbackups { + source sourceSets.main + } + } + } + + data { + workingDirectory project.file('run') + + property 'forge.logging.markers', 'REGISTRIES' + + property 'forge.logging.console.level', 'debug' + + // Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources. + args '--mod', 'advancedbackups', '--all', '--output', file('src/generated/resources/'), '--existing', file('src/main/resources/') + + mods { + advancedbackups { + source sourceSets.main + } + } + } + } +} + +// Include resources generated by data generators. +sourceSets.main.resources { srcDir 'src/generated/resources' } + +configurations { + // configuration that holds jars to include in the jar + extraLibs +} + +repositories { + // Put repositories for dependencies here + // ForgeGradle automatically adds the Forge maven and Maven Central for you + + // If you have mod jar dependencies in ./libs, you can declare them as a repository like so: + // flatDir { + // dir 'libs' + // } +} + +dependencies { + // Specify the version of Minecraft to use. If this is any group other than 'net.minecraft', it is assumed + // that the dep is a ForgeGradle 'patcher' dependency, and its patches will be applied. + // The userdev artifact is a special name and will get all sorts of transformations applied to it. + minecraft 'net.minecraftforge:forge:1.19.2-43.2.0' + //implementation files('dependencies/jansi-2.4.0.jar') + //extraLibs files('dependencies/jansi-2.4.0.jar') + + minecraftLibrary files ('advancedbackups-corelib.jar') + extraLibs files ('advancedbackups-corelib.jar') + + // Real mod deobf dependency examples - these get remapped to your current mappings + // compileOnly fg.deobf("mezz.jei:jei-${mc_version}:${jei_version}:api") // Adds JEI API as a compile dependency + // runtimeOnly fg.deobf("mezz.jei:jei-${mc_version}:${jei_version}") // Adds the full JEI mod as a runtime dependency + // implementation fg.deobf("com.tterrag.registrate:Registrate:MC${mc_version}-${registrate_version}") // Adds registrate as a dependency + + // Examples using mod jars from ./libs + // implementation fg.deobf("blank:coolmod-${mc_version}:${coolmod_version}") + + // For more info... + // http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html + // http://www.gradle.org/docs/current/userguide/dependency_management.html +} + +tasks.withType(ProcessResources).configureEach { + def replaceProperties = [ + mod_version: version + ] + inputs.properties replaceProperties + + filesMatching(['META-INF/mods.toml']) { + expand replaceProperties + [project: project] + } +} + +// Example for how to get properties into the manifest for reading at runtime. +jar { + manifest { + attributes([ + "Main-Class" : "co.uk.mommyheather.advancedbackups.cli.AdvancedBackupsCLI", + "Specification-Title" : "advancedbackups", + "Specification-Vendor" : "mommyheather", + "Specification-Version" : "1", // We are version 1 of ourselves + "Implementation-Title" : project.name, + "Implementation-Version" : project.jar.archiveVersion, + "Implementation-Vendor" : "mommyheather", + "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ") + ]) + } + from { + configurations.extraLibs.collect { it.isDirectory() ? it : zipTree(it) } + } +} + +// Example configuration to allow publishing using the maven-publish plugin +// This is the preferred method to reobfuscate your jar file +jar.finalizedBy('reobfJar') +// However if you are in a multi-project build, dev time needs unobfed jar files, so you can delay the obfuscation until publishing by doing +// publish.dependsOn('reobfJar') + +publishing { + publications { + mavenJava(MavenPublication) { + artifact jar + } + } + repositories { + maven { + url "file://${project.projectDir}/mcmodsrepo" + } + } +} + +tasks.withType(JavaCompile).configureEach { + options.encoding = 'UTF-8' // Use the UTF-8 charset for Java compilation +} diff --git a/src/main/resources/META-INF/mods.toml b/src/main/resources/META-INF/mods.toml index 403ff7e8..5423d122 100644 --- a/src/main/resources/META-INF/mods.toml +++ b/src/main/resources/META-INF/mods.toml @@ -1,63 +1,63 @@ -# This is an example mods.toml file. It contains the data relating to the loading mods. -# There are several mandatory fields (#mandatory), and many more that are optional (#optional). -# The overall format is standard TOML format, v0.5.0. -# Note that there are a couple of TOML lists in this file. -# Find more information on toml format here: https://github.com/toml-lang/toml -# The name of the mod loader type to load - for regular FML @Mod mods it should be javafml -modLoader="javafml" #mandatory -# A version range to match for said mod loader - for regular FML @Mod it will be the forge version -loaderVersion="[40,)" #mandatory This is typically bumped every Minecraft version by Forge. See our download page for lists of versions. -# The license for you mod. This is mandatory metadata and allows for easier comprehension of your redistributive properties. -# Review your options at https://choosealicense.com/. All rights reserved is the default copyright stance, and is thus the default here. -license="BSD" -# A URL to refer people to when problems occur with this mod -#issueTrackerURL="https://change.me.to.your.issue.tracker.example.invalid/" #optional -# A list of mods - how many allowed here is determined by the individual mod loader -[[mods]] #mandatory -# The modid of the mod -modId="advancedbackups" #mandatory -# The version number of the mod - there's a few well known ${} variables useable here or just hardcode it -# ${file.jarVersion} will substitute the value of the Implementation-Version as read from the mod's JAR file metadata -# see the associated build.gradle script for how to populate this completely automatically during a build -version="${file.jarVersion}" #mandatory - # A display name for the mod -displayName="Advanced Backups" #mandatory -# A URL to query for updates for this mod. See the JSON update specification https://mcforge.readthedocs.io/en/latest/gettingstarted/autoupdate/ -#updateJSONURL="https://change.me.example.invalid/updates.json" #optional -# A URL for the "homepage" for this mod, displayed in the mod UI -#displayURL="https://change.me.to.your.mods.homepage.example.invalid/" #optional -# A file name (in the root of the mod JAR) containing a logo for display -#logoFile="advancedbackups.png" #optional -# A text field displayed in the mod UI -#credits="Thanks for this example mod goes to Java" #optional -# A text field displayed in the mod UI -#authors="Love, Cheese and small house plants" #optional -# The description text for the mod (multi line!) (#mandatory) -description=''' -An extremely advanced backup mod. - -Supports many backup types. - -Config file and github contain documentation. -''' -# A dependency - use the . to indicate dependency for a specific modid. Dependencies are optional. -[[dependencies.advancedbackups]] #optional - # the modid of the dependency - modId="forge" #mandatory - # Does this dependency have to exist - if not, ordering below must be specified - mandatory=true #mandatory - # The version range of the dependency - versionRange="[40,)" #mandatory - # An ordering relationship for the dependency - BEFORE or AFTER required if the relationship is not mandatory - ordering="NONE" - # Side this dependency is applied on - BOTH, CLIENT or SERVER - side="BOTH" -# Here's another dependency -[[dependencies.advancedbackups]] - modId="minecraft" - mandatory=true -# This version range declares a minimum of the current minecraft version up to but not including the next major version -# 1.19.3 is a break - as such, we can't support it with this branch, and we'll need a new one... fuck me - versionRange="[1.19,1.19.3)" - ordering="NONE" - side="BOTH" +# This is an example mods.toml file. It contains the data relating to the loading mods. +# There are several mandatory fields (#mandatory), and many more that are optional (#optional). +# The overall format is standard TOML format, v0.5.0. +# Note that there are a couple of TOML lists in this file. +# Find more information on toml format here: https://github.com/toml-lang/toml +# The name of the mod loader type to load - for regular FML @Mod mods it should be javafml +modLoader="javafml" #mandatory +# A version range to match for said mod loader - for regular FML @Mod it will be the forge version +loaderVersion="[40,)" #mandatory This is typically bumped every Minecraft version by Forge. See our download page for lists of versions. +# The license for you mod. This is mandatory metadata and allows for easier comprehension of your redistributive properties. +# Review your options at https://choosealicense.com/. All rights reserved is the default copyright stance, and is thus the default here. +license="BSD" +# A URL to refer people to when problems occur with this mod +#issueTrackerURL="https://change.me.to.your.issue.tracker.example.invalid/" #optional +# A list of mods - how many allowed here is determined by the individual mod loader +[[mods]] #mandatory +# The modid of the mod +modId="advancedbackups" #mandatory +# The version number of the mod - there's a few well known ${} variables useable here or just hardcode it +# {file.jarVersion} will substitute the value of the Implementation-Version as read from the mod's JAR file metadata +# see the associated build.gradle script for how to populate this completely automatically during a build +version="${mod_version}" #mandatory + # A display name for the mod +displayName="Advanced Backups" #mandatory +# A URL to query for updates for this mod. See the JSON update specification https://mcforge.readthedocs.io/en/latest/gettingstarted/autoupdate/ +#updateJSONURL="https://change.me.example.invalid/updates.json" #optional +# A URL for the "homepage" for this mod, displayed in the mod UI +#displayURL="https://change.me.to.your.mods.homepage.example.invalid/" #optional +# A file name (in the root of the mod JAR) containing a logo for display +#logoFile="advancedbackups.png" #optional +# A text field displayed in the mod UI +#credits="Thanks for this example mod goes to Java" #optional +# A text field displayed in the mod UI +#authors="Love, Cheese and small house plants" #optional +# The description text for the mod (multi line!) (#mandatory) +description=''' +An extremely advanced backup mod. + +Supports many backup types. + +Config file and github contain documentation. +''' +# A dependency - use the . to indicate dependency for a specific modid. Dependencies are optional. +[[dependencies.advancedbackups]] #optional + # the modid of the dependency + modId="forge" #mandatory + # Does this dependency have to exist - if not, ordering below must be specified + mandatory=true #mandatory + # The version range of the dependency + versionRange="[40,)" #mandatory + # An ordering relationship for the dependency - BEFORE or AFTER required if the relationship is not mandatory + ordering="NONE" + # Side this dependency is applied on - BOTH, CLIENT or SERVER + side="BOTH" +# Here's another dependency +[[dependencies.advancedbackups]] + modId="minecraft" + mandatory=true +# This version range declares a minimum of the current minecraft version up to but not including the next major version +# 1.19.3 is a break - as such, we can't support it with this branch, and we'll need a new one... fuck me + versionRange="[1.19,1.19.3)" + ordering="NONE" + side="BOTH" From 69eb670cca198a9c018026602f432f57019623ca Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 9 Apr 2024 07:42:26 +0100 Subject: [PATCH 480/580] ( #57 ) gradle versioning in 1.19.3 forge --- build.gradle | 373 +++++++++++++------------- src/main/resources/META-INF/mods.toml | 4 +- 2 files changed, 194 insertions(+), 183 deletions(-) diff --git a/build.gradle b/build.gradle index a03159a2..ab182079 100644 --- a/build.gradle +++ b/build.gradle @@ -1,181 +1,192 @@ -plugins { - id 'eclipse' - id 'maven-publish' - id 'net.minecraftforge.gradle' version '[6.0,6.2)' -} - - - -group = 'co.uk.mommyheather.advancedbackups' // http://maven.apache.org/guides/mini/guide-naming-conventions.html -archivesBaseName = 'AdvancedBackups-' + modloaderName + "-" + minecraftVersion - -// Mojang ships Java 17 to end users in 1.18+, so your mod should target Java 17. -java.toolchain.languageVersion = JavaLanguageVersion.of(17) - -println "Java: ${System.getProperty 'java.version'}, JVM: ${System.getProperty 'java.vm.version'} (${System.getProperty 'java.vendor'}), Arch: ${System.getProperty 'os.arch'}" -minecraft { - // The mappings can be changed at any time and must be in the following format. - // Channel: Version: - // official MCVersion Official field/method names from Mojang mapping files - // parchment YYYY.MM.DD-MCVersion Open community-sourced parameter names and javadocs layered on top of official - // - // You must be aware of the Mojang license when using the 'official' or 'parchment' mappings. - // See more information here: https://github.com/MinecraftForge/MCPConfig/blob/master/Mojang.md - // - // Parchment is an unofficial project maintained by ParchmentMC, separate from MinecraftForge - // Additional setup is needed to use their mappings: https://github.com/ParchmentMC/Parchment/wiki/Getting-Started - // - // Use non-default mappings at your own risk. They may not always work. - // Simply re-run your setup task after changing the mappings to update your workspace. - mappings channel: 'official', version: '1.19.4' - - // accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg') // Currently, this location cannot be changed from the default. - accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg') - - // Default run configurations. - // These can be tweaked, removed, or duplicated as needed. - runs { - client { - workingDirectory project.file('run') - - // Recommended logging data for a userdev environment - // The markers can be added/remove as needed separated by commas. - // "SCAN": For mods scan. - // "REGISTRIES": For firing of registry events. - // "REGISTRYDUMP": For getting the contents of all registries. - property 'forge.logging.markers', 'REGISTRIES' - - // Recommended logging level for the console - // You can set various levels here. - // Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels - property 'forge.logging.console.level', 'debug' - - // Comma-separated list of namespaces to load gametests from. Empty = all namespaces. - property 'forge.enabledGameTestNamespaces', 'advancedbackups' - - mods { - advancedbackups { - source sourceSets.main - } - } - } - - server { - workingDirectory project.file('run') - - property 'forge.logging.markers', 'REGISTRIES' - - property 'forge.logging.console.level', 'debug' - - // Comma-separated list of namespaces to load gametests from. Empty = all namespaces. - property 'forge.enabledGameTestNamespaces', 'advancedbackups' - - mods { - advancedbackups { - source sourceSets.main - } - } - } - - data { - workingDirectory project.file('run') - - property 'forge.logging.markers', 'REGISTRIES' - - property 'forge.logging.console.level', 'debug' - - // Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources. - args '--mod', 'advancedbackups', '--all', '--output', file('src/generated/resources/'), '--existing', file('src/main/resources/') - - mods { - advancedbackups { - source sourceSets.main - } - } - } - } -} - -// Include resources generated by data generators. -sourceSets.main.resources { srcDir 'src/generated/resources' } - -configurations { - // configuration that holds jars to include in the jar - extraLibs -} - -repositories { - // Put repositories for dependencies here - // ForgeGradle automatically adds the Forge maven and Maven Central for you - - // If you have mod jar dependencies in ./libs, you can declare them as a repository like so: - // flatDir { - // dir 'libs' - // } -} - -dependencies { - // Specify the version of Minecraft to use. If this is any group other than 'net.minecraft', it is assumed - // that the dep is a ForgeGradle 'patcher' dependency, and its patches will be applied. - // The userdev artifact is a special name and will get all sorts of transformations applied to it. - minecraft 'net.minecraftforge:forge:1.19.4-45.2.4' - //implementation files('dependencies/jansi-2.4.0.jar') - //extraLibs files('dependencies/jansi-2.4.0.jar') - - minecraftLibrary files ('advancedbackups-corelib.jar') - extraLibs files ('advancedbackups-corelib.jar') - - // Real mod deobf dependency examples - these get remapped to your current mappings - // compileOnly fg.deobf("mezz.jei:jei-${mc_version}:${jei_version}:api") // Adds JEI API as a compile dependency - // runtimeOnly fg.deobf("mezz.jei:jei-${mc_version}:${jei_version}") // Adds the full JEI mod as a runtime dependency - // implementation fg.deobf("com.tterrag.registrate:Registrate:MC${mc_version}-${registrate_version}") // Adds registrate as a dependency - - // Examples using mod jars from ./libs - // implementation fg.deobf("blank:coolmod-${mc_version}:${coolmod_version}") - - // For more info... - // http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html - // http://www.gradle.org/docs/current/userguide/dependency_management.html -} - -// Example for how to get properties into the manifest for reading at runtime. -jar { - manifest { - attributes([ - "Main-Class" : "co.uk.mommyheather.advancedbackups.cli.AdvancedBackupsCLI", - "Specification-Title" : "advancedbackups", - "Specification-Vendor" : "mommyheather", - "Specification-Version" : "1", // We are version 1 of ourselves - "Implementation-Title" : project.name, - "Implementation-Version" : project.jar.archiveVersion, - "Implementation-Vendor" : "mommyheather", - "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ") - ]) - } - from { - configurations.extraLibs.collect { it.isDirectory() ? it : zipTree(it) } - } -} - -// Example configuration to allow publishing using the maven-publish plugin -// This is the preferred method to reobfuscate your jar file -jar.finalizedBy('reobfJar') -// However if you are in a multi-project build, dev time needs unobfed jar files, so you can delay the obfuscation until publishing by doing -// publish.dependsOn('reobfJar') - -publishing { - publications { - mavenJava(MavenPublication) { - artifact jar - } - } - repositories { - maven { - url "file://${project.projectDir}/mcmodsrepo" - } - } -} - -tasks.withType(JavaCompile).configureEach { - options.encoding = 'UTF-8' // Use the UTF-8 charset for Java compilation -} +plugins { + id 'eclipse' + id 'maven-publish' + id 'net.minecraftforge.gradle' version '[6.0,6.2)' +} + + + +group = 'co.uk.mommyheather.advancedbackups' // http://maven.apache.org/guides/mini/guide-naming-conventions.html +archivesBaseName = 'AdvancedBackups-' + modloaderName + "-" + minecraftVersion + +// Mojang ships Java 17 to end users in 1.18+, so your mod should target Java 17. +java.toolchain.languageVersion = JavaLanguageVersion.of(17) + +println "Java: ${System.getProperty 'java.version'}, JVM: ${System.getProperty 'java.vm.version'} (${System.getProperty 'java.vendor'}), Arch: ${System.getProperty 'os.arch'}" +minecraft { + // The mappings can be changed at any time and must be in the following format. + // Channel: Version: + // official MCVersion Official field/method names from Mojang mapping files + // parchment YYYY.MM.DD-MCVersion Open community-sourced parameter names and javadocs layered on top of official + // + // You must be aware of the Mojang license when using the 'official' or 'parchment' mappings. + // See more information here: https://github.com/MinecraftForge/MCPConfig/blob/master/Mojang.md + // + // Parchment is an unofficial project maintained by ParchmentMC, separate from MinecraftForge + // Additional setup is needed to use their mappings: https://github.com/ParchmentMC/Parchment/wiki/Getting-Started + // + // Use non-default mappings at your own risk. They may not always work. + // Simply re-run your setup task after changing the mappings to update your workspace. + mappings channel: 'official', version: '1.19.4' + + // accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg') // Currently, this location cannot be changed from the default. + accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg') + + // Default run configurations. + // These can be tweaked, removed, or duplicated as needed. + runs { + client { + workingDirectory project.file('run') + + // Recommended logging data for a userdev environment + // The markers can be added/remove as needed separated by commas. + // "SCAN": For mods scan. + // "REGISTRIES": For firing of registry events. + // "REGISTRYDUMP": For getting the contents of all registries. + property 'forge.logging.markers', 'REGISTRIES' + + // Recommended logging level for the console + // You can set various levels here. + // Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels + property 'forge.logging.console.level', 'debug' + + // Comma-separated list of namespaces to load gametests from. Empty = all namespaces. + property 'forge.enabledGameTestNamespaces', 'advancedbackups' + + mods { + advancedbackups { + source sourceSets.main + } + } + } + + server { + workingDirectory project.file('run') + + property 'forge.logging.markers', 'REGISTRIES' + + property 'forge.logging.console.level', 'debug' + + // Comma-separated list of namespaces to load gametests from. Empty = all namespaces. + property 'forge.enabledGameTestNamespaces', 'advancedbackups' + + mods { + advancedbackups { + source sourceSets.main + } + } + } + + data { + workingDirectory project.file('run') + + property 'forge.logging.markers', 'REGISTRIES' + + property 'forge.logging.console.level', 'debug' + + // Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources. + args '--mod', 'advancedbackups', '--all', '--output', file('src/generated/resources/'), '--existing', file('src/main/resources/') + + mods { + advancedbackups { + source sourceSets.main + } + } + } + } +} + +// Include resources generated by data generators. +sourceSets.main.resources { srcDir 'src/generated/resources' } + +configurations { + // configuration that holds jars to include in the jar + extraLibs +} + +repositories { + // Put repositories for dependencies here + // ForgeGradle automatically adds the Forge maven and Maven Central for you + + // If you have mod jar dependencies in ./libs, you can declare them as a repository like so: + // flatDir { + // dir 'libs' + // } +} + +dependencies { + // Specify the version of Minecraft to use. If this is any group other than 'net.minecraft', it is assumed + // that the dep is a ForgeGradle 'patcher' dependency, and its patches will be applied. + // The userdev artifact is a special name and will get all sorts of transformations applied to it. + minecraft 'net.minecraftforge:forge:1.19.4-45.2.4' + //implementation files('dependencies/jansi-2.4.0.jar') + //extraLibs files('dependencies/jansi-2.4.0.jar') + + minecraftLibrary files ('advancedbackups-corelib.jar') + extraLibs files ('advancedbackups-corelib.jar') + + // Real mod deobf dependency examples - these get remapped to your current mappings + // compileOnly fg.deobf("mezz.jei:jei-${mc_version}:${jei_version}:api") // Adds JEI API as a compile dependency + // runtimeOnly fg.deobf("mezz.jei:jei-${mc_version}:${jei_version}") // Adds the full JEI mod as a runtime dependency + // implementation fg.deobf("com.tterrag.registrate:Registrate:MC${mc_version}-${registrate_version}") // Adds registrate as a dependency + + // Examples using mod jars from ./libs + // implementation fg.deobf("blank:coolmod-${mc_version}:${coolmod_version}") + + // For more info... + // http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html + // http://www.gradle.org/docs/current/userguide/dependency_management.html +} + +tasks.withType(ProcessResources).configureEach { + def replaceProperties = [ + mod_version: version + ] + inputs.properties replaceProperties + + filesMatching(['META-INF/mods.toml']) { + expand replaceProperties + [project: project] + } +} + +// Example for how to get properties into the manifest for reading at runtime. +jar { + manifest { + attributes([ + "Main-Class" : "co.uk.mommyheather.advancedbackups.cli.AdvancedBackupsCLI", + "Specification-Title" : "advancedbackups", + "Specification-Vendor" : "mommyheather", + "Specification-Version" : "1", // We are version 1 of ourselves + "Implementation-Title" : project.name, + "Implementation-Version" : project.jar.archiveVersion, + "Implementation-Vendor" : "mommyheather", + "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ") + ]) + } + from { + configurations.extraLibs.collect { it.isDirectory() ? it : zipTree(it) } + } +} + +// Example configuration to allow publishing using the maven-publish plugin +// This is the preferred method to reobfuscate your jar file +jar.finalizedBy('reobfJar') +// However if you are in a multi-project build, dev time needs unobfed jar files, so you can delay the obfuscation until publishing by doing +// publish.dependsOn('reobfJar') + +publishing { + publications { + mavenJava(MavenPublication) { + artifact jar + } + } + repositories { + maven { + url "file://${project.projectDir}/mcmodsrepo" + } + } +} + +tasks.withType(JavaCompile).configureEach { + options.encoding = 'UTF-8' // Use the UTF-8 charset for Java compilation +} diff --git a/src/main/resources/META-INF/mods.toml b/src/main/resources/META-INF/mods.toml index acd79570..ac1b72c1 100644 --- a/src/main/resources/META-INF/mods.toml +++ b/src/main/resources/META-INF/mods.toml @@ -17,9 +17,9 @@ license="BSD" # The modid of the mod modId="advancedbackups" #mandatory # The version number of the mod - there's a few well known ${} variables useable here or just hardcode it -# ${file.jarVersion} will substitute the value of the Implementation-Version as read from the mod's JAR file metadata +# {file.jarVersion} will substitute the value of the Implementation-Version as read from the mod's JAR file metadata # see the associated build.gradle script for how to populate this completely automatically during a build -version="${file.jarVersion}" #mandatory +version="${mod_version}" #mandatory # A display name for the mod displayName="Advanced Backups" #mandatory # A URL to query for updates for this mod. See the JSON update specification https://mcforge.readthedocs.io/en/latest/gettingstarted/autoupdate/ From 97f021288dc244f97583a598f9d75c496fc81b82 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 9 Apr 2024 08:10:25 +0100 Subject: [PATCH 481/580] ( #57 ) gradle versioning on forge 1.20 --- build.gradle | 2 +- gradle.properties | 126 +++++++++++++++++++++++----------------------- 2 files changed, 63 insertions(+), 65 deletions(-) diff --git a/build.gradle b/build.gradle index b91808db..90592407 100644 --- a/build.gradle +++ b/build.gradle @@ -174,7 +174,7 @@ tasks.withType(ProcessResources).configureEach { minecraft_version : minecraft_version, minecraft_version_range: minecraft_version_range, neo_version : neo_version, neo_version_range: neo_version_range, loader_version_range: loader_version_range, - mod_id : mod_id, mod_name: mod_name, mod_license: mod_license, mod_version: mod_version, + mod_id : mod_id, mod_name: mod_name, mod_license: mod_license, mod_version: version, mod_authors : mod_authors, mod_description: mod_description, pack_format_number: pack_format_number, ] inputs.properties replaceProperties diff --git a/gradle.properties b/gradle.properties index a19b4b35..e94396cd 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,65 +1,63 @@ -# Sets default memory used for gradle commands. Can be overridden by user or command line properties. -# This is required to provide enough memory for the Minecraft decompilation process. -org.gradle.jvmargs=-Xmx3G -org.gradle.daemon=false - - -## Environment Properties - -# The Minecraft version must agree with the Neo version to get a valid artifact -minecraft_version=1.20.1 -# The Minecraft version range can use any release version of Minecraft as bounds. -# Snapshots, pre-releases, and release candidates are not guaranteed to sort properly -# as they do not follow standard versioning conventions. -minecraft_version_range=[1.20,1.22) -# The Neo version must agree with the Minecraft version to get a valid artifact -neo_version=47.1.65 -# The Neo version range can use any version of Neo as bounds or match the loader version range -neo_version_range=[46,) -# The loader version range can only use the major version of Neo/FML as bounds -loader_version_range=[46,) -# The mapping channel to use for mappings. -# The default set of supported mapping channels are ["official", "snapshot", "snapshot_nodoc", "stable", "stable_nodoc"]. -# Additional mapping channels can be registered through the "channelProviders" extension in a Gradle plugin. -# -# | Channel | Version | | -# |-----------|----------------------|--------------------------------------------------------------------------------| -# | official | MCVersion | Official field/method names from Mojang mapping files | -# | parchment | YYYY.MM.DD-MCVersion | Open community-sourced parameter names and javadocs layered on top of official | -# -# You must be aware of the Mojang license when using the 'official' or 'parchment' mappings. -# See more information here: https://github.com/neoforged/NeoForm/blob/main/Mojang.md -# -# Parchment is an unofficial project maintained by ParchmentMC, separate from Minecraft Forge. -# Additional setup is needed to use their mappings, see https://parchmentmc.org/docs/getting-started -mapping_channel=official -# The mapping version to query from the mapping channel. -# This must match the format required by the mapping channel. -mapping_version=1.20.1 - - -## Mod Properties - -# The unique mod identifier for the mod. Must be lowercase in English locale. Must fit the regex [a-z][a-z0-9_]{1,63} -# Must match the String constant located in the main mod class annotated with @Mod. -mod_id=advancedbackups -# The human-readable display name for the mod. -mod_name=Advanced Backups -# The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default. -mod_license=BSD -# The mod version. See https://semver.org/ -mod_version=2.1.2 -# The group ID for the mod. It is only important when publishing as an artifact to a Maven repository. -# This should match the base package used for the mod sources. -# See https://maven.apache.org/guides/mini/guide-naming-conventions.html -mod_group_id=co.uk.mommyheather.advancedbackups -# The authors of the mod. This is a simple text string that is used for display purposes in the mod list. -mod_authors=Heather White -# The description of the mod. This is a simple multiline text string that is used for display purposes in the mod list. -mod_description=A highly advanced and configurable backup mod.\Github contains documentation. -# Pack version - this changes each minecraft release, in general. -pack_format_number=15 - - -modloaderName =forge +# Sets default memory used for gradle commands. Can be overridden by user or command line properties. +# This is required to provide enough memory for the Minecraft decompilation process. +org.gradle.jvmargs=-Xmx3G +org.gradle.daemon=false + + +## Environment Properties + +# The Minecraft version must agree with the Neo version to get a valid artifact +minecraft_version=1.20.1 +# The Minecraft version range can use any release version of Minecraft as bounds. +# Snapshots, pre-releases, and release candidates are not guaranteed to sort properly +# as they do not follow standard versioning conventions. +minecraft_version_range=[1.20,1.22) +# The Neo version must agree with the Minecraft version to get a valid artifact +neo_version=47.1.65 +# The Neo version range can use any version of Neo as bounds or match the loader version range +neo_version_range=[46,) +# The loader version range can only use the major version of Neo/FML as bounds +loader_version_range=[46,) +# The mapping channel to use for mappings. +# The default set of supported mapping channels are ["official", "snapshot", "snapshot_nodoc", "stable", "stable_nodoc"]. +# Additional mapping channels can be registered through the "channelProviders" extension in a Gradle plugin. +# +# | Channel | Version | | +# |-----------|----------------------|--------------------------------------------------------------------------------| +# | official | MCVersion | Official field/method names from Mojang mapping files | +# | parchment | YYYY.MM.DD-MCVersion | Open community-sourced parameter names and javadocs layered on top of official | +# +# You must be aware of the Mojang license when using the 'official' or 'parchment' mappings. +# See more information here: https://github.com/neoforged/NeoForm/blob/main/Mojang.md +# +# Parchment is an unofficial project maintained by ParchmentMC, separate from Minecraft Forge. +# Additional setup is needed to use their mappings, see https://parchmentmc.org/docs/getting-started +mapping_channel=official +# The mapping version to query from the mapping channel. +# This must match the format required by the mapping channel. +mapping_version=1.20.1 + + +## Mod Properties + +# The unique mod identifier for the mod. Must be lowercase in English locale. Must fit the regex [a-z][a-z0-9_]{1,63} +# Must match the String constant located in the main mod class annotated with @Mod. +mod_id=advancedbackups +# The human-readable display name for the mod. +mod_name=Advanced Backups +# The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default. +mod_license=BSD +# The group ID for the mod. It is only important when publishing as an artifact to a Maven repository. +# This should match the base package used for the mod sources. +# See https://maven.apache.org/guides/mini/guide-naming-conventions.html +mod_group_id=co.uk.mommyheather.advancedbackups +# The authors of the mod. This is a simple text string that is used for display purposes in the mod list. +mod_authors=Heather White +# The description of the mod. This is a simple multiline text string that is used for display purposes in the mod list. +mod_description=A highly advanced and configurable backup mod.\Github contains documentation. +# Pack version - this changes each minecraft release, in general. +pack_format_number=15 + + +modloaderName =forge minecraftVersion =1.20 \ No newline at end of file From b629b6f1abc3321a754ecb8ddcc94de2778bd863 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 9 Apr 2024 23:35:42 +0100 Subject: [PATCH 482/580] Migrate to neoforge 1.20.4! --- README.md | 8 ++-- build.gradle | 2 +- settings.gradle | 24 +++++----- .../advancedbackups/AdvancedBackups.java | 7 +-- .../network/NetworkHandler.java | 48 +++++++------------ .../network/PacketBackupStatus.java | 28 ++++++----- .../network/PacketToastSubscribe.java | 29 +++++++---- src/main/resources/META-INF/mods.toml | 3 -- 8 files changed, 73 insertions(+), 76 deletions(-) diff --git a/README.md b/README.md index 5e146fc9..aa324402 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Forge - 1.20 - -This is the branch specifically for forge 1.20. -Any differences will be listed below. For full documentation, see the `core` branch. +# Neoforge - 1.20.4 + +This is the branch specifically for neoforge 1.20.4 +Any differences will be listed below. For full documentation, see the `core` branch. diff --git a/build.gradle b/build.gradle index eff2ead4..f02608dd 100644 --- a/build.gradle +++ b/build.gradle @@ -3,7 +3,7 @@ plugins { id 'eclipse' id 'idea' id 'maven-publish' - id 'net.neoforged.gradle.userdev' version '7.0.26' + id 'net.neoforged.gradle.userdev' version '7.0.80' } group = mod_group_id diff --git a/settings.gradle b/settings.gradle index 24584e97..07fc75e5 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,13 +1,13 @@ -pluginManagement { - repositories { - gradlePluginPortal() - maven { - name = 'NeoForged' - url = 'https://maven.neoforged.net/releases' - } - } -} - -plugins { - id 'org.gradle.toolchains.foojay-resolver-convention' version '0.5.0' +pluginManagement { + repositories { + gradlePluginPortal() + maven { + name = 'NeoForged' + url = 'https://maven.neoforged.net/releases' + } + } +} + +plugins { + id 'org.gradle.toolchains.foojay-resolver-convention' version '0.5.0' } \ No newline at end of file diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 792dbbcc..7ea91c3b 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -19,6 +19,7 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.level.storage.LevelResource; +import net.neoforged.bus.api.IEventBus; import net.neoforged.bus.api.SubscribeEvent; import net.neoforged.fml.ModList; import net.neoforged.fml.common.Mod; @@ -46,12 +47,12 @@ public class AdvancedBackups public static final ArrayList players = new ArrayList<>(); - public AdvancedBackups() + public AdvancedBackups(IEventBus modEventBus) { // Register ourselves for server and other game events we are interested in NeoForge.EVENT_BUS.register(this); - NetworkHandler.register(); - FMLJavaModLoadingContext.get().getModEventBus().addListener(this::clientSetup); + modEventBus.addListener(NetworkHandler::onRegisterPayloadHandler); + modEventBus.addListener(this::clientSetup); ABCore.infoLogger = infoLogger; ABCore.warningLogger = warningLogger; diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java index c9ebb9e7..06c2b6f6 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java @@ -1,46 +1,32 @@ package co.uk.mommyheather.advancedbackups.network; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.server.level.ServerPlayer; -import net.neoforged.neoforge.network.NetworkRegistry; -import net.neoforged.neoforge.network.PlayNetworkDirection; -import net.neoforged.neoforge.network.simple.SimpleChannel; +import net.neoforged.neoforge.network.PacketDistributor; +import net.neoforged.neoforge.network.event.RegisterPayloadHandlerEvent; +import net.neoforged.neoforge.network.registration.IPayloadRegistrar; public class NetworkHandler { - private static final String PROTOCOL_VERSION = "1"; - private static int id = 0; - private static int id() { - return id++; - } - - public static final SimpleChannel INSTANCE = NetworkRegistry.newSimpleChannel( - new ResourceLocation("advancedbackups", "main"), - () -> PROTOCOL_VERSION, - (version) -> true, - (version) -> true - ); + public static void onRegisterPayloadHandler(RegisterPayloadHandlerEvent event) { + final IPayloadRegistrar registrar = event.registrar("advancedbackups") + .versioned("1.0") + .optional(); - public static void register() { - INSTANCE.messageBuilder(PacketBackupStatus.class, id()) - .encoder(PacketBackupStatus::toBytes) - .decoder(buf -> new PacketBackupStatus(buf)) - .consumerNetworkThread(PacketBackupStatus::handle) - .add(); - INSTANCE.messageBuilder(PacketToastSubscribe.class, id()) - .encoder(PacketToastSubscribe::toBytes) - .decoder(buf -> new PacketToastSubscribe(buf)) - .consumerNetworkThread(PacketToastSubscribe::handle) - .add(); + registrar.play(PacketToastSubscribe.ID, PacketToastSubscribe::new, handler -> handler + .server(PacketToastSubscribe::handle)); + + registrar.play(PacketBackupStatus.ID, PacketBackupStatus::new, handler -> handler + .client(PacketBackupStatus::handle)); } - public static void sendToClient(ServerPlayer player, Object packet) { - INSTANCE.sendTo(packet, player.connection.connection, PlayNetworkDirection.PLAY_TO_CLIENT); + public static void sendToClient(ServerPlayer player, MSG message) { + PacketDistributor.PLAYER.with(player).send(message); } - public static void sendToServer(Object packet) { - INSTANCE.sendToServer(packet); + public static void sendToServer(MSG message) { + PacketDistributor.SERVER.noArg().send(message); } } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java index 99acd262..df36dd4c 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java @@ -1,15 +1,20 @@ package co.uk.mommyheather.advancedbackups.network; -import java.util.function.Supplier; - -import co.uk.mommyheather.advancedbackups.client.BackupToast; import co.uk.mommyheather.advancedbackups.client.ClientWrapper; -import net.minecraft.client.Minecraft; import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.protocol.common.custom.CustomPacketPayload; +import net.minecraft.resources.ResourceLocation; import net.neoforged.fml.LogicalSide; -import net.neoforged.neoforge.network.NetworkEvent; +import net.neoforged.neoforge.network.handling.PlayPayloadContext; + +public class PacketBackupStatus implements CustomPacketPayload { -public class PacketBackupStatus { + public static final ResourceLocation ID = new ResourceLocation("advancedbackups", "backup_status"); + + @Override + public ResourceLocation id() { + return ID; + } public boolean starting; public boolean started; @@ -45,7 +50,8 @@ public PacketBackupStatus(FriendlyByteBuf buf) { max = buf.readInt(); } - public void toBytes(FriendlyByteBuf buf) { + @Override + public void write(FriendlyByteBuf buf) { buf.writeBoolean(starting); buf.writeBoolean(started); buf.writeBoolean(failed); @@ -56,14 +62,12 @@ public void toBytes(FriendlyByteBuf buf) { buf.writeInt(max); } - public boolean handle(NetworkEvent.Context ctx) { - ctx.enqueueWork(() -> { - if (ctx.getDirection().getReceptionSide() == LogicalSide.CLIENT) { + public void handle(PlayPayloadContext ctx) { + ctx.workHandler().submitAsync(() -> { + if (ctx.flow().getReceptionSide() == LogicalSide.CLIENT) { ClientWrapper.handle(this); } }); - ctx.setPacketHandled(true); - return true; } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java index 4e9224f5..2be2770a 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java @@ -1,12 +1,20 @@ package co.uk.mommyheather.advancedbackups.network; -import java.util.function.Supplier; import co.uk.mommyheather.advancedbackups.AdvancedBackups; import net.minecraft.network.FriendlyByteBuf; -import net.neoforged.neoforge.network.NetworkEvent; +import net.minecraft.network.protocol.common.custom.CustomPacketPayload; +import net.minecraft.resources.ResourceLocation; +import net.neoforged.neoforge.network.handling.PlayPayloadContext; -public class PacketToastSubscribe { +public class PacketToastSubscribe implements CustomPacketPayload { + + public static final ResourceLocation ID = new ResourceLocation("advancedbackups", "toast_subscribe"); + + @Override + public ResourceLocation id() { + return ID; + } private boolean enable; @@ -19,18 +27,19 @@ public PacketToastSubscribe(FriendlyByteBuf buf) { enable = buf.readBoolean(); } - public void toBytes(FriendlyByteBuf buf) { + @Override + public void write(FriendlyByteBuf buf) { buf.writeBoolean(enable); } - public boolean handle(NetworkEvent.Context ctx) { - ctx.enqueueWork(() -> { - if (ctx.getSender() == null) return; - if (enable && !AdvancedBackups.players.contains(ctx.getSender().getStringUUID())) { - AdvancedBackups.players.add(ctx.getSender().getStringUUID()); + public boolean handle(PlayPayloadContext ctx) { + ctx.workHandler().submitAsync(() -> { + if (!ctx.player().isPresent()) return; + if (enable && !AdvancedBackups.players.contains(ctx.player().get().getStringUUID())) { + AdvancedBackups.players.add(ctx.player().get().getStringUUID()); } else if (!enable) { - AdvancedBackups.players.remove(ctx.getSender().getStringUUID()); + AdvancedBackups.players.remove(ctx.player().get().getStringUUID()); } }); diff --git a/src/main/resources/META-INF/mods.toml b/src/main/resources/META-INF/mods.toml index 3435b2b2..3721a573 100644 --- a/src/main/resources/META-INF/mods.toml +++ b/src/main/resources/META-INF/mods.toml @@ -47,8 +47,6 @@ description='''${mod_description}''' [[dependencies.${mod_id}]] #optional # the modid of the dependency modId="neoforge" #mandatory - # Does this dependency have to exist - if not, ordering below must be specified - mandatory=true #mandatory # The version range of the dependency versionRange="${neo_version_range}" #mandatory # An ordering relationship for the dependency - BEFORE or AFTER required if the dependency is not mandatory @@ -60,7 +58,6 @@ description='''${mod_description}''' # Here's another dependency [[dependencies.${mod_id}]] modId="minecraft" - mandatory=true # This version range declares a minimum of the current minecraft version up to but not including the next major version versionRange="${minecraft_version_range}" ordering="NONE" From 98e202ded8572ce8848c4e67767f27d9417030d0 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Wed, 10 Apr 2024 00:04:02 +0100 Subject: [PATCH 483/580] forgot to commit this --- gradle.properties | 131 +++++++++++++++++++++++----------------------- 1 file changed, 66 insertions(+), 65 deletions(-) diff --git a/gradle.properties b/gradle.properties index ba912535..59efd150 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,65 +1,66 @@ -# Sets default memory used for gradle commands. Can be overridden by user or command line properties. -# This is required to provide enough memory for the Minecraft decompilation process. -org.gradle.jvmargs=-Xmx3G -org.gradle.daemon=false - - -## Environment Properties - -# The Minecraft version must agree with the Neo version to get a valid artifact -minecraft_version=1.20.2 -# The Minecraft version range can use any release version of Minecraft as bounds. -# Snapshots, pre-releases, and release candidates are not guaranteed to sort properly -# as they do not follow standard versioning conventions. -minecraft_version_range=[1.20.2,1.21) -# The Neo version must agree with the Minecraft version to get a valid artifact -neo_version=20.2.35-beta -# The Neo version range can use any version of Neo as bounds or match the loader version range -neo_version_range=[20.2,) -# The loader version range can only use the major version of Neo/FML as bounds -loader_version_range=[1,) -# The mapping channel to use for mappings. -# The default set of supported mapping channels are ["official", "snapshot", "snapshot_nodoc", "stable", "stable_nodoc"]. -# Additional mapping channels can be registered through the "channelProviders" extension in a Gradle plugin. -# -# | Channel | Version | | -# |-----------|----------------------|--------------------------------------------------------------------------------| -# | official | MCVersion | Official field/method names from Mojang mapping files | -# | parchment | YYYY.MM.DD-MCVersion | Open community-sourced parameter names and javadocs layered on top of official | -# -# You must be aware of the Mojang license when using the 'official' or 'parchment' mappings. -# See more information here: https://github.com/neoforged/NeoForm/blob/main/Mojang.md -# -# Parchment is an unofficial project maintained by ParchmentMC, separate from Minecraft Forge. -# Additional setup is needed to use their mappings, see https://parchmentmc.org/docs/getting-started -mapping_channel=official -# The mapping version to query from the mapping channel. -# This must match the format required by the mapping channel. -mapping_version=1.20.2 - - -## Mod Properties - -# The unique mod identifier for the mod. Must be lowercase in English locale. Must fit the regex [a-z][a-z0-9_]{1,63} -# Must match the String constant located in the main mod class annotated with @Mod. -mod_id=advancedbackups -# The human-readable display name for the mod. -mod_name=Advanced Backups -# The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default. -mod_license=BSD -# The mod version. See https://semver.org/ -mod_version=2.1.2 -# The group ID for the mod. It is only important when publishing as an artifact to a Maven repository. -# This should match the base package used for the mod sources. -# See https://maven.apache.org/guides/mini/guide-naming-conventions.html -mod_group_id=co.uk.mommyheather.advancedbackups -# The authors of the mod. This is a simple text string that is used for display purposes in the mod list. -mod_authors=Heather White -# The description of the mod. This is a simple multiline text string that is used for display purposes in the mod list. -mod_description=A highly advanced and configurable backup mod.\Github contains documentation. -# Pack version - this changes each minecraft release, in general. -pack_format_number=18 - - -modloaderName =neoforge -minecraftVersion =1.20.2 \ No newline at end of file +# Sets default memory used for gradle commands. Can be overridden by user or command line properties. +# This is required to provide enough memory for the Minecraft decompilation process. +org.gradle.jvmargs=-Xmx3G +org.gradle.daemon=false + + +## Environment Properties + +# The Minecraft version must agree with the Forge version to get a valid artifact +minecraft_version=1.20.4 +# The Minecraft version range can use any release version of Minecraft as bounds. +# Snapshots, pre-releases, and release candidates are not guaranteed to sort properly +# as they do not follow standard versioning conventions. +minecraft_version_range=[1.20.4,1.21) +# The Forge version must agree with the Minecraft version to get a valid artifact +neo_version=20.4.173 +# The Forge version range can use any version of Forge as bounds or match the loader version range +neo_version_range=[20.4,) +# The loader version range can only use the major version of Forge/FML as bounds +loader_version_range=[2,) +# The mapping channel to use for mappings. +# The default set of supported mapping channels are ["official", "snapshot", "snapshot_nodoc", "stable", "stable_nodoc"]. +# Additional mapping channels can be registered through the "channelProviders" extension in a Gradle plugin. +# +# | Channel | Version | | +# |-----------|----------------------|--------------------------------------------------------------------------------| +# | official | MCVersion | Official field/method names from Mojang mapping files | +# | parchment | YYYY.MM.DD-MCVersion | Open community-sourced parameter names and javadocs layered on top of official | +# +# You must be aware of the Mojang license when using the 'official' or 'parchment' mappings. +# See more information here: https://github.com/neoforged/NeoForm/blob/main/Mojang.md +# +# Parchment is an unofficial project maintained by ParchmentMC, separate from Minecraft Forge. +# Additional setup is needed to use their mappings, see https://parchmentmc.org/docs/getting-started +mapping_channel=official +# The mapping version to query from the mapping channel. +# This must match the format required by the mapping channel. +mapping_version=1.20.4 + + + +## Mod Properties + +# The unique mod identifier for the mod. Must be lowercase in English locale. Must fit the regex [a-z][a-z0-9_]{1,63} +# Must match the String constant located in the main mod class annotated with @Mod. +mod_id=advancedbackups +# The human-readable display name for the mod. +mod_name=Advanced Backups +# The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default. +mod_license=BSD +# The mod version. See https://semver.org/ +mod_version=2.1.2 +# The group ID for the mod. It is only important when publishing as an artifact to a Maven repository. +# This should match the base package used for the mod sources. +# See https://maven.apache.org/guides/mini/guide-naming-conventions.html +mod_group_id=co.uk.mommyheather.advancedbackups +# The authors of the mod. This is a simple text string that is used for display purposes in the mod list. +mod_authors=Heather White +# The description of the mod. This is a simple multiline text string that is used for display purposes in the mod list. +mod_description=A highly advanced and configurable backup mod.\Github contains documentation. +# Pack version - this changes each minecraft release, in general. +pack_format_number=18 + + +modloaderName =neoforge +minecraftVersion =1.20.4 \ No newline at end of file From 28f5398947454de32252f474bf135b094cefdea0 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Fri, 19 Apr 2024 18:12:50 +0100 Subject: [PATCH 484/580] Update fabric.mod.json --- src/main/resources/fabric.mod.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 81bd0977..d73a73ab 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -2,7 +2,7 @@ "schemaVersion": 1, "id": "advancedbackups", "version": "${version}", - "accessWidener" : "advancedbackups.accesswidener", + "accessWidener" : "advancedbackups.accesswidener", "name": "Advanced Backups", "description": "An extremely advanced backup mod.\n\nSupports many backup types.\n\nConfig file and github contain documentation.", "authors": [ @@ -28,4 +28,4 @@ "java": ">=17", "fabric-api": "*" } -} \ No newline at end of file +} From 69742d12a147f64876dc60c94bc454784c95e673 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Fri, 19 Apr 2024 18:13:20 +0100 Subject: [PATCH 485/580] fix accesswidener outside of dev --- src/main/resources/fabric.mod.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 8eb6c936..d73a73ab 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -2,6 +2,7 @@ "schemaVersion": 1, "id": "advancedbackups", "version": "${version}", + "accessWidener" : "advancedbackups.accesswidener", "name": "Advanced Backups", "description": "An extremely advanced backup mod.\n\nSupports many backup types.\n\nConfig file and github contain documentation.", "authors": [ @@ -27,4 +28,4 @@ "java": ">=17", "fabric-api": "*" } -} \ No newline at end of file +} From 4e29493f00833e7c9ec9872db0a3ec78dccc6670 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Fri, 19 Apr 2024 18:13:42 +0100 Subject: [PATCH 486/580] fix accesswidener outside of dev --- src/main/resources/fabric.mod.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 12543992..6024ee33 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -2,6 +2,7 @@ "schemaVersion": 1, "id": "advancedbackups", "version": "${version}", + "accessWidener" : "advancedbackups.accesswidener", "name": "Advanced Backups", "description": "An extremely advanced backup mod.\n\nSupports many backup types.\n\nConfig file and github contain documentation.", "authors": [ @@ -27,4 +28,4 @@ "java": ">=17", "fabric-api": "*" } -} \ No newline at end of file +} From 512b41ea5c06f1c9bf3c1cddc547dd5b8e39e180 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Thu, 23 May 2024 04:24:31 +0100 Subject: [PATCH 487/580] manifest changes to allow 1.16.1 runs --- src/main/resources/META-INF/mods.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/META-INF/mods.toml b/src/main/resources/META-INF/mods.toml index 645fa28b..d711034c 100644 --- a/src/main/resources/META-INF/mods.toml +++ b/src/main/resources/META-INF/mods.toml @@ -6,7 +6,7 @@ # The name of the mod loader type to load - for regular FML @Mod mods it should be javafml modLoader="javafml" #mandatory # A version range to match for said mod loader - for regular FML @Mod it will be the forge version -loaderVersion="[34,)" #mandatory This is typically bumped every Minecraft version by Forge. See our download page for lists of versions. +loaderVersion="[32,)" #mandatory This is typically bumped every Minecraft version by Forge. See our download page for lists of versions. # The license for you mod. This is mandatory metadata and allows for easier comprehension of your redistributive properties. # Review your options at https://choosealicense.com/. All rights reserved is the default copyright stance, and is thus the default here. license="MIT" @@ -43,7 +43,7 @@ A powerful and highly configurable backup mod. Visit https://github.com/MommyHea # Does this dependency have to exist - if not, ordering below must be specified mandatory=true #mandatory # The version range of the dependency - versionRange="[34,)" #mandatory + versionRange="[32,)" #mandatory # An ordering relationship for the dependency - BEFORE or AFTER required if the relationship is not mandatory ordering="NONE" # Side this dependency is applied on - BOTH, CLIENT or SERVER From c3af709daa0554c3eee022341cd029023a8e54c5 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Fri, 24 May 2024 00:01:33 +0100 Subject: [PATCH 488/580] Fabric 1.20.5! Let's hope I don't need a specific branch for 1.20.6.. --- README.md | 8 +- build.gradle | 8 +- gradle.properties | 42 ++-- gradle/wrapper/gradle-wrapper.properties | 15 +- gradlew.bat | 184 +++++++++--------- settings.gradle | 16 +- .../advancedbackups/AdvancedBackups.java | 7 +- .../client/AdvancedBackupsClientCommand.java | 19 +- .../advancedbackups/client/ClientWrapper.java | 60 +++--- .../network/NetworkHandler.java | 9 +- .../network/PacketBackupStatus.java | 82 +++----- .../network/PacketToastSubscribe.java | 65 +++---- src/main/resources/fabric.mod.json | 6 +- 13 files changed, 235 insertions(+), 286 deletions(-) diff --git a/README.md b/README.md index 09db287c..b811bcda 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Fabric - 1.20 - -This is the branch specifically for fabric 1.20. -Any differences will be listed below. For full documentation, see the `core` branch. +# Fabric - 1.20.5 + +This is the branch specifically for fabric 1.20.5. +Any differences will be listed below. For full documentation, see the `core` branch. diff --git a/build.gradle b/build.gradle index 269aba8b..f6432078 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ plugins { - id 'fabric-loom' version '1.4-SNAPSHOT' + id 'fabric-loom' version '1.6-SNAPSHOT' id 'maven-publish' } @@ -51,7 +51,7 @@ processResources { } tasks.withType(JavaCompile).configureEach { - it.options.release = 17 + it.options.release = 21 } java { @@ -60,8 +60,8 @@ java { // If you remove this line, sources will not be generated. withSourcesJar() - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 + sourceCompatibility = JavaVersion.VERSION_21 + targetCompatibility = JavaVersion.VERSION_21 } jar { diff --git a/gradle.properties b/gradle.properties index c2803258..afe2a72e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,21 +1,21 @@ -# Done to increase the memory available to gradle. -org.gradle.jvmargs=-Xmx1G -org.gradle.parallel=true - -# Fabric Properties -# check these on https://fabricmc.net/develop -minecraft_version=1.20.2 -yarn_mappings=1.20.2+build.4 -loader_version=0.14.24 - -# Mod Properties -version=2.0 -mod_version=2.0 -maven_group=co.uk.mommyheather.advancedbackups -archives_base_name=advancedbackups -modloaderName =fabric -minecraftVersion =1.20.2 - -# Dependencies -fabric_version=0.90.4+1.20.2 - +# Done to increase the memory available to gradle. +org.gradle.jvmargs=-Xmx1G +org.gradle.parallel=true + +# Fabric Properties +# check these on https://fabricmc.net/develop +minecraft_version=1.20.5 +yarn_mappings=1.20.5+build.1 +loader_version=0.15.10 + +# Mod Properties +version=2.0 +mod_version=2.0 +maven_group=co.uk.mommyheather.advancedbackups +archives_base_name=advancedbackups +modloaderName =fabric +minecraftVersion =1.20.5 + +# Dependencies +fabric_version=0.97.5+1.20.5 + diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index ac72c34e..d878609b 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,8 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip -networkTimeout=10000 -validateDistributionUrl=true -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists +#Fri May 10 17:19:51 BST 2024 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew.bat b/gradlew.bat index 93e3f59f..6689b85b 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,92 +1,92 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%"=="" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%"=="" set DIRNAME=. -@rem This is normally unused -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if %ERRORLEVEL% equ 0 goto execute - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/settings.gradle b/settings.gradle index 56266b41..75c4d726 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,10 +1,10 @@ pluginManagement { - repositories { - maven { - name = 'Fabric' - url = 'https://maven.fabricmc.net/' - } - mavenCentral() - gradlePluginPortal() - } + repositories { + maven { + name = 'Fabric' + url = 'https://maven.fabricmc.net/' + } + mavenCentral() + gradlePluginPortal() + } } \ No newline at end of file diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 69adbc9f..6a40ebab 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -13,12 +13,13 @@ import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; -import co.uk.mommyheather.advancedbackups.network.NetworkHandler; +import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; import co.uk.mommyheather.advancedbackups.network.PacketToastSubscribe; import net.fabricmc.api.ModInitializer; import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; +import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry; import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; import net.fabricmc.loader.impl.FabricLoaderImpl; @@ -88,8 +89,10 @@ public void onInitialize() { BackupTimer.check(); }); - ServerPlayNetworking.registerGlobalReceiver(NetworkHandler.TOAST_SUBSCRIBE_ID, PacketToastSubscribe::handle); + PayloadTypeRegistry.playS2C().register(PacketBackupStatus.ID, PacketBackupStatus.CODEC); + PayloadTypeRegistry.playC2S().register(PacketToastSubscribe.ID, PacketToastSubscribe.CODEC); + ServerPlayNetworking.registerGlobalReceiver(PacketToastSubscribe.ID, PacketToastSubscribe::handle); } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java index 78b4f858..2763982d 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java @@ -1,16 +1,12 @@ package co.uk.mommyheather.advancedbackups.client; -import java.time.Instant; - import com.mojang.brigadier.CommandDispatcher; import co.uk.mommyheather.advancedbackups.core.CoreCommandSystem; import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; import net.minecraft.client.MinecraftClient; -import net.minecraft.network.message.ArgumentSignatureDataMap; -import net.minecraft.network.message.LastSeenMessageList.Acknowledgment; import net.minecraft.network.packet.c2s.play.CommandExecutionC2SPacket; import net.minecraft.text.Text; @@ -19,32 +15,27 @@ public static void register(CommandDispatcher dispatc dispatcher.register(ClientCommandManager.literal("backup").requires((runner) -> { return true; }).then(ClientCommandManager.literal("start").executes((runner) -> { - Acknowledgment acknowledgment = MinecraftClient.getInstance().player.networkHandler.lastSeenMessagesCollector.collect().update(); - MinecraftClient.getInstance().player.networkHandler.sendPacket(new CommandExecutionC2SPacket("backup start", Instant.now(), 0L, ArgumentSignatureDataMap.EMPTY, acknowledgment)); + MinecraftClient.getInstance().player.networkHandler.sendPacket(new CommandExecutionC2SPacket("backup start")); return 1; })) .then(ClientCommandManager.literal("reload-config").executes((runner) -> { - Acknowledgment acknowledgment = MinecraftClient.getInstance().player.networkHandler.lastSeenMessagesCollector.collect().update(); - MinecraftClient.getInstance().player.networkHandler.sendPacket(new CommandExecutionC2SPacket("backup reload-config", Instant.now(), 0L, ArgumentSignatureDataMap.EMPTY, acknowledgment)); + MinecraftClient.getInstance().player.networkHandler.sendPacket(new CommandExecutionC2SPacket("backup reload-config")); return 1; })) .then(ClientCommandManager.literal("reset-chain").executes((runner) -> { - Acknowledgment acknowledgment = MinecraftClient.getInstance().player.networkHandler.lastSeenMessagesCollector.collect().update(); - MinecraftClient.getInstance().player.networkHandler.sendPacket(new CommandExecutionC2SPacket("backup reset-chain", Instant.now(), 0L, ArgumentSignatureDataMap.EMPTY, acknowledgment)); + MinecraftClient.getInstance().player.networkHandler.sendPacket(new CommandExecutionC2SPacket("backup reset-chain")); return 1; })) .then(ClientCommandManager.literal("snapshot").executes((runner) -> { - Acknowledgment acknowledgment = MinecraftClient.getInstance().player.networkHandler.lastSeenMessagesCollector.collect().update(); - MinecraftClient.getInstance().player.networkHandler.sendPacket(new CommandExecutionC2SPacket("backup snapshot", Instant.now(), 0L, ArgumentSignatureDataMap.EMPTY, acknowledgment)); + MinecraftClient.getInstance().player.networkHandler.sendPacket(new CommandExecutionC2SPacket("backup snapshot")); return 1; })) .then(ClientCommandManager.literal("cancel").executes((runner) -> { - Acknowledgment acknowledgment = MinecraftClient.getInstance().player.networkHandler.lastSeenMessagesCollector.collect().update(); - MinecraftClient.getInstance().player.networkHandler.sendPacket(new CommandExecutionC2SPacket("backup cancel", Instant.now(), 0L, ArgumentSignatureDataMap.EMPTY, acknowledgment)); + MinecraftClient.getInstance().player.networkHandler.sendPacket(new CommandExecutionC2SPacket("backup cancel")); return 1; })) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java index 42f70d89..7ed317a7 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java @@ -3,7 +3,6 @@ import co.uk.mommyheather.advancedbackups.AdvancedBackups; import co.uk.mommyheather.advancedbackups.core.ABCore; import co.uk.mommyheather.advancedbackups.core.config.ClientConfigManager; -import co.uk.mommyheather.advancedbackups.network.NetworkHandler; import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; import co.uk.mommyheather.advancedbackups.network.PacketToastSubscribe; import net.fabricmc.api.ClientModInitializer; @@ -11,64 +10,61 @@ import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; -import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; -import net.fabricmc.fabric.api.networking.v1.PacketSender; import net.minecraft.client.MinecraftClient; -import net.minecraft.client.network.ClientPlayNetworkHandler; -import net.minecraft.network.PacketByteBuf; public class ClientWrapper implements ClientModInitializer { @Override public void onInitializeClient() { - + ABCore.infoLogger = AdvancedBackups.infoLogger; ABCore.warningLogger = AdvancedBackups.warningLogger; ABCore.errorLogger = AdvancedBackups.errorLogger; - - ClientPlayNetworking.registerGlobalReceiver(NetworkHandler.STATUS_PACKET_ID, ClientWrapper::handle); + ClientLifecycleEvents.CLIENT_STARTED.register((client) -> { ClientConfigManager.loadOrCreateConfig(); }); - + ClientPlayConnectionEvents.JOIN.register((handler, sender, client) -> { PacketToastSubscribe packet = new PacketToastSubscribe(ClientConfigManager.showProgress.get()); - sender.sendPacket(NetworkHandler.TOAST_SUBSCRIBE_ID, packet.write(PacketByteBufs.create())); + ClientPlayNetworking.send(packet); }); - + ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> { AdvancedBackupsClientCommand.register(dispatcher); - + }); - + + + ClientPlayNetworking.registerGlobalReceiver(PacketBackupStatus.ID, ClientWrapper::handle); + } - - - public static void handle(MinecraftClient client, ClientPlayNetworkHandler handler, PacketByteBuf buf, PacketSender responseSender) { - - PacketBackupStatus message = new PacketBackupStatus(); - message.read(buf); - - client.execute(() -> { - BackupToast.starting = message.starting; - BackupToast.started = message.started; - BackupToast.failed = message.failed; - BackupToast.finished = message.finished; - BackupToast.cancelled = message.cancelled; - BackupToast.progress = message.progress; - BackupToast.max = message.max; + public static void handle(PacketBackupStatus message, ClientPlayNetworking.Context context) { + + + + MinecraftClient.getInstance().execute(() -> { + BackupToast.starting = message.starting(); + BackupToast.started = message.started(); + BackupToast.failed = message.failed(); + BackupToast.finished = message.finished(); + BackupToast.cancelled = message.cancelled(); + + BackupToast.progress = message.progress(); + BackupToast.max = message.max(); + if (!BackupToast.exists) { BackupToast.exists = true; - client.getToastManager().add(new BackupToast()); + MinecraftClient.getInstance().getToastManager().add(new BackupToast()); } - + }); - - + + } } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java index 8faf7e33..41d32363 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java @@ -1,20 +1,13 @@ package co.uk.mommyheather.advancedbackups.network; -import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; -import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.util.Identifier; public class NetworkHandler { - public static Identifier STATUS_PACKET_ID = new Identifier("advancedbackups", "backup_status"); - public static final Identifier TOAST_SUBSCRIBE_ID = new Identifier("advancedbackups", "toast_subscribe"); - - public static void sendToClient(ServerPlayerEntity player, PacketBackupStatus packet) { - ServerPlayNetworking.send(player, STATUS_PACKET_ID, packet.write(PacketByteBufs.create())); + ServerPlayNetworking.send(player, packet); } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java index 633236a3..b5df8d78 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java @@ -1,57 +1,37 @@ package co.uk.mommyheather.advancedbackups.network; import net.minecraft.network.PacketByteBuf; - -public class PacketBackupStatus { - - public boolean starting; - public boolean started; - public boolean failed; - public boolean finished; - public boolean cancelled; - - public int progress; - public int max; - - - public PacketBackupStatus(boolean starting, boolean started, boolean failed, boolean finished, boolean cancelled, int progress, - int max) { - this.starting = starting; - this.started = started; - this.failed = failed; - this.finished = finished; - this.cancelled = cancelled; - this.progress = progress; - this.max = max; - } - - public PacketBackupStatus() { - - } - - public void read(PacketByteBuf buf) { - starting = buf.readBoolean(); - started = buf.readBoolean(); - failed = buf.readBoolean(); - finished = buf.readBoolean(); - cancelled = buf.readBoolean(); - - progress = buf.readInt(); - max = buf.readInt(); - } - - public PacketByteBuf write(PacketByteBuf buf) { - buf.writeBoolean(starting); - buf.writeBoolean(started); - buf.writeBoolean(failed); - buf.writeBoolean(finished); - buf.writeBoolean(cancelled); - - buf.writeInt(progress); - buf.writeInt(max); - - return buf; - +import net.minecraft.network.codec.PacketCodec; +import net.minecraft.network.packet.CustomPayload; + +public record PacketBackupStatus(boolean starting, boolean started, boolean failed, boolean finished, boolean cancelled, int progress, int max) implements CustomPayload { + + public static final Id ID = CustomPayload.id("advancedbackups:backup_status"); + + public static final PacketCodec CODEC = PacketCodec.of((packet, buf) -> { + buf.writeBoolean(packet.starting); + buf.writeBoolean(packet.started); + buf.writeBoolean(packet.failed); + buf.writeBoolean(packet.finished); + buf.writeBoolean(packet.cancelled); + buf.writeInt(packet.progress); + buf.writeInt(packet.max); + }, + + buf -> new PacketBackupStatus( + buf.readBoolean(), + buf.readBoolean(), + buf.readBoolean(), + buf.readBoolean(), + buf.readBoolean(), + buf.readInt(), + buf.readInt() + )); + + + @Override + public Id getId() { + return ID; } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java index 5d8b743e..13c69c8f 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java @@ -1,57 +1,42 @@ package co.uk.mommyheather.advancedbackups.network; import co.uk.mommyheather.advancedbackups.AdvancedBackups; -import net.fabricmc.fabric.api.networking.v1.PacketSender; +import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; import net.minecraft.network.PacketByteBuf; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.network.ServerPlayNetworkHandler; +import net.minecraft.network.codec.PacketCodec; +import net.minecraft.network.codec.PacketCodecs; +import net.minecraft.network.packet.CustomPayload; import net.minecraft.server.network.ServerPlayerEntity; -public class PacketToastSubscribe { - - public boolean enable; +public record PacketToastSubscribe(boolean enable) implements CustomPayload { + public static final Id ID = CustomPayload.id("advancedbackups:toast_subscribe"); public PacketToastSubscribe(boolean enable) { this.enable = enable; } - - public PacketToastSubscribe() { - - } - - public void read(PacketByteBuf buf) { - enable = buf.readBoolean(); - } - - public PacketByteBuf write(PacketByteBuf buf) { - buf.writeBoolean(enable); - - return buf; + + public static final PacketCodec CODEC = PacketCodec.tuple(PacketCodecs.BOOL, PacketToastSubscribe::enable, PacketToastSubscribe::new); + + + public static void handle(PacketToastSubscribe message, ServerPlayNetworking.Context context) { + + ServerPlayerEntity player = context.player(); + + if (message.enable() && !AdvancedBackups.players.contains(player.getUuidAsString())) { + AdvancedBackups.players.add(player.getUuidAsString()); + } + else if (!message.enable()) { + AdvancedBackups.players.remove(player.getUuidAsString()); + } } - - public static void handle(MinecraftServer server, ServerPlayerEntity player, ServerPlayNetworkHandler handler, PacketByteBuf buf, PacketSender responseSender) { - - PacketToastSubscribe message = new PacketToastSubscribe(); - message.read(buf); - - - server.execute(() -> { - if (message.enable && !AdvancedBackups.players.contains(player.getUuidAsString())) { - AdvancedBackups.players.add(player.getUuidAsString()); - } - else if (!message.enable) { - AdvancedBackups.players.remove(player.getUuidAsString()); - } - - }); - - - - - + + + @Override + public Id getId() { + return ID; } diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 81bd0977..118fa15f 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -23,9 +23,9 @@ ] }, "depends": { - "fabricloader": ">=0.14.22", - "minecraft": ">=1.20", - "java": ">=17", + "fabricloader": ">=0.15.10", + "minecraft": ">=1.20.5", + "java": ">=21", "fabric-api": "*" } } \ No newline at end of file From afa5de907f0026563cb36100a4390ed8778c0157 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sat, 8 Jun 2024 02:43:39 +0100 Subject: [PATCH 489/580] neoforge 1.20.5/1.20.6! --- .gitignore | 1 + README.md | 4 +- build.gradle | 10 +- gradle.properties | 12 +-- gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew.bat | 92 +++++++++++++++++++ .../advancedbackups/AdvancedBackups.java | 5 +- .../client/AdvancedBackupsClientCommand.java | 27 ++---- .../advancedbackups/client/ClientWrapper.java | 17 ++-- .../network/NetworkHandler.java | 22 ++--- .../network/PacketBackupStatus.java | 85 +++++------------ .../network/PacketToastSubscribe.java | 55 +++++------ .../{mods.toml => neoforge.mods.toml} | 0 13 files changed, 183 insertions(+), 149 deletions(-) create mode 100644 gradlew.bat rename src/main/resources/META-INF/{mods.toml => neoforge.mods.toml} (100%) diff --git a/.gitignore b/.gitignore index 12f86447..97468583 100644 --- a/.gitignore +++ b/.gitignore @@ -20,6 +20,7 @@ build # other eclipse run +runs # Files from Forge MDK forge*changelog.txt diff --git a/README.md b/README.md index aa324402..f11c15e1 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Neoforge - 1.20.4 +# Neoforge - 1.20.5 -This is the branch specifically for neoforge 1.20.4 +This is the branch specifically for neoforge 1.20.5 Any differences will be listed below. For full documentation, see the `core` branch. diff --git a/build.gradle b/build.gradle index f02608dd..a318c9a8 100644 --- a/build.gradle +++ b/build.gradle @@ -3,7 +3,7 @@ plugins { id 'eclipse' id 'idea' id 'maven-publish' - id 'net.neoforged.gradle.userdev' version '7.0.80' + id 'net.neoforged.gradle.userdev' version '7.0.109' } group = mod_group_id @@ -25,7 +25,7 @@ base { // Mojang ships Java 17 to end users in 1.18+, so your mod should target Java 17. -java.toolchain.languageVersion = JavaLanguageVersion.of(17) +java.toolchain.languageVersion = JavaLanguageVersion.of(21) //minecraft.accessTransformers.file rootProject.file('src/main/resources/META-INF/accesstransformer.cfg') //minecraft.accessTransformers.entry public net.minecraft.client.Minecraft textureManager # textureManager @@ -95,7 +95,7 @@ dependencies { // For all intends and purposes: You can treat this dependency as if it is a normal library you would use. implementation "net.neoforged:neoforge:${neo_version}" - + implementation files ('advancedbackups-corelib.jar') extraLibs files ('advancedbackups-corelib.jar') @@ -135,8 +135,8 @@ tasks.withType(ProcessResources).configureEach { ] inputs.properties replaceProperties - filesMatching(['META-INF/mods.toml', 'pack.mcmeta']) { - expand replaceProperties + [project: project] + filesMatching(['META-INF/neoforge.mods.toml']) { + expand replaceProperties } } diff --git a/gradle.properties b/gradle.properties index 59efd150..d21a30d1 100644 --- a/gradle.properties +++ b/gradle.properties @@ -7,15 +7,15 @@ org.gradle.daemon=false ## Environment Properties # The Minecraft version must agree with the Forge version to get a valid artifact -minecraft_version=1.20.4 +minecraft_version=1.20.5 # The Minecraft version range can use any release version of Minecraft as bounds. # Snapshots, pre-releases, and release candidates are not guaranteed to sort properly # as they do not follow standard versioning conventions. -minecraft_version_range=[1.20.4,1.21) +minecraft_version_range=[1.20.5,1.21) # The Forge version must agree with the Minecraft version to get a valid artifact -neo_version=20.4.173 +neo_version=20.5.17-beta # The Forge version range can use any version of Forge as bounds or match the loader version range -neo_version_range=[20.4,) +neo_version_range=[20.5,21) # The loader version range can only use the major version of Forge/FML as bounds loader_version_range=[2,) # The mapping channel to use for mappings. @@ -35,7 +35,7 @@ loader_version_range=[2,) mapping_channel=official # The mapping version to query from the mapping channel. # This must match the format required by the mapping channel. -mapping_version=1.20.4 +mapping_version=1.20.5 @@ -63,4 +63,4 @@ pack_format_number=18 modloaderName =neoforge -minecraftVersion =1.20.4 \ No newline at end of file +minecraftVersion =1.20.5 \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 37aef8d3..20db9ad5 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 00000000..93e3f59f --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,92 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 7ea91c3b..77b3aed3 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -27,11 +27,11 @@ import net.neoforged.fml.javafmlmod.FMLJavaModLoadingContext; import net.neoforged.neoforge.common.NeoForge; import net.neoforged.neoforge.event.RegisterCommandsEvent; -import net.neoforged.neoforge.event.TickEvent; import net.neoforged.neoforge.event.entity.player.PlayerEvent; import net.neoforged.neoforge.event.server.ServerStartedEvent; import net.neoforged.neoforge.event.server.ServerStartingEvent; import net.neoforged.neoforge.event.server.ServerStoppingEvent; +import net.neoforged.neoforge.event.tick.ServerTickEvent; import net.neoforged.neoforge.server.ServerLifecycleHooks; @Mod("advancedbackups") @@ -109,8 +109,7 @@ public void registerCommands(RegisterCommandsEvent event){ @SubscribeEvent - public void onPostTick(TickEvent.ServerTickEvent event) { - if (!event.phase.equals(TickEvent.Phase.END)) return; + public void onPostTick(ServerTickEvent.Post event) { BackupTimer.check(); } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java index 8271dc91..2db78a4d 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java @@ -1,55 +1,40 @@ package co.uk.mommyheather.advancedbackups.client; -import java.time.Instant; - import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.builder.LiteralArgumentBuilder; import co.uk.mommyheather.advancedbackups.core.CoreCommandSystem; import net.minecraft.client.Minecraft; import net.minecraft.commands.CommandSourceStack; -import net.minecraft.commands.arguments.ArgumentSignatures; import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.LastSeenMessages.Update; import net.minecraft.network.protocol.game.ServerboundChatCommandPacket; -import net.neoforged.neoforge.server.ServerLifecycleHooks; public class AdvancedBackupsClientCommand { public static void register(CommandDispatcher commandDispatcher) { commandDispatcher.register(literal("backup").requires((runner) -> { return true; }).then(literal("start").executes((runner) -> { - Update acknowledgment = Minecraft.getInstance().player.connection.lastSeenMessages.generateAndApplyUpdate().update(); - Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup start", Instant.now(), 0, - ArgumentSignatures.EMPTY, acknowledgment)); + Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup start")); return 1; })) - .then(literal("reload-config").executes((runner) -> { - Update acknowledgment = Minecraft.getInstance().player.connection.lastSeenMessages.generateAndApplyUpdate().update(); - Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup reload-config", Instant.now(), 0, - ArgumentSignatures.EMPTY, acknowledgment)); + .then(literal("reload-config").executes((runner) -> { + Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup reload-config")); return 1; })) .then(literal("reset-chain").executes((runner) -> { - Update acknowledgment = Minecraft.getInstance().player.connection.lastSeenMessages.generateAndApplyUpdate().update(); - Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup reset-chain", Instant.now(), 0, - ArgumentSignatures.EMPTY, acknowledgment)); + Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup reset-chain")); return 1; })) .then(literal("snapshot").executes((runner) -> { - Update acknowledgment = Minecraft.getInstance().player.connection.lastSeenMessages.generateAndApplyUpdate().update(); - Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup snapshot", Instant.now(), 0, - ArgumentSignatures.EMPTY, acknowledgment)); + Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup snapshot")); return 1; })) .then(literal("cancel").executes((runner) -> { - Update acknowledgment = Minecraft.getInstance().player.connection.lastSeenMessages.generateAndApplyUpdate().update(); - Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup cancel", Instant.now(), 0, - ArgumentSignatures.EMPTY, acknowledgment)); + Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup cancel")); return 1; })) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java index e1c86f56..26472494 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java @@ -9,18 +9,19 @@ import net.neoforged.neoforge.client.event.ClientPlayerNetworkEvent; import net.neoforged.neoforge.client.event.RegisterClientCommandsEvent; import net.neoforged.neoforge.common.NeoForge; +import net.neoforged.neoforge.network.handling.IPayloadContext; public class ClientWrapper { - public static void handle(PacketBackupStatus packet) { - BackupToast.starting = packet.starting; - BackupToast.started = packet.started; - BackupToast.failed = packet.failed; - BackupToast.finished = packet.finished; - BackupToast.cancelled = packet.cancelled; + public static void handle(PacketBackupStatus packet, IPayloadContext context) { + BackupToast.starting = packet.starting(); + BackupToast.started = packet.started(); + BackupToast.failed = packet.failed(); + BackupToast.finished = packet.finished(); + BackupToast.cancelled = packet.cancelled(); - BackupToast.progress = packet.progress; - BackupToast.max = packet.max; + BackupToast.progress = packet.progress(); + BackupToast.max = packet.max(); if (!BackupToast.exists) { BackupToast.exists = true; diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java index 06c2b6f6..86bc0c2f 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java @@ -1,32 +1,28 @@ package co.uk.mommyheather.advancedbackups.network; +import co.uk.mommyheather.advancedbackups.client.ClientWrapper; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.server.level.ServerPlayer; import net.neoforged.neoforge.network.PacketDistributor; -import net.neoforged.neoforge.network.event.RegisterPayloadHandlerEvent; -import net.neoforged.neoforge.network.registration.IPayloadRegistrar; +import net.neoforged.neoforge.network.event.RegisterPayloadHandlersEvent; +import net.neoforged.neoforge.network.registration.PayloadRegistrar; public class NetworkHandler { - public static void onRegisterPayloadHandler(RegisterPayloadHandlerEvent event) { - final IPayloadRegistrar registrar = event.registrar("advancedbackups") - .versioned("1.0") - .optional(); + public static void onRegisterPayloadHandler(RegisterPayloadHandlersEvent event) { + final PayloadRegistrar registrar = event.registrar("1"); - registrar.play(PacketToastSubscribe.ID, PacketToastSubscribe::new, handler -> handler - .server(PacketToastSubscribe::handle)); - - registrar.play(PacketBackupStatus.ID, PacketBackupStatus::new, handler -> handler - .client(PacketBackupStatus::handle)); + registrar.commonToClient(PacketBackupStatus.ID, PacketBackupStatus.CODEC, ClientWrapper::handle); + registrar.commonToServer(PacketToastSubscribe.ID, PacketToastSubscribe.CODEC, PacketToastSubscribe::handle); } public static void sendToClient(ServerPlayer player, MSG message) { - PacketDistributor.PLAYER.with(player).send(message); + PacketDistributor.sendToPlayer(player, message); } public static void sendToServer(MSG message) { - PacketDistributor.SERVER.noArg().send(message); + PacketDistributor.sendToServer(message); } } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java index df36dd4c..ea842bf2 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java @@ -1,74 +1,39 @@ package co.uk.mommyheather.advancedbackups.network; -import co.uk.mommyheather.advancedbackups.client.ClientWrapper; import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.codec.StreamCodec; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.resources.ResourceLocation; -import net.neoforged.fml.LogicalSide; -import net.neoforged.neoforge.network.handling.PlayPayloadContext; -public class PacketBackupStatus implements CustomPacketPayload { +public record PacketBackupStatus(boolean starting, boolean started, boolean failed, boolean finished, boolean cancelled, int progress, int max) implements CustomPacketPayload { + + public static final CustomPacketPayload.Type ID = new CustomPacketPayload.Type(new ResourceLocation("advancedbackups:backup_status")); + + public static final StreamCodec CODEC = StreamCodec.of((buf, packet) -> { + buf.writeBoolean(packet.starting); + buf.writeBoolean(packet.started); + buf.writeBoolean(packet.failed); + buf.writeBoolean(packet.finished); + buf.writeBoolean(packet.cancelled); + buf.writeInt(packet.progress); + buf.writeInt(packet.max); + }, + + buf -> new PacketBackupStatus( + buf.readBoolean(), + buf.readBoolean(), + buf.readBoolean(), + buf.readBoolean(), + buf.readBoolean(), + buf.readInt(), + buf.readInt() + )); - public static final ResourceLocation ID = new ResourceLocation("advancedbackups", "backup_status"); @Override - public ResourceLocation id() { + public CustomPacketPayload.Type type() { return ID; } - - public boolean starting; - public boolean started; - - public boolean failed; - public boolean finished; - public boolean cancelled; - - public int progress; - public int max; - - - public PacketBackupStatus(boolean starting, boolean started, boolean failed, boolean finished, boolean cancelled, int progress, - int max) { - this.starting = starting; - this.started = started; - this.failed = failed; - this.finished = finished; - this.cancelled = cancelled; - this.progress = progress; - this.max = max; - } - - - public PacketBackupStatus(FriendlyByteBuf buf) { - starting = buf.readBoolean(); - started = buf.readBoolean(); - failed = buf.readBoolean(); - finished = buf.readBoolean(); - cancelled = buf.readBoolean(); - progress = buf.readInt(); - max = buf.readInt(); - } - - @Override - public void write(FriendlyByteBuf buf) { - buf.writeBoolean(starting); - buf.writeBoolean(started); - buf.writeBoolean(failed); - buf.writeBoolean(finished); - buf.writeBoolean(cancelled); - - buf.writeInt(progress); - buf.writeInt(max); - } - - public void handle(PlayPayloadContext ctx) { - ctx.workHandler().submitAsync(() -> { - if (ctx.flow().getReceptionSide() == LogicalSide.CLIENT) { - ClientWrapper.handle(this); - } - }); - - } } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java index 2be2770a..514a7567 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java @@ -1,50 +1,45 @@ package co.uk.mommyheather.advancedbackups.network; - import co.uk.mommyheather.advancedbackups.AdvancedBackups; import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.codec.StreamCodec; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.resources.ResourceLocation; -import net.neoforged.neoforge.network.handling.PlayPayloadContext; - -public class PacketToastSubscribe implements CustomPacketPayload { +import net.minecraft.world.entity.player.Player; +import net.neoforged.neoforge.network.handling.IPayloadContext; - public static final ResourceLocation ID = new ResourceLocation("advancedbackups", "toast_subscribe"); - - @Override - public ResourceLocation id() { - return ID; - } +public record PacketToastSubscribe(boolean enable) implements CustomPacketPayload { - private boolean enable; + public static final CustomPacketPayload.Type ID = new CustomPacketPayload.Type<>(new ResourceLocation("advancedbackups:toast_subscribe")); public PacketToastSubscribe(boolean enable) { this.enable = enable; } + public static final StreamCodec CODEC = StreamCodec.composite(ByteBufCodecs.BOOL, PacketToastSubscribe::enable, PacketToastSubscribe::new); - public PacketToastSubscribe(FriendlyByteBuf buf) { - enable = buf.readBoolean(); - } - @Override - public void write(FriendlyByteBuf buf) { - buf.writeBoolean(enable); - } + public static void handle(PacketToastSubscribe message, IPayloadContext context) { + + Player player = context.player(); - public boolean handle(PlayPayloadContext ctx) { - ctx.workHandler().submitAsync(() -> { - if (!ctx.player().isPresent()) return; - if (enable && !AdvancedBackups.players.contains(ctx.player().get().getStringUUID())) { - AdvancedBackups.players.add(ctx.player().get().getStringUUID()); - } - else if (!enable) { - AdvancedBackups.players.remove(ctx.player().get().getStringUUID()); - } - }); + if (message.enable() && !AdvancedBackups.players.contains(player.getStringUUID())) { + AdvancedBackups.players.add(player.getStringUUID()); + } + else if (!message.enable()) { + AdvancedBackups.players.remove(player.getStringUUID()); + } + + } + - return true; + @Override + public CustomPacketPayload.Type type() { + return ID; } -} + + +} \ No newline at end of file diff --git a/src/main/resources/META-INF/mods.toml b/src/main/resources/META-INF/neoforge.mods.toml similarity index 100% rename from src/main/resources/META-INF/mods.toml rename to src/main/resources/META-INF/neoforge.mods.toml From 0b4d2dd495857ddae0fccfd1b7c5eb8de05508f2 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sun, 9 Jun 2024 21:29:27 +0100 Subject: [PATCH 490/580] change jar name to show 1.20.6 instead of 1.20.5 --- gradle.properties | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index d21a30d1..f5678413 100644 --- a/gradle.properties +++ b/gradle.properties @@ -63,4 +63,5 @@ pack_format_number=18 modloaderName =neoforge -minecraftVersion =1.20.5 \ No newline at end of file +#We support 1.20.5, but it shouldn't be used so we won't mention it here. +minecraftVersion =1.20.6 \ No newline at end of file From 423f4a65734fdb3b74716b54f09050cdef707f7f Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sun, 9 Jun 2024 21:45:27 +0100 Subject: [PATCH 491/580] change jar output name --- gradle.properties | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index afe2a72e..893ab27b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -14,7 +14,8 @@ mod_version=2.0 maven_group=co.uk.mommyheather.advancedbackups archives_base_name=advancedbackups modloaderName =fabric -minecraftVersion =1.20.5 +#We support 1.20.6, but it shouldn't be used so we won't show in the jar name. +minecraftVersion =1.20.6 # Dependencies fabric_version=0.97.5+1.20.5 From 2020249e8fab04b1e8812f4359d95f869eeedc41 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sun, 9 Jun 2024 23:01:38 +0100 Subject: [PATCH 492/580] readme shenanigans --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 5e146fc9..34f365d6 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Forge - 1.20 - -This is the branch specifically for forge 1.20. -Any differences will be listed below. For full documentation, see the `core` branch. +# Forge - 1.20 + +This is the branch specifically for forge 1.20. +Any differences will be listed below. For full documentation, see the `core` branch. From e95c3a8a1a638a67ed9ad26dac076b5fe37250b7 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Mon, 10 Jun 2024 00:27:48 +0100 Subject: [PATCH 493/580] don't require forge on server - should let clients connect to non-forge servers --- src/main/resources/META-INF/mods.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/META-INF/mods.toml b/src/main/resources/META-INF/mods.toml index 450de68c..f3e20eb9 100644 --- a/src/main/resources/META-INF/mods.toml +++ b/src/main/resources/META-INF/mods.toml @@ -53,7 +53,7 @@ description='''${mod_description}''' # AFTER - This mod is loaded AFTER the dependency ordering="NONE" # Side this dependency is applied on - BOTH, CLIENT, or SERVER - side="BOTH" + side="CLIENT" # Features are specific properties of the game environment, that you may want to declare you require. This example declares # that your mod requires GL version 3.2 or higher. Other features will be added. They are side aware so declaring this won't # stop your mod loading on the server for example. From be93bae3f6eb6091af98406629b6f70fa42bbe6a Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Mon, 10 Jun 2024 00:28:41 +0100 Subject: [PATCH 494/580] don't require neoforge on server --- src/main/resources/META-INF/neoforge.mods.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/META-INF/neoforge.mods.toml b/src/main/resources/META-INF/neoforge.mods.toml index 3721a573..9e0f97f1 100644 --- a/src/main/resources/META-INF/neoforge.mods.toml +++ b/src/main/resources/META-INF/neoforge.mods.toml @@ -54,7 +54,7 @@ description='''${mod_description}''' # AFTER - This mod is loaded AFTER the dependency ordering="NONE" # Side this dependency is applied on - BOTH, CLIENT, or SERVER - side="BOTH" + side="CLIENT" # Here's another dependency [[dependencies.${mod_id}]] modId="minecraft" From 761c61f5f5b825c79d9b5ccb83f66583e818e5d5 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Mon, 10 Jun 2024 01:56:03 +0100 Subject: [PATCH 495/580] implement checks - don't try sending packets to servers that can't handle them! --- .../advancedbackups/client/ClientWrapper.java | 24 +++++++++++++++++-- .../network/NetworkHandler.java | 6 ++--- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java index 26472494..17432bd6 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java @@ -1,15 +1,20 @@ package co.uk.mommyheather.advancedbackups.client; +import java.util.Objects; + import co.uk.mommyheather.advancedbackups.core.config.ClientConfigManager; -import co.uk.mommyheather.advancedbackups.network.NetworkHandler; import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; import co.uk.mommyheather.advancedbackups.network.PacketToastSubscribe; import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.ClientPacketListener; +import net.minecraft.network.protocol.common.ServerboundCustomPayloadPacket; +import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent; import net.neoforged.neoforge.client.event.ClientPlayerNetworkEvent; import net.neoforged.neoforge.client.event.RegisterClientCommandsEvent; import net.neoforged.neoforge.common.NeoForge; import net.neoforged.neoforge.network.handling.IPayloadContext; +import net.neoforged.neoforge.network.registration.NetworkRegistry; public class ClientWrapper { @@ -40,7 +45,22 @@ public static void registerClientCommands(RegisterClientCommandsEvent event) { } public static void onServerConnected(ClientPlayerNetworkEvent.LoggingIn event) { - NetworkHandler.sendToServer(new PacketToastSubscribe(ClientConfigManager.showProgress.get())); + sendToServer(new PacketToastSubscribe(ClientConfigManager.showProgress.get())); + } + + + public static void sendToServer(MSG message) { + //We do this to implement custom checks! + ServerboundCustomPayloadPacket packet = new ServerboundCustomPayloadPacket(message); + + ClientPacketListener listener = Objects.requireNonNull(Minecraft.getInstance().getConnection()); + try { + NetworkRegistry.checkPacket(packet, listener); + } + catch (UnsupportedOperationException e) { + return; + } + listener.connection.send(packet); } } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java index 86bc0c2f..5d473a8c 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java @@ -1,5 +1,6 @@ package co.uk.mommyheather.advancedbackups.network; + import co.uk.mommyheather.advancedbackups.client.ClientWrapper; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.server.level.ServerPlayer; @@ -11,7 +12,7 @@ public class NetworkHandler { public static void onRegisterPayloadHandler(RegisterPayloadHandlersEvent event) { - final PayloadRegistrar registrar = event.registrar("1"); + final PayloadRegistrar registrar = event.registrar("1").optional(); //this .optional() seems to be required, but will it be a problem for our packets with non-neo servers...? registrar.commonToClient(PacketBackupStatus.ID, PacketBackupStatus.CODEC, ClientWrapper::handle); registrar.commonToServer(PacketToastSubscribe.ID, PacketToastSubscribe.CODEC, PacketToastSubscribe::handle); @@ -21,8 +22,5 @@ public static void sendToClient(ServerPlayer p PacketDistributor.sendToPlayer(player, message); } - public static void sendToServer(MSG message) { - PacketDistributor.sendToServer(message); - } } From ba20a1500afae208e6144d0feddd701fdc8b2752 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Mon, 10 Jun 2024 02:00:41 +0100 Subject: [PATCH 496/580] log when a packet isn't sent --- .../uk/mommyheather/advancedbackups/client/ClientWrapper.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java index 17432bd6..872563e2 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java @@ -2,6 +2,7 @@ import java.util.Objects; +import co.uk.mommyheather.advancedbackups.core.ABCore; import co.uk.mommyheather.advancedbackups.core.config.ClientConfigManager; import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; import co.uk.mommyheather.advancedbackups.network.PacketToastSubscribe; @@ -58,6 +59,7 @@ public static void sendToServer(MSG message) { NetworkRegistry.checkPacket(packet, listener); } catch (UnsupportedOperationException e) { + ABCore.warningLogger.accept("Refusing to send packet " + message + " to server as the serve cannot receive it."); return; } listener.connection.send(packet); From 5400c8b4f5f4e81c27daa6949c0bfa8441c5bb25 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Mon, 10 Jun 2024 02:02:15 +0100 Subject: [PATCH 497/580] check if a packet can be sent before trying to send it --- .../advancedbackups/client/ClientWrapper.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java index 7ed317a7..4b00410b 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientWrapper.java @@ -27,7 +27,13 @@ public void onInitializeClient() { ClientPlayConnectionEvents.JOIN.register((handler, sender, client) -> { PacketToastSubscribe packet = new PacketToastSubscribe(ClientConfigManager.showProgress.get()); - ClientPlayNetworking.send(packet); + if (ClientPlayNetworking.canSend(packet.getId())) { + //Make sure a server can receive the packet before trying to send! + ClientPlayNetworking.send(packet); + } + else { + ABCore.warningLogger.accept("Refusing to send packet " + packet + " as the server cannot accept it!"); + } }); ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> { From 960b77e52752e32cefd356c26b9ab2e4a8cc112c Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Mon, 10 Jun 2024 02:06:07 +0100 Subject: [PATCH 498/580] working 1.20.6. however, networking needs a rewrite to be compatible with spigot/paper plans! --- README.md | 2 +- build.gradle | 38 +++++++++++-------- gradle.properties | 16 ++++---- gradle/wrapper/gradle-wrapper.properties | 2 +- settings.gradle | 2 +- .../client/AdvancedBackupsClientCommand.java | 20 +++------- .../network/PacketBackupStatus.java | 4 +- 7 files changed, 41 insertions(+), 43 deletions(-) diff --git a/README.md b/README.md index 34f365d6..f1b8d2a3 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Forge - 1.20 +# Forge - 1.20.6 This is the branch specifically for forge 1.20. Any differences will be listed below. For full documentation, see the `core` branch. diff --git a/build.gradle b/build.gradle index d96139aa..9160221a 100644 --- a/build.gradle +++ b/build.gradle @@ -2,8 +2,7 @@ plugins { id 'eclipse' id 'idea' id 'maven-publish' - id 'net.minecraftforge.gradle' version '[6.0.14,6.2)' - id 'org.spongepowered.mixin' version '0.7.+' + id 'net.minecraftforge.gradle' version '[6.0.24,6.2)' } group = mod_group_id @@ -17,8 +16,8 @@ task copyVSCodeResources (dependsOn: 'processResources', type: Copy) { into 'bin/' } -// Mojang ships Java 17 to end users in 1.18+, so your mod should target Java 17. -java.toolchain.languageVersion = JavaLanguageVersion.of(17) +// Mojang ships Java 21 to end users in 1.20.5+, so your mod should target Java 21. +java.toolchain.languageVersion = JavaLanguageVersion.of(21) println "Java: ${System.getProperty 'java.version'}, JVM: ${System.getProperty 'java.vm.version'} (${System.getProperty 'java.vendor'}), Arch: ${System.getProperty 'os.arch'}" minecraft { @@ -36,6 +35,9 @@ minecraft { // Use non-default mappings at your own risk. They may not always work. // Simply re-run your setup task after changing the mappings to update your workspace. mappings channel: mapping_channel, version: mapping_version + + // Tell FG to not automtically create the reobf tasks, as we now use Official mappings at runtime, If you don't use them at dev time then you'll have to fix your reobf yourself. + reobf = false // When true, this property will have all Eclipse/IntelliJ IDEA run configurations run the "prepareX" task for the given run configuration before launching the game. // In most cases, it is not necessary to enable. @@ -66,7 +68,7 @@ minecraft { runs { // applies to all the run configs below configureEach { - workingDirectory project.file("run/${it.name}") + workingDirectory project.file('run') // Recommended logging data for a userdev environment // The markers can be added/remove as needed separated by commas. @@ -79,12 +81,6 @@ minecraft { // You can set various levels here. // Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels property 'forge.logging.console.level', 'debug' - - mods { - "${mod_id}" { - source sourceSets.main - } - } } client { @@ -94,7 +90,6 @@ minecraft { server { property 'forge.enabledGameTestNamespaces', mod_id - args '--nogui' } // This run config launches GameTestServer and runs all registered gametests, then exits. @@ -105,8 +100,8 @@ minecraft { } data { - // example of overriding the workingDirectory set in configureEach above, uncomment if you want to use it - // workingDirectory project.file('run-data') + // example of overriding the workingDirectory set in configureEach above + workingDirectory project.file('run-data') // Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources. args '--mod', mod_id, '--all', '--output', file('src/generated/resources/'), '--existing', file('src/main/resources/') @@ -157,7 +152,10 @@ dependencies { // For more info: // http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html - // http://www.gradle.org/docs/current/userguide/dependency_management.html + // http://www.gradle.org/docs/current/userguide/dependency_management.html + + // Hack fix for now, force jopt-simple to be exactly 5.0.4 because Mojang ships that version, but some transitive dependencies request 6.0+ + implementation('net.sf.jopt-simple:jopt-simple:5.0.4') { version { strictly '5.0.4' } } } // This block of code expands all declared replace properties in the specified resource targets. @@ -222,3 +220,13 @@ publishing { tasks.withType(JavaCompile).configureEach { options.encoding = 'UTF-8' // Use the UTF-8 charset for Java compilation } + +// Merge the resources and classes into the same directory. +// This is done because java expects modules to be in a single directory. +// And if we have it in multiple we have to do performance intensive hacks like having the UnionFileSystem +// This will eventually be migrated to ForgeGradle so modders don't need to manually do it. But that is later. +sourceSets.each { + def dir = layout.buildDirectory.dir("sourcesSets/$it.name") + it.output.resourcesDir = dir + it.java.destinationDirectory = dir +} diff --git a/gradle.properties b/gradle.properties index e5f82103..d0986fab 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,18 +6,18 @@ org.gradle.daemon=false ## Environment Properties -# The Minecraft version must agree with the Neo version to get a valid artifact -minecraft_version=1.20.2 +# The Minecraft version must agree with the Forge version to get a valid artifact +minecraft_version=1.20.6 # The Minecraft version range can use any release version of Minecraft as bounds. # Snapshots, pre-releases, and release candidates are not guaranteed to sort properly # as they do not follow standard versioning conventions. -minecraft_version_range=[1.20.2,1.21) +minecraft_version_range=[1.20.6,1.21) # The Forge version must agree with the Minecraft version to get a valid artifact -forge_version=48.0.31 +forge_version=50.1.3 # The Forge version range can use any version of Forge as bounds or match the loader version range -forge_version_range=[48,) +forge_version_range=[0,) # The loader version range can only use the major version of Forge/FML as bounds -loader_version_range=[48,) +loader_version_range=[0,) # The mapping channel to use for mappings. # The default set of supported mapping channels are ["official", "snapshot", "snapshot_nodoc", "stable", "stable_nodoc"]. # Additional mapping channels can be registered through the "channelProviders" extension in a Gradle plugin. @@ -35,7 +35,7 @@ loader_version_range=[48,) mapping_channel=official # The mapping version to query from the mapping channel. # This must match the format required by the mapping channel. -mapping_version=1.20.2 +mapping_version=1.20.6 ## Mod Properties @@ -62,4 +62,4 @@ pack_format_number=15 modloaderName =forge -minecraftVersion =1.20.2 \ No newline at end of file +minecraftVersion =1.20.6 \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 37aef8d3..20db9ad5 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/settings.gradle b/settings.gradle index 291d399d..93f1b806 100644 --- a/settings.gradle +++ b/settings.gradle @@ -9,5 +9,5 @@ pluginManagement { } plugins { - id 'org.gradle.toolchains.foojay-resolver-convention' version '0.5.0' + id 'org.gradle.toolchains.foojay-resolver-convention' version '0.7.0' } \ No newline at end of file diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java index 36d678c1..1afa82ef 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java @@ -20,37 +20,27 @@ public static void register(CommandDispatcher commandDispatc commandDispatcher.register(literal("backup").requires((runner) -> { return true; }).then(literal("start").executes((runner) -> { - Update acknowledgment = Minecraft.getInstance().player.connection.lastSeenMessages.generateAndApplyUpdate().update(); - Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup start", Instant.now(), 0, - ArgumentSignatures.EMPTY, acknowledgment)); + Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup start")); return 1; })) .then(literal("reload-config").executes((runner) -> { - Update acknowledgment = Minecraft.getInstance().player.connection.lastSeenMessages.generateAndApplyUpdate().update(); - Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup reload-config", Instant.now(), 0, - ArgumentSignatures.EMPTY, acknowledgment)); + Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup reload-config")); return 1; })) .then(literal("reset-chain").executes((runner) -> { - Update acknowledgment = Minecraft.getInstance().player.connection.lastSeenMessages.generateAndApplyUpdate().update(); - Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup reset-chain", Instant.now(), 0, - ArgumentSignatures.EMPTY, acknowledgment)); + Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup reset-chain")); return 1; })) .then(literal("snapshot").executes((runner) -> { - Update acknowledgment = Minecraft.getInstance().player.connection.lastSeenMessages.generateAndApplyUpdate().update(); - Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup snapshot", Instant.now(), 0, - ArgumentSignatures.EMPTY, acknowledgment)); + Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup snapshot")); return 1; })) .then(literal("cancel").executes((runner) -> { - Update acknowledgment = Minecraft.getInstance().player.connection.lastSeenMessages.generateAndApplyUpdate().update(); - Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup cancel", Instant.now(), 0, - ArgumentSignatures.EMPTY, acknowledgment)); + Minecraft.getInstance().player.connection.send(new ServerboundChatCommandPacket("backup cancel")); return 1; })) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java index bdfdfa80..5f4631db 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java @@ -2,8 +2,8 @@ import co.uk.mommyheather.advancedbackups.client.ClientWrapper; import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.protocol.PacketFlow; import net.minecraftforge.event.network.CustomPayloadEvent; -import net.minecraftforge.fml.LogicalSide; public class PacketBackupStatus { @@ -54,7 +54,7 @@ public void toBytes(FriendlyByteBuf buf) { public static boolean handle(PacketBackupStatus message, CustomPayloadEvent.Context ctx) { ctx.enqueueWork(() -> { - if (ctx.getDirection().getReceptionSide() == LogicalSide.CLIENT) { + if (ctx.getConnection().getReceiving() == PacketFlow.CLIENTBOUND) { ClientWrapper.handle(message); } }); From 42e3f58de1cf6f954bd6615ec9e366051c865833 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Wed, 12 Jun 2024 19:29:53 +0100 Subject: [PATCH 499/580] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 34f365d6..02ce4a92 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Forge - 1.20 +# Forge - 1.20.2 This is the branch specifically for forge 1.20. Any differences will be listed below. For full documentation, see the `core` branch. From c622b0f4e875a170be1b5c9a54d1bc55a724efb6 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Wed, 12 Jun 2024 19:32:49 +0100 Subject: [PATCH 500/580] remove unused imports --- .../uk/mommyheather/advancedbackups/network/NetworkHandler.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java index f5c208e6..97da3a5d 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java @@ -3,8 +3,6 @@ import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; import net.minecraftforge.network.ChannelBuilder; -import net.minecraftforge.network.NetworkDirection; -import net.minecraftforge.network.NetworkRegistry; import net.minecraftforge.network.SimpleChannel; public class NetworkHandler { From 1c5b29ab77b1146151e2fb46d310336e76d46081 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Wed, 12 Jun 2024 19:48:35 +0100 Subject: [PATCH 501/580] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c6254984..e138f081 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Fabric - 1.19 +# Fabric - 1.19.3 -This is the branch specifically for fabric 1.19. +This is the branch specifically for fabric 1.19.3 / 1.19.4 Any differences will be listed below. For full documentation, see the `core` branch. From 647313cf651500fde1dc76cbdac27ace864da784 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Wed, 12 Jun 2024 19:48:57 +0100 Subject: [PATCH 502/580] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 09db287c..8c973847 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Fabric - 1.20 +# Fabric - 1.20.2 -This is the branch specifically for fabric 1.20. +This is the branch specifically for fabric 1.20.2. Any differences will be listed below. For full documentation, see the `core` branch. From 524c8f5b62bb3256764c9087c49a0502b4948c1f Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Wed, 12 Jun 2024 19:49:11 +0100 Subject: [PATCH 503/580] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b811bcda..59ab5213 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Fabric - 1.20.5 +# Fabric - 1.20.6 -This is the branch specifically for fabric 1.20.5. +This is the branch specifically for fabric 1.20.6. Any differences will be listed below. For full documentation, see the `core` branch. From 7ea6d40d4b7c35e547b31e445f4dd507c4b59ed9 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Wed, 12 Jun 2024 19:54:20 +0100 Subject: [PATCH 504/580] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 11effd38..50337d0b 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Forge - 1.19 +# Forge - 1.19.3 -This is the branch specifically for forge 1.19. -Any differences will be listed below. For full documentation, see the `core` branch. \ No newline at end of file +This is the branch specifically for forge 1.19.3 / 1.19.4. +Any differences will be listed below. For full documentation, see the `core` branch. From 98575fa2697a29b995e2551a90718f2a6f36dad1 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Wed, 12 Jun 2024 19:54:38 +0100 Subject: [PATCH 505/580] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 02ce4a92..3826329f 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ # Forge - 1.20.2 -This is the branch specifically for forge 1.20. +This is the branch specifically for forge 1.20.2. Any differences will be listed below. For full documentation, see the `core` branch. From d1fdf4c31122f374e2083b51806135904e4af331 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Wed, 12 Jun 2024 19:54:51 +0100 Subject: [PATCH 506/580] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f1b8d2a3..b22e47af 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ # Forge - 1.20.6 -This is the branch specifically for forge 1.20. +This is the branch specifically for forge 1.20.6. Any differences will be listed below. For full documentation, see the `core` branch. From f987724e27b0995499afde557b06efaa312d6de3 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Wed, 12 Jun 2024 19:56:35 +0100 Subject: [PATCH 507/580] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5e146fc9..46760a8d 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Forge - 1.20 +# Neoforge - 1.20.2 -This is the branch specifically for forge 1.20. +This is the branch specifically for neoforge 1.20.2. Any differences will be listed below. For full documentation, see the `core` branch. From ab7e8350f7f3a88ddb97f9a212394881891307fa Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Wed, 12 Jun 2024 19:56:56 +0100 Subject: [PATCH 508/580] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f11c15e1..8fa7bc54 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Neoforge - 1.20.5 +# Neoforge - 1.20.6 -This is the branch specifically for neoforge 1.20.5 +This is the branch specifically for neoforge 1.20.6. Any differences will be listed below. For full documentation, see the `core` branch. From ddcf3be0f2bc75a15d4f39065a64a0719bd5e8cf Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Wed, 12 Jun 2024 20:04:10 +0100 Subject: [PATCH 509/580] remove erroneous reobf mentions --- build.gradle | 6 ------ 1 file changed, 6 deletions(-) diff --git a/build.gradle b/build.gradle index 9160221a..ea78d171 100644 --- a/build.gradle +++ b/build.gradle @@ -194,14 +194,8 @@ tasks.named('jar', Jar).configure { from { configurations.extraLibs.collect { it.isDirectory() ? it : zipTree(it) } } - // This is the preferred method to reobfuscate your jar file - finalizedBy 'reobfJar' } -// However if you are in a multi-project build, dev time needs unobfed jar files, so you can delay the obfuscation until publishing by doing: -// tasks.named('publish').configure { -// dependsOn 'reobfJar' -// } // Example configuration to allow publishing using the maven-publish plugin publishing { From 8e891e3e04589e4e753fa947d815cb393cbf675b Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Sun, 16 Jun 2024 02:40:09 +0100 Subject: [PATCH 510/580] support for 3.6 changes --- .../advancedbackups/AdvancedBackups.java | 402 +++++++++--------- .../client/ABClientContactor.java | 184 ++++---- 2 files changed, 292 insertions(+), 294 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index c378312d..57a4c84d 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -1,204 +1,198 @@ -package co.uk.mommyheather.advancedbackups; - -import net.minecraft.command.server.CommandSaveAll; -import net.minecraft.init.Blocks; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.management.ServerConfigurationManager; -import net.minecraft.util.IProgressUpdate; -import net.minecraft.world.MinecraftException; -import net.minecraft.world.WorldServer; - -import org.apache.logging.log4j.Logger; - -import co.uk.mommyheather.advancedbackups.client.ABClientContactor; -import co.uk.mommyheather.advancedbackups.client.ABClientRenderer; -import co.uk.mommyheather.advancedbackups.core.ABCore; -import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; -import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; -import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; -import co.uk.mommyheather.advancedbackups.network.NetworkHandler; -import cpw.mods.fml.common.FMLCommonHandler; -import cpw.mods.fml.common.Loader; -import cpw.mods.fml.common.Mod; -import cpw.mods.fml.common.Mod.EventHandler; -import cpw.mods.fml.common.event.FMLPreInitializationEvent; -import cpw.mods.fml.common.event.FMLServerStartedEvent; -import cpw.mods.fml.common.event.FMLServerStartingEvent; -import cpw.mods.fml.common.event.FMLServerStoppingEvent; -import cpw.mods.fml.common.eventhandler.SubscribeEvent; -import cpw.mods.fml.common.gameevent.PlayerEvent; -import cpw.mods.fml.common.gameevent.TickEvent; -import cpw.mods.fml.relauncher.Side; -import net.minecraftforge.common.MinecraftForge; - -import java.io.File; -import java.util.ArrayList; -import java.util.function.Consumer; - -@Mod(modid = AdvancedBackups.MODID, name = AdvancedBackups.NAME, acceptableRemoteVersions = "*") -public class AdvancedBackups -{ - public static final String MODID = "advancedbackups"; - public static final String NAME = "Advanced Backups"; - - private static Logger LOGGER; - public static Consumer infoLogger; - public static Consumer warningLogger; - public static Consumer errorLogger; - - public static ArrayList players = new ArrayList<>(); - - public static MinecraftServer server; - - @EventHandler - public void preInit(FMLPreInitializationEvent event) - { - LOGGER = event.getModLog(); - infoLogger = LOGGER::info; - warningLogger = LOGGER::warn; - errorLogger = LOGGER::error; - } - - - - public AdvancedBackups() - { - // Register ourselves for server and other game events we are interested in - MinecraftForge.EVENT_BUS.register(this); - FMLCommonHandler.instance().bus().register(this); - MinecraftForge.EVENT_BUS.register(ABClientRenderer.INSTANCE); - FMLCommonHandler.instance().bus().register(ABClientRenderer.INSTANCE); - NetworkHandler.init(); - } - - @EventHandler - public void onServerStarting(FMLServerStartingEvent event) - { - // Do something when the server starts - ABCore.worldName = event.getServer().worldServers[0].getWorldInfo().getWorldName(); - - //Yes, this works. Yes, it feels FUCKING ILLEGAL - if (event.getSide() == Side.SERVER) { - ABCore.worldDir = new File(event.getServer().getFolderName(), "./").toPath(); - } - else { - ABCore.worldDir = new File("saves/" + event.getServer().getFolderName(), "./").toPath(); - } - // the extra ./ is because some of the code in core calls a getParent as it was required when devving in my forge 1.18 instance, but versions earlier than 1.16 do not have this requirement - - server = event.getServer(); - - ABCore.disableSaving = AdvancedBackups::disableSaving; - ABCore.enableSaving = AdvancedBackups::enableSaving; - ABCore.saveOnce = AdvancedBackups::saveOnce; - - ABCore.infoLogger = infoLogger; - ABCore.warningLogger = warningLogger; - ABCore.errorLogger = errorLogger; - - ABCore.clientContactor = new ABClientContactor(); - ABCore.resetActivity = AdvancedBackups::resetActivity; - - event.registerServerCommand(new AdvancedBackupsCommand()); - - ABCore.modJar = Loader.instance().getIndexedModList().get("advancedbackups").getSource(); - - ConfigManager.loadOrCreateConfig(); - LOGGER.info("Config loaded!!"); - - } - - - @EventHandler - public void onServerStarted(FMLServerStartedEvent event) { - BackupWrapper.checkStartupBackups(); - } - - @EventHandler - public void onServerStopping(FMLServerStoppingEvent event) { - BackupWrapper.checkShutdownBackups(); - } - - @SubscribeEvent - public void onPlayerConnected(PlayerEvent.PlayerLoggedInEvent event) { - ABCore.setActivity(true); - } - - @SubscribeEvent - public void onTickEnd(TickEvent.ServerTickEvent event) { - if (!event.phase.equals(TickEvent.Phase.END)) return; - BackupTimer.check(); - } - - - public static final String savesDisabledMessage = "\n\n\n***************************************\nSAVING DISABLED - PREPARING FOR BACKUP!\n***************************************"; - public static final String savesEnabledMessage = "\n\n\n*********************************\nSAVING ENABLED - BACKUP COMPLETE!\n*********************************"; - public static final String saveCompleteMessage = "\n\n\n*************************************\nSAVE COMPLETE - PREPARING FOR BACKUP!\n*************************************"; - - - //fun fact : this boolean is named wrong in MCP mappings! - //reference : net.minecraft.command.server.CommandSaveOff and CommandSaveOn - //notice how off sets the boolean to true, and on sets it to false! - public static void disableSaving() { - MinecraftServer server = AdvancedBackups.server; - for (WorldServer level : server.worldServers) { - if (level != null && !level.levelSaving) { - level.levelSaving = true; - } - } - if (ConfigManager.silent.get()) return; - warningLogger.accept(savesDisabledMessage); - } - - public static void enableSaving() { - MinecraftServer server = AdvancedBackups.server; - for (WorldServer level : server.worldServers) { - if (level != null && level.levelSaving) { - level.levelSaving = false; - } - } - if (ConfigManager.silent.get()) return; - warningLogger.accept(savesEnabledMessage); - } - - public static void saveOnce(boolean unused) { //flush doesn't seem to be an option in 1.7.10 - try { - MinecraftServer server = AdvancedBackups.server; - if (server.getConfigurationManager() != null) - { - server.getConfigurationManager().saveAllPlayerData(); - } - - int i; - WorldServer worldserver; - boolean flag; - - for (i = 0; i < server.worldServers.length; ++i) - { - if (server.worldServers[i] != null) - { - worldserver = server.worldServers[i]; - flag = worldserver.levelSaving; - worldserver.levelSaving = false; - worldserver.saveAllChunks(true, (IProgressUpdate)null); - worldserver.levelSaving = flag; - } - } - - - if (ConfigManager.silent.get()) return; - warningLogger.accept(saveCompleteMessage); - } catch (MinecraftException e) { - // TODO Scream at user - errorLogger.accept("FAILED TO SAVE WORLD!"); - e.printStackTrace(); - } - } - - - public static void resetActivity() { - ServerConfigurationManager configurationManager = server.getConfigurationManager(); - ABCore.setActivity(!configurationManager.playerEntityList.isEmpty()); - } - -} +package co.uk.mommyheather.advancedbackups; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.management.ServerConfigurationManager; +import net.minecraft.util.IProgressUpdate; +import net.minecraft.world.MinecraftException; +import net.minecraft.world.WorldServer; + +import org.apache.logging.log4j.Logger; + +import co.uk.mommyheather.advancedbackups.client.ABClientContactor; +import co.uk.mommyheather.advancedbackups.client.ABClientRenderer; +import co.uk.mommyheather.advancedbackups.core.ABCore; +import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; +import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; +import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; +import cpw.mods.fml.common.FMLCommonHandler; +import cpw.mods.fml.common.Loader; +import cpw.mods.fml.common.Mod; +import cpw.mods.fml.common.Mod.EventHandler; +import cpw.mods.fml.common.event.FMLPreInitializationEvent; +import cpw.mods.fml.common.event.FMLServerStartedEvent; +import cpw.mods.fml.common.event.FMLServerStartingEvent; +import cpw.mods.fml.common.event.FMLServerStoppingEvent; +import cpw.mods.fml.common.eventhandler.SubscribeEvent; +import cpw.mods.fml.common.gameevent.PlayerEvent; +import cpw.mods.fml.common.gameevent.TickEvent; +import cpw.mods.fml.relauncher.Side; +import net.minecraftforge.common.MinecraftForge; + +import java.io.File; +import java.util.ArrayList; +import java.util.function.Consumer; + +@Mod(modid = AdvancedBackups.MODID, name = AdvancedBackups.NAME, acceptableRemoteVersions = "*") +public class AdvancedBackups +{ + public static final String MODID = "advancedbackups"; + public static final String NAME = "Advanced Backups"; + + private static Logger LOGGER; + public static Consumer infoLogger; + public static Consumer warningLogger; + public static Consumer errorLogger; + + public static ArrayList players = new ArrayList<>(); + + public static MinecraftServer server; + + @EventHandler + public void preInit(FMLPreInitializationEvent event) + { + LOGGER = event.getModLog(); + infoLogger = LOGGER::info; + warningLogger = LOGGER::warn; + errorLogger = LOGGER::error; + } + + + + public AdvancedBackups() + { + // Register ourselves for server and other game events we are interested in + MinecraftForge.EVENT_BUS.register(this); + FMLCommonHandler.instance().bus().register(this); + MinecraftForge.EVENT_BUS.register(ABClientRenderer.INSTANCE); + FMLCommonHandler.instance().bus().register(ABClientRenderer.INSTANCE); + NetworkHandler.init(); + } + + @EventHandler + public void onServerStarting(FMLServerStartingEvent event) + { + // Do something when the server starts + ABCore.worldName = event.getServer().worldServers[0].getWorldInfo().getWorldName(); + + //Yes, this works. Yes, it feels FUCKING ILLEGAL + if (event.getSide() == Side.SERVER) { + ABCore.worldDir = new File(event.getServer().getFolderName(), "./").toPath(); + } + else { + ABCore.worldDir = new File("saves/" + event.getServer().getFolderName(), "./").toPath(); + } + // the extra ./ is because some of the code in core calls a getParent as it was required when devving in my forge 1.18 instance, but versions earlier than 1.16 do not have this requirement + + server = event.getServer(); + + ABCore.disableSaving = AdvancedBackups::disableSaving; + ABCore.enableSaving = AdvancedBackups::enableSaving; + ABCore.saveOnce = AdvancedBackups::saveOnce; + + ABCore.infoLogger = infoLogger; + ABCore.warningLogger = warningLogger; + ABCore.errorLogger = errorLogger; + + ABCore.clientContactor = new ABClientContactor(); + ABCore.resetActivity = AdvancedBackups::resetActivity; + + event.registerServerCommand(new AdvancedBackupsCommand()); + + ABCore.modJar = Loader.instance().getIndexedModList().get("advancedbackups").getSource(); + + ConfigManager.loadOrCreateConfig(); + LOGGER.info("Config loaded!!"); + + } + + + @EventHandler + public void onServerStarted(FMLServerStartedEvent event) { + BackupWrapper.checkStartupBackups(); + } + + @EventHandler + public void onServerStopping(FMLServerStoppingEvent event) { + BackupWrapper.checkShutdownBackups(); + } + + @SubscribeEvent + public void onPlayerConnected(PlayerEvent.PlayerLoggedInEvent event) { + ABCore.setActivity(true); + } + + @SubscribeEvent + public void onTickEnd(TickEvent.ServerTickEvent event) { + if (!event.phase.equals(TickEvent.Phase.END)) return; + BackupTimer.check(); + } + + + public static final String savesDisabledMessage = "\n\n\n***************************************\nSAVING DISABLED - PREPARING FOR BACKUP!\n***************************************"; + public static final String savesEnabledMessage = "\n\n\n*********************************\nSAVING ENABLED - BACKUP COMPLETE!\n*********************************"; + public static final String saveCompleteMessage = "\n\n\n*************************************\nSAVE COMPLETE - PREPARING FOR BACKUP!\n*************************************"; + + + //fun fact : this boolean is named wrong in MCP mappings! + //reference : net.minecraft.command.server.CommandSaveOff and CommandSaveOn + //notice how off sets the boolean to true, and on sets it to false! + public static void disableSaving() { + MinecraftServer server = AdvancedBackups.server; + for (WorldServer level : server.worldServers) { + if (level != null && !level.levelSaving) { + level.levelSaving = true; + } + } + warningLogger.accept(savesDisabledMessage); + } + + public static void enableSaving() { + MinecraftServer server = AdvancedBackups.server; + for (WorldServer level : server.worldServers) { + if (level != null && level.levelSaving) { + level.levelSaving = false; + } + } + warningLogger.accept(savesEnabledMessage); + } + + public static void saveOnce(boolean unused) { //flush doesn't seem to be an option in 1.7.10 + try { + MinecraftServer server = AdvancedBackups.server; + if (server.getConfigurationManager() != null) + { + server.getConfigurationManager().saveAllPlayerData(); + } + + int i; + WorldServer worldserver; + boolean flag; + + for (i = 0; i < server.worldServers.length; ++i) + { + if (server.worldServers[i] != null) + { + worldserver = server.worldServers[i]; + flag = worldserver.levelSaving; + worldserver.levelSaving = false; + worldserver.saveAllChunks(true, (IProgressUpdate)null); + worldserver.levelSaving = flag; + } + } + + warningLogger.accept(saveCompleteMessage); + } catch (MinecraftException e) { + // TODO Scream at user + errorLogger.accept("FAILED TO SAVE WORLD!"); + e.printStackTrace(); + } + } + + + public static void resetActivity() { + ServerConfigurationManager configurationManager = server.getConfigurationManager(); + ABCore.setActivity(!configurationManager.playerEntityList.isEmpty()); + } + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ABClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ABClientContactor.java index 9c922b95..c0ceefdb 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ABClientContactor.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ABClientContactor.java @@ -1,90 +1,94 @@ -package co.uk.mommyheather.advancedbackups.client; - - -import co.uk.mommyheather.advancedbackups.AdvancedBackups; -import co.uk.mommyheather.advancedbackups.interfaces.IClientContactor; -import co.uk.mommyheather.advancedbackups.network.NetworkHandler; -import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; -import net.minecraft.entity.player.EntityPlayerMP; -import net.minecraft.server.management.ServerConfigurationManager; - -@SuppressWarnings("unchecked") -public class ABClientContactor implements IClientContactor { - - @Override - public void backupComplete() { - ServerConfigurationManager configurationManager = AdvancedBackups.server.getConfigurationManager(); - PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, false, 0, 0); - configurationManager.playerEntityList.forEach((player) -> { - if (player instanceof EntityPlayerMP) { - EntityPlayerMP playerMP = (EntityPlayerMP) player; - if (!AdvancedBackups.players.contains(playerMP.getGameProfile().getId().toString())) return; - //if they can run the command, or are in singleplayer, they should receive info on active backups. - if (playerMP.canCommandSenderUseCommand(3, "advancedbackups") || !AdvancedBackups.server.isDedicatedServer()) { - NetworkHandler.HANDLER.sendTo(packet, playerMP); - } - } - }); - } - - @Override - public void backupFailed() { - ServerConfigurationManager configurationManager = AdvancedBackups.server.getConfigurationManager(); - PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, false, 0, 0); - configurationManager.playerEntityList.forEach((player) -> { - if (player instanceof EntityPlayerMP) { - EntityPlayerMP playerMP = (EntityPlayerMP) player; - if (!AdvancedBackups.players.contains(playerMP.getGameProfile().getId().toString())) return; - if (playerMP.canCommandSenderUseCommand(3, "advancedbackups")) { //if they can run the command, they should receive info on active backups - NetworkHandler.HANDLER.sendTo(packet, playerMP); - } - } - }); - } - - @Override - public void backupProgress(int progress, int max) { - ServerConfigurationManager configurationManager = AdvancedBackups.server.getConfigurationManager(); - PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, false, progress, max); - configurationManager.playerEntityList.forEach((player) -> { - if (player instanceof EntityPlayerMP) { - EntityPlayerMP playerMP = (EntityPlayerMP) player; - if (!AdvancedBackups.players.contains(playerMP.getGameProfile().getId().toString())) return; - if (playerMP.canCommandSenderUseCommand(3, "advancedbackups")) { //if they can run the command, they should receive info on active backups - NetworkHandler.HANDLER.sendTo(packet, playerMP); - } - } - }); - } - - @Override - public void backupStarting() { - ServerConfigurationManager configurationManager = AdvancedBackups.server.getConfigurationManager(); - PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, false, 0, 0); - configurationManager.playerEntityList.forEach((player) -> { - if (player instanceof EntityPlayerMP) { - EntityPlayerMP playerMP = (EntityPlayerMP) player; - if (!AdvancedBackups.players.contains(playerMP.getGameProfile().getId().toString())) return; - if (playerMP.canCommandSenderUseCommand(3, "advancedbackups")) { //if they can run the command, they should receive info on active backups - NetworkHandler.HANDLER.sendTo(packet, playerMP); - } - } - }); - } - - @Override - public void backupCancelled() { - ServerConfigurationManager configurationManager = AdvancedBackups.server.getConfigurationManager(); - PacketBackupStatus packet = new PacketBackupStatus(false, false, false, false, true, 0, 0); - configurationManager.playerEntityList.forEach((player) -> { - if (player instanceof EntityPlayerMP) { - EntityPlayerMP playerMP = (EntityPlayerMP) player; - if (!AdvancedBackups.players.contains(playerMP.getGameProfile().getId().toString())) return; - if (playerMP.canCommandSenderUseCommand(3, "advancedbackups")) { //if they can run the command, they should receive info on active backups - NetworkHandler.HANDLER.sendTo(packet, playerMP); - } - } - }); - } - -} +package co.uk.mommyheather.advancedbackups.client; + + +import co.uk.mommyheather.advancedbackups.AdvancedBackups; +import co.uk.mommyheather.advancedbackups.interfaces.IClientContactor; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; +import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.server.management.ServerConfigurationManager; + +@SuppressWarnings("unchecked") +public class ABClientContactor implements IClientContactor { + + @Override + public void backupComplete(boolean all) { + ServerConfigurationManager configurationManager = AdvancedBackups.server.getConfigurationManager(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, false, 0, 0); + configurationManager.playerEntityList.forEach((player) -> { + if (player instanceof EntityPlayerMP) { + EntityPlayerMP playerMP = (EntityPlayerMP) player; + if (!AdvancedBackups.players.contains(playerMP.getGameProfile().getId().toString())) return; + //if they can run the command, or are in singleplayer, or config says all players, they should receive info on active backups. + if (playerMP.canCommandSenderUseCommand(3, "advancedbackups") || !AdvancedBackups.server.isDedicatedServer() || all) { + NetworkHandler.HANDLER.sendTo(packet, playerMP); + } + } + }); + } + + @Override + public void backupFailed(boolean all) { + ServerConfigurationManager configurationManager = AdvancedBackups.server.getConfigurationManager(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, false, 0, 0); + configurationManager.playerEntityList.forEach((player) -> { + if (player instanceof EntityPlayerMP) { + EntityPlayerMP playerMP = (EntityPlayerMP) player; + if (!AdvancedBackups.players.contains(playerMP.getGameProfile().getId().toString())) return; + //if they can run the command, or are in singleplayer, or config says all players, they should receive info on active backups. + if (playerMP.canCommandSenderUseCommand(3, "advancedbackups") || !AdvancedBackups.server.isDedicatedServer() || all) { + NetworkHandler.HANDLER.sendTo(packet, playerMP); + } + } + }); + } + + @Override + public void backupProgress(int progress, int max, boolean all) { + ServerConfigurationManager configurationManager = AdvancedBackups.server.getConfigurationManager(); + PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, false, progress, max); + configurationManager.playerEntityList.forEach((player) -> { + if (player instanceof EntityPlayerMP) { + EntityPlayerMP playerMP = (EntityPlayerMP) player; + if (!AdvancedBackups.players.contains(playerMP.getGameProfile().getId().toString())) return; + //if they can run the command, or are in singleplayer, or config says all players, they should receive info on active backups. + if (playerMP.canCommandSenderUseCommand(3, "advancedbackups") || !AdvancedBackups.server.isDedicatedServer() || all) { + NetworkHandler.HANDLER.sendTo(packet, playerMP); + } + } + }); + } + + @Override + public void backupStarting(boolean all) { + ServerConfigurationManager configurationManager = AdvancedBackups.server.getConfigurationManager(); + PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, false, 0, 0); + configurationManager.playerEntityList.forEach((player) -> { + if (player instanceof EntityPlayerMP) { + EntityPlayerMP playerMP = (EntityPlayerMP) player; + if (!AdvancedBackups.players.contains(playerMP.getGameProfile().getId().toString())) return; + //if they can run the command, or are in singleplayer, or config says all players, they should receive info on active backups. + if (playerMP.canCommandSenderUseCommand(3, "advancedbackups") || !AdvancedBackups.server.isDedicatedServer() || all) { + NetworkHandler.HANDLER.sendTo(packet, playerMP); + } + } + }); + } + + @Override + public void backupCancelled(boolean all) { + ServerConfigurationManager configurationManager = AdvancedBackups.server.getConfigurationManager(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, false, false, true, 0, 0); + configurationManager.playerEntityList.forEach((player) -> { + if (player instanceof EntityPlayerMP) { + EntityPlayerMP playerMP = (EntityPlayerMP) player; + if (!AdvancedBackups.players.contains(playerMP.getGameProfile().getId().toString())) return; + //if they can run the command, or are in singleplayer, or config says all players, they should receive info on active backups. + if (playerMP.canCommandSenderUseCommand(3, "advancedbackups") || !AdvancedBackups.server.isDedicatedServer() || all) { + NetworkHandler.HANDLER.sendTo(packet, playerMP); + } + } + }); + } + +} From e62b504af37646f78b16ba81f820ef59f98edd2a Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Mon, 17 Jun 2024 00:02:17 +0100 Subject: [PATCH 511/580] support v3.6 changes --- .../advancedbackups/AdvancedBackups.java | 405 +++++++++--------- .../client/ClientContactor.java | 146 +++---- 2 files changed, 274 insertions(+), 277 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 4fb138eb..c89e6f91 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -1,204 +1,201 @@ -package co.uk.mommyheather.advancedbackups; - -import java.io.File; -import java.util.ArrayList; -import java.util.List; -import java.util.function.Consumer; - -import org.apache.logging.log4j.Logger; - -import co.uk.mommyheather.advancedbackups.client.ClientBridge; -import co.uk.mommyheather.advancedbackups.client.ClientContactor; -import co.uk.mommyheather.advancedbackups.core.ABCore; -import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; -import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; -import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; -import co.uk.mommyheather.advancedbackups.network.NetworkHandler; -import co.uk.mommyheather.advancedbackups.network.PacketToastTest; -import net.minecraft.entity.player.EntityPlayerMP; -import net.minecraft.server.MinecraftServer; -import net.minecraft.world.WorldServer; -import net.minecraftforge.client.event.ClientChatEvent; -import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.fml.common.Loader; -import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.fml.common.Mod.EventBusSubscriber; -import net.minecraftforge.fml.common.Mod.EventHandler; -import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; -import net.minecraftforge.fml.common.event.FMLServerStartedEvent; -import net.minecraftforge.fml.common.event.FMLServerStartingEvent; -import net.minecraftforge.fml.common.event.FMLServerStoppingEvent; -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; -import net.minecraftforge.fml.common.gameevent.PlayerEvent; -import net.minecraftforge.fml.common.gameevent.TickEvent; -import net.minecraftforge.fml.common.gameevent.PlayerEvent.PlayerLoggedInEvent; -import net.minecraftforge.fml.relauncher.Side; - - -@Mod(modid = AdvancedBackups.MODID, name = AdvancedBackups.NAME, acceptableRemoteVersions = "*") -@EventBusSubscriber -public class AdvancedBackups -{ - public static final String MODID = "advancedbackups"; - public static final String NAME = "Advanced Backups"; - - private static Logger LOGGER; - public static Consumer infoLogger; - public static Consumer warningLogger; - public static Consumer errorLogger; - - public static final ArrayList players = new ArrayList<>(); - - public static MinecraftServer server; - - @EventHandler - public void preInit(FMLPreInitializationEvent event) - { - LOGGER = event.getModLog(); - infoLogger = LOGGER::info; - warningLogger = LOGGER::warn; - errorLogger = LOGGER::error; - } - - - - public AdvancedBackups() - { - // Register ourselves for server and other game events we are interested in - MinecraftForge.EVENT_BUS.register(this); - NetworkHandler.registerMessages(); - } - - @EventHandler - public void onServerStarting(FMLServerStartingEvent event) - { - // Do something when the server starts - ABCore.worldName = event.getServer().worlds[0].getWorldInfo().getWorldName(); - - //Yes, this works. Yes, it feels FUCKING ILLEGAL - if (event.getSide() == Side.SERVER) { - ABCore.worldDir = new File(event.getServer().getFolderName(), "./").toPath(); - } - else { - ABCore.worldDir = new File("saves/" + event.getServer().getFolderName(), "./").toPath(); - } - // the extra ./ is because some of the code in core calls a getParent as it was required when devving in my forge 1.18 instance, but versions earlier than 1.16 do not have this requirement - - server = event.getServer(); - - ABCore.disableSaving = AdvancedBackups::disableSaving; - ABCore.enableSaving = AdvancedBackups::enableSaving; - ABCore.saveOnce = AdvancedBackups::saveOnce; - - ABCore.infoLogger = infoLogger; - ABCore.warningLogger = warningLogger; - ABCore.errorLogger = errorLogger; - - ABCore.resetActivity = AdvancedBackups::resetActivity; - - ABCore.clientContactor = new ClientContactor(); - - ABCore.modJar = Loader.instance().getIndexedModList().get("advancedbackups").getSource(); - //ModList.get().getModFileById("advancedbackups").getFile().getFilePath().toFile(); - ConfigManager.loadOrCreateConfig(); - LOGGER.info("Config loaded!!"); - - - - event.registerServerCommand(new AdvancedBackupsCommand()); - - } - - @EventHandler - public void onServerStarted(FMLServerStartedEvent event) { - BackupWrapper.checkStartupBackups(); - } - - @EventHandler - public void onServerStopping(FMLServerStoppingEvent event) { - BackupWrapper.checkShutdownBackups(); - } - - @SubscribeEvent - public void onPlayerConnect(PlayerEvent.PlayerLoggedInEvent event) { - ABCore.setActivity(true); - } - - @SubscribeEvent - public void onTickEnd(TickEvent.ServerTickEvent event) { - if (!event.phase.equals(TickEvent.Phase.END)) return; - BackupTimer.check(); - } - - @SubscribeEvent - public void onConnectedToServer(PlayerLoggedInEvent event) { - - //Here's our answer. - //Player logs in. Server sends them a packet. Client responds with a different packet to indicate their wish to subscribe to toasts. - //It means a single packet at login is sent to clients without the mod, but it should be dropped fine. - if (event.player instanceof EntityPlayerMP) { - NetworkHandler.HANDLER.sendTo(new PacketToastTest(), (EntityPlayerMP) event.player); - } - - - /*ClientConfigManager.loadOrCreateConfig(); - - //NetworkHandler.HANDLER.sendToServer(new PacketToastSubscribe(ClientConfigManager.showProgress.get())); - - - //You serious? If I use the above line, the packet is just never received. - //DONE : rework this in a nicer way. Use something other than a fucking threaded five second delay. - new Thread(() -> { - try { - Thread.sleep(5000); - } catch (InterruptedException e) { - - } - NetworkHandler.HANDLER.sendToServer(new PacketToastSubscribe(ClientConfigManager.showProgress.get())); - }).start();*/ - } - - @SubscribeEvent - public void onClientChat(ClientChatEvent event) { - ClientBridge.onClientChat(event); - } - - - - public static final String savesDisabledMessage = "\n\n\n***************************************\nSAVING DISABLED - PREPARING FOR BACKUP!\n***************************************"; - public static final String savesEnabledMessage = "\n\n\n*********************************\nSAVING ENABLED - BACKUP COMPLETE!\n*********************************"; - public static final String saveCompleteMessage = "\n\n\n*************************************\nSAVE COMPLETE - PREPARING FOR BACKUP!\n*************************************"; - - - public static void disableSaving() { - for (WorldServer level : server.worlds) { - if (level != null && !level.disableLevelSaving) { - level.disableLevelSaving = true; - } - } - if (ConfigManager.silent.get()) return; - warningLogger.accept(savesDisabledMessage); - } - - public static void enableSaving() { - for (WorldServer level : server.worlds) { - if (level != null && level.disableLevelSaving) { - level.disableLevelSaving = false; - } - } - if (ConfigManager.silent.get()) return; - warningLogger.accept(savesEnabledMessage); - } - - public static void saveOnce(boolean unused) { //no flush bool in 1.12 either - server.saveAllWorlds(false); - if (ConfigManager.silent.get()) return; - warningLogger.accept(saveCompleteMessage); - } - - public static void resetActivity() { - List players = server.getPlayerList().getPlayers(); - ABCore.setActivity(!players.isEmpty()); - } - -} +package co.uk.mommyheather.advancedbackups; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; + +import org.apache.logging.log4j.Logger; + +import co.uk.mommyheather.advancedbackups.client.ClientBridge; +import co.uk.mommyheather.advancedbackups.client.ClientContactor; +import co.uk.mommyheather.advancedbackups.core.ABCore; +import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; +import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; +import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; +import co.uk.mommyheather.advancedbackups.network.PacketToastTest; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.server.MinecraftServer; +import net.minecraft.world.WorldServer; +import net.minecraftforge.client.event.ClientChatEvent; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.fml.common.Loader; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.Mod.EventBusSubscriber; +import net.minecraftforge.fml.common.Mod.EventHandler; +import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; +import net.minecraftforge.fml.common.event.FMLServerStartedEvent; +import net.minecraftforge.fml.common.event.FMLServerStartingEvent; +import net.minecraftforge.fml.common.event.FMLServerStoppingEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.PlayerEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; +import net.minecraftforge.fml.common.gameevent.PlayerEvent.PlayerLoggedInEvent; +import net.minecraftforge.fml.relauncher.Side; + + +@Mod(modid = AdvancedBackups.MODID, name = AdvancedBackups.NAME, acceptableRemoteVersions = "*") +@EventBusSubscriber +public class AdvancedBackups +{ + public static final String MODID = "advancedbackups"; + public static final String NAME = "Advanced Backups"; + + private static Logger LOGGER; + public static Consumer infoLogger; + public static Consumer warningLogger; + public static Consumer errorLogger; + + public static final ArrayList players = new ArrayList<>(); + + public static MinecraftServer server; + + @EventHandler + public void preInit(FMLPreInitializationEvent event) + { + LOGGER = event.getModLog(); + infoLogger = LOGGER::info; + warningLogger = LOGGER::warn; + errorLogger = LOGGER::error; + } + + + + public AdvancedBackups() + { + // Register ourselves for server and other game events we are interested in + MinecraftForge.EVENT_BUS.register(this); + NetworkHandler.registerMessages(); + } + + @EventHandler + public void onServerStarting(FMLServerStartingEvent event) + { + // Do something when the server starts + ABCore.worldName = event.getServer().worlds[0].getWorldInfo().getWorldName(); + + //Yes, this works. Yes, it feels FUCKING ILLEGAL + if (event.getSide() == Side.SERVER) { + ABCore.worldDir = new File(event.getServer().getFolderName(), "./").toPath(); + } + else { + ABCore.worldDir = new File("saves/" + event.getServer().getFolderName(), "./").toPath(); + } + // the extra ./ is because some of the code in core calls a getParent as it was required when devving in my forge 1.18 instance, but versions earlier than 1.16 do not have this requirement + + server = event.getServer(); + + ABCore.disableSaving = AdvancedBackups::disableSaving; + ABCore.enableSaving = AdvancedBackups::enableSaving; + ABCore.saveOnce = AdvancedBackups::saveOnce; + + ABCore.infoLogger = infoLogger; + ABCore.warningLogger = warningLogger; + ABCore.errorLogger = errorLogger; + + ABCore.resetActivity = AdvancedBackups::resetActivity; + + ABCore.clientContactor = new ClientContactor(); + + ABCore.modJar = Loader.instance().getIndexedModList().get("advancedbackups").getSource(); + //ModList.get().getModFileById("advancedbackups").getFile().getFilePath().toFile(); + ConfigManager.loadOrCreateConfig(); + LOGGER.info("Config loaded!!"); + + + + event.registerServerCommand(new AdvancedBackupsCommand()); + + } + + @EventHandler + public void onServerStarted(FMLServerStartedEvent event) { + BackupWrapper.checkStartupBackups(); + } + + @EventHandler + public void onServerStopping(FMLServerStoppingEvent event) { + BackupWrapper.checkShutdownBackups(); + } + + @SubscribeEvent + public void onPlayerConnect(PlayerEvent.PlayerLoggedInEvent event) { + ABCore.setActivity(true); + } + + @SubscribeEvent + public void onTickEnd(TickEvent.ServerTickEvent event) { + if (!event.phase.equals(TickEvent.Phase.END)) return; + BackupTimer.check(); + } + + @SubscribeEvent + public void onConnectedToServer(PlayerLoggedInEvent event) { + + //Here's our answer. + //Player logs in. Server sends them a packet. Client responds with a different packet to indicate their wish to subscribe to toasts. + //It means a single packet at login is sent to clients without the mod, but it should be dropped fine. + if (event.player instanceof EntityPlayerMP) { + NetworkHandler.HANDLER.sendTo(new PacketToastTest(), (EntityPlayerMP) event.player); + } + + + /*ClientConfigManager.loadOrCreateConfig(); + + //NetworkHandler.HANDLER.sendToServer(new PacketToastSubscribe(ClientConfigManager.showProgress.get())); + + + //You serious? If I use the above line, the packet is just never received. + //DONE : rework this in a nicer way. Use something other than a fucking threaded five second delay. + new Thread(() -> { + try { + Thread.sleep(5000); + } catch (InterruptedException e) { + + } + NetworkHandler.HANDLER.sendToServer(new PacketToastSubscribe(ClientConfigManager.showProgress.get())); + }).start();*/ + } + + @SubscribeEvent + public void onClientChat(ClientChatEvent event) { + ClientBridge.onClientChat(event); + } + + + + public static final String savesDisabledMessage = "\n\n\n***************************************\nSAVING DISABLED - PREPARING FOR BACKUP!\n***************************************"; + public static final String savesEnabledMessage = "\n\n\n*********************************\nSAVING ENABLED - BACKUP COMPLETE!\n*********************************"; + public static final String saveCompleteMessage = "\n\n\n*************************************\nSAVE COMPLETE - PREPARING FOR BACKUP!\n*************************************"; + + + public static void disableSaving() { + for (WorldServer level : server.worlds) { + if (level != null && !level.disableLevelSaving) { + level.disableLevelSaving = true; + } + } + warningLogger.accept(savesDisabledMessage); + } + + public static void enableSaving() { + for (WorldServer level : server.worlds) { + if (level != null && level.disableLevelSaving) { + level.disableLevelSaving = false; + } + } + warningLogger.accept(savesEnabledMessage); + } + + public static void saveOnce(boolean unused) { //no flush bool in 1.12 either + server.saveAllWorlds(false); + warningLogger.accept(saveCompleteMessage); + } + + public static void resetActivity() { + List players = server.getPlayerList().getPlayers(); + ABCore.setActivity(!players.isEmpty()); + } + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java index f7d450d2..85d02911 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java @@ -1,73 +1,73 @@ -package co.uk.mommyheather.advancedbackups.client; - -import java.util.List; - -import co.uk.mommyheather.advancedbackups.AdvancedBackups; -import co.uk.mommyheather.advancedbackups.interfaces.IClientContactor; -import co.uk.mommyheather.advancedbackups.network.NetworkHandler; -import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; -import net.minecraft.entity.player.EntityPlayerMP; - -public class ClientContactor implements IClientContactor { - - @Override - public void backupComplete() { - List players = AdvancedBackups.server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, false, 0, 0); - for (EntityPlayerMP player : players) { - if (!AdvancedBackups.players.contains(player.getGameProfile().getId().toString())) continue; - if (!AdvancedBackups.server.isDedicatedServer() || player.canUseCommand(3, "backup")) { - NetworkHandler.HANDLER.sendTo(packet, player); - } - } - } - - @Override - public void backupFailed() { - List players = AdvancedBackups.server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, false, 0, 0); - for (EntityPlayerMP player : players) { - if (!AdvancedBackups.players.contains(player.getGameProfile().getId().toString())) continue; - if (!AdvancedBackups.server.isDedicatedServer() || player.canUseCommand(3, "backup")) { - NetworkHandler.HANDLER.sendTo(packet, player); - } - } - } - - @Override - public void backupProgress(int progress, int max) { - List players = AdvancedBackups.server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, false, progress, max); - for (EntityPlayerMP player : players) { - if (!AdvancedBackups.players.contains(player.getGameProfile().getId().toString())) continue; - if (!AdvancedBackups.server.isDedicatedServer() || player.canUseCommand(3, "backup")) { - NetworkHandler.HANDLER.sendTo(packet, player); - } - } - } - - @Override - public void backupStarting() { - List players = AdvancedBackups.server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, false, 0, 0); - for (EntityPlayerMP player : players) { - if (!AdvancedBackups.players.contains(player.getGameProfile().getId().toString())) continue; - if (!AdvancedBackups.server.isDedicatedServer() || player.canUseCommand(3, "backup")) { - NetworkHandler.HANDLER.sendTo(packet, player); - } - } - } - - @Override - public void backupCancelled() { - List players = AdvancedBackups.server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(false, false, false, false, true, 0, 0); - for (EntityPlayerMP player : players) { - if (!AdvancedBackups.players.contains(player.getGameProfile().getId().toString())) continue; - if (!AdvancedBackups.server.isDedicatedServer() || player.canUseCommand(3, "backup")) { - NetworkHandler.HANDLER.sendTo(packet, player); - } - } - } - -} +package co.uk.mommyheather.advancedbackups.client; + +import java.util.List; + +import co.uk.mommyheather.advancedbackups.AdvancedBackups; +import co.uk.mommyheather.advancedbackups.interfaces.IClientContactor; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; +import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; +import net.minecraft.entity.player.EntityPlayerMP; + +public class ClientContactor implements IClientContactor { + + @Override + public void backupComplete(boolean all) { + List players = AdvancedBackups.server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, false, 0, 0); + for (EntityPlayerMP player : players) { + if (!AdvancedBackups.players.contains(player.getGameProfile().getId().toString())) continue; + if (!AdvancedBackups.server.isDedicatedServer() || player.canUseCommand(3, "backup") || all) { + NetworkHandler.HANDLER.sendTo(packet, player); + } + } + } + + @Override + public void backupFailed(boolean all) { + List players = AdvancedBackups.server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, false, 0, 0); + for (EntityPlayerMP player : players) { + if (!AdvancedBackups.players.contains(player.getGameProfile().getId().toString())) continue; + if (!AdvancedBackups.server.isDedicatedServer() || player.canUseCommand(3, "backup") || all) { + NetworkHandler.HANDLER.sendTo(packet, player); + } + } + } + + @Override + public void backupProgress(int progress, int max, boolean all) { + List players = AdvancedBackups.server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, false, progress, max); + for (EntityPlayerMP player : players) { + if (!AdvancedBackups.players.contains(player.getGameProfile().getId().toString())) continue; + if (!AdvancedBackups.server.isDedicatedServer() || player.canUseCommand(3, "backup") || all) { + NetworkHandler.HANDLER.sendTo(packet, player); + } + } + } + + @Override + public void backupStarting(boolean all) { + List players = AdvancedBackups.server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, false, 0, 0); + for (EntityPlayerMP player : players) { + if (!AdvancedBackups.players.contains(player.getGameProfile().getId().toString())) continue; + if (!AdvancedBackups.server.isDedicatedServer() || player.canUseCommand(3, "backup") || all) { + NetworkHandler.HANDLER.sendTo(packet, player); + } + } + } + + @Override + public void backupCancelled(boolean all) { + List players = AdvancedBackups.server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, false, false, true, 0, 0); + for (EntityPlayerMP player : players) { + if (!AdvancedBackups.players.contains(player.getGameProfile().getId().toString())) continue; + if (!AdvancedBackups.server.isDedicatedServer() || player.canUseCommand(3, "backup") || all) { + NetworkHandler.HANDLER.sendTo(packet, player); + } + } + } + +} From e73b6d30b722cd38233c6cd09af185891058220d Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Mon, 17 Jun 2024 00:04:52 +0100 Subject: [PATCH 512/580] fix erroneous license marker in mods.toml --- src/main/resources/META-INF/mods.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/META-INF/mods.toml b/src/main/resources/META-INF/mods.toml index 645fa28b..d1adc336 100644 --- a/src/main/resources/META-INF/mods.toml +++ b/src/main/resources/META-INF/mods.toml @@ -9,7 +9,7 @@ modLoader="javafml" #mandatory loaderVersion="[34,)" #mandatory This is typically bumped every Minecraft version by Forge. See our download page for lists of versions. # The license for you mod. This is mandatory metadata and allows for easier comprehension of your redistributive properties. # Review your options at https://choosealicense.com/. All rights reserved is the default copyright stance, and is thus the default here. -license="MIT" +license="BSD 3-Clause" # A URL to refer people to when problems occur with this mod #issueTrackerURL="https://change.me.to.your.issue.tracker.example.invalid/" #optional # A list of mods - how many allowed here is determined by the individual mod loader From 37b7fc28e06948ee6ce72739b68aa0ccd60230eb Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Mon, 17 Jun 2024 00:34:49 +0100 Subject: [PATCH 513/580] support v3.6 changes --- .../advancedbackups/AdvancedBackups.java | 315 +++++++++--------- .../client/ClientContactor.java | 158 ++++----- 2 files changed, 235 insertions(+), 238 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 3fa83351..d3066690 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -1,159 +1,156 @@ -package co.uk.mommyheather.advancedbackups; - - -import java.util.ArrayList; -import java.util.List; -import java.util.function.Consumer; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import co.uk.mommyheather.advancedbackups.client.ClientContactor; -import co.uk.mommyheather.advancedbackups.client.ClientWrapper; -import co.uk.mommyheather.advancedbackups.core.ABCore; -import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; -import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; -import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; -import co.uk.mommyheather.advancedbackups.network.NetworkHandler; -import net.minecraft.entity.player.ServerPlayerEntity; -import net.minecraft.server.MinecraftServer; -import net.minecraft.world.server.ServerWorld; -import net.minecraft.world.storage.FolderName; -import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.event.RegisterCommandsEvent; -import net.minecraftforge.event.TickEvent; -import net.minecraftforge.event.entity.player.PlayerEvent.PlayerLoggedInEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.ModList; -import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; -import net.minecraftforge.fml.event.server.FMLServerStartedEvent; -import net.minecraftforge.fml.event.server.FMLServerStartingEvent; -import net.minecraftforge.fml.event.server.FMLServerStoppingEvent; -import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; -import net.minecraftforge.fml.server.ServerLifecycleHooks; - -@Mod("advancedbackups") -public class AdvancedBackups -{ - - private static final Logger LOGGER = LogManager.getLogger(); - - public static final Consumer infoLogger = LOGGER::info; - public static final Consumer warningLogger = LOGGER::warn; - public static final Consumer errorLogger = LOGGER::error; - - public static final ArrayList players = new ArrayList<>(); - - - public AdvancedBackups() - { - // Register ourselves for server and other game events we are interested in - MinecraftForge.EVENT_BUS.register(this); - - FMLJavaModLoadingContext.get().getModEventBus().addListener(this::clientSetup); - NetworkHandler.register(); - - - ABCore.infoLogger = infoLogger; - ABCore.warningLogger = warningLogger; - ABCore.errorLogger = errorLogger; - } - - @SubscribeEvent - public void onServerStarting(FMLServerStartingEvent event) - { - // Do something when the server starts - ABCore.worldName = event.getServer().getWorldData().getLevelName(); - ABCore.worldDir = event.getServer().getWorldPath(FolderName.ROOT); - - - ABCore.disableSaving = AdvancedBackups::disableSaving; - ABCore.enableSaving = AdvancedBackups::enableSaving; - ABCore.saveOnce = AdvancedBackups::saveOnce; - - - ABCore.resetActivity = AdvancedBackups::resetActivity; - - ABCore.clientContactor = new ClientContactor(); - ABCore.modJar = ModList.get().getModFileById("advancedbackups").getFile().getFilePath().toFile(); - - - ConfigManager.loadOrCreateConfig(); - LOGGER.info("Config loaded!!"); - - } - - public void clientSetup(FMLClientSetupEvent e) { - ClientWrapper.init(e); - } - - @SubscribeEvent - public void onServerStarted(FMLServerStartedEvent event) { - BackupWrapper.checkStartupBackups(); - } - - @SubscribeEvent - public void onServerStopping(FMLServerStoppingEvent event) { - BackupWrapper.checkShutdownBackups(); - } - - @SubscribeEvent - public void onPlayerConneccted(PlayerLoggedInEvent event) { - ABCore.activity = true; - } - - @SubscribeEvent - public void registerCommands(RegisterCommandsEvent event){ - AdvancedBackupsCommand.register(event.getDispatcher()); - } - - @SubscribeEvent - public void onPostTick(TickEvent.ServerTickEvent event) { - if (!event.phase.equals(TickEvent.Phase.END)) return; - BackupTimer.check(); - } - - - - public static final String savesDisabledMessage = "\n\n\n***************************************\nSAVING DISABLED - PREPARING FOR BACKUP!\n***************************************"; - public static final String savesEnabledMessage = "\n\n\n*********************************\nSAVING ENABLED - BACKUP COMPLETE!\n*********************************"; - public static final String saveCompleteMessage = "\n\n\n*************************************\nSAVE COMPLETE - PREPARING FOR BACKUP!\n*************************************"; - - - public static void disableSaving() { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - for (ServerWorld level : server.getAllLevels()) { - if (level != null && !level.noSave) { - level.noSave = true; - } - } - if (ConfigManager.silent.get()) return; - warningLogger.accept(savesDisabledMessage); - } - - public static void enableSaving() { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - for (ServerWorld level : server.getAllLevels()) { - if (level != null && level.noSave) { - level.noSave = false; - } - } - if (ConfigManager.silent.get()) return; - warningLogger.accept(savesEnabledMessage); - } - - public static void saveOnce(boolean flush) { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - server.saveAllChunks(true, flush, true); - if (ConfigManager.silent.get()) return; - warningLogger.accept(saveCompleteMessage); - } - - public static void resetActivity() { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - List players = server.getPlayerList().getPlayers(); - ABCore.setActivity(!players.isEmpty()); - } - -} +package co.uk.mommyheather.advancedbackups; + + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import co.uk.mommyheather.advancedbackups.client.ClientContactor; +import co.uk.mommyheather.advancedbackups.client.ClientWrapper; +import co.uk.mommyheather.advancedbackups.core.ABCore; +import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; +import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; +import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; +import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.server.MinecraftServer; +import net.minecraft.world.server.ServerWorld; +import net.minecraft.world.storage.FolderName; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.RegisterCommandsEvent; +import net.minecraftforge.event.TickEvent; +import net.minecraftforge.event.entity.player.PlayerEvent.PlayerLoggedInEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.ModList; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; +import net.minecraftforge.fml.event.server.FMLServerStartedEvent; +import net.minecraftforge.fml.event.server.FMLServerStartingEvent; +import net.minecraftforge.fml.event.server.FMLServerStoppingEvent; +import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; +import net.minecraftforge.fml.server.ServerLifecycleHooks; + +@Mod("advancedbackups") +public class AdvancedBackups +{ + + private static final Logger LOGGER = LogManager.getLogger(); + + public static final Consumer infoLogger = LOGGER::info; + public static final Consumer warningLogger = LOGGER::warn; + public static final Consumer errorLogger = LOGGER::error; + + public static final ArrayList players = new ArrayList<>(); + + + public AdvancedBackups() + { + // Register ourselves for server and other game events we are interested in + MinecraftForge.EVENT_BUS.register(this); + + FMLJavaModLoadingContext.get().getModEventBus().addListener(this::clientSetup); + NetworkHandler.register(); + + + ABCore.infoLogger = infoLogger; + ABCore.warningLogger = warningLogger; + ABCore.errorLogger = errorLogger; + } + + @SubscribeEvent + public void onServerStarting(FMLServerStartingEvent event) + { + // Do something when the server starts + ABCore.worldName = event.getServer().getWorldData().getLevelName(); + ABCore.worldDir = event.getServer().getWorldPath(FolderName.ROOT); + + + ABCore.disableSaving = AdvancedBackups::disableSaving; + ABCore.enableSaving = AdvancedBackups::enableSaving; + ABCore.saveOnce = AdvancedBackups::saveOnce; + + + ABCore.resetActivity = AdvancedBackups::resetActivity; + + ABCore.clientContactor = new ClientContactor(); + ABCore.modJar = ModList.get().getModFileById("advancedbackups").getFile().getFilePath().toFile(); + + + ConfigManager.loadOrCreateConfig(); + LOGGER.info("Config loaded!!"); + + } + + public void clientSetup(FMLClientSetupEvent e) { + ClientWrapper.init(e); + } + + @SubscribeEvent + public void onServerStarted(FMLServerStartedEvent event) { + BackupWrapper.checkStartupBackups(); + } + + @SubscribeEvent + public void onServerStopping(FMLServerStoppingEvent event) { + BackupWrapper.checkShutdownBackups(); + } + + @SubscribeEvent + public void onPlayerConneccted(PlayerLoggedInEvent event) { + ABCore.activity = true; + } + + @SubscribeEvent + public void registerCommands(RegisterCommandsEvent event){ + AdvancedBackupsCommand.register(event.getDispatcher()); + } + + @SubscribeEvent + public void onPostTick(TickEvent.ServerTickEvent event) { + if (!event.phase.equals(TickEvent.Phase.END)) return; + BackupTimer.check(); + } + + + + public static final String savesDisabledMessage = "\n\n\n***************************************\nSAVING DISABLED - PREPARING FOR BACKUP!\n***************************************"; + public static final String savesEnabledMessage = "\n\n\n*********************************\nSAVING ENABLED - BACKUP COMPLETE!\n*********************************"; + public static final String saveCompleteMessage = "\n\n\n*************************************\nSAVE COMPLETE - PREPARING FOR BACKUP!\n*************************************"; + + + public static void disableSaving() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + for (ServerWorld level : server.getAllLevels()) { + if (level != null && !level.noSave) { + level.noSave = true; + } + } + warningLogger.accept(savesDisabledMessage); + } + + public static void enableSaving() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + for (ServerWorld level : server.getAllLevels()) { + if (level != null && level.noSave) { + level.noSave = false; + } + } + warningLogger.accept(savesEnabledMessage); + } + + public static void saveOnce(boolean flush) { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + server.saveAllChunks(true, flush, true); + warningLogger.accept(saveCompleteMessage); + } + + public static void resetActivity() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + ABCore.setActivity(!players.isEmpty()); + } + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java index df18d1e4..e0453848 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java @@ -1,79 +1,79 @@ -package co.uk.mommyheather.advancedbackups.client; - -import java.util.List; - -import co.uk.mommyheather.advancedbackups.AdvancedBackups; -import co.uk.mommyheather.advancedbackups.interfaces.IClientContactor; -import co.uk.mommyheather.advancedbackups.network.NetworkHandler; -import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; -import net.minecraft.entity.player.ServerPlayerEntity; -import net.minecraft.server.MinecraftServer; -import net.minecraftforge.fml.server.ServerLifecycleHooks; - -public class ClientContactor implements IClientContactor { - - @Override - public void backupComplete() { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - List players = server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, false, 0, 0); - for (ServerPlayerEntity player : players) { - if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; - if (!server.isDedicatedServer() || player.hasPermissions(3)) { - NetworkHandler.sendToClient(player, packet); - } - } - } - - @Override - public void backupFailed() { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - List players = server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, false, 0, 0); - for (ServerPlayerEntity player : players) { - if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; - if (!server.isDedicatedServer() || player.hasPermissions(3)) { - NetworkHandler.sendToClient(player, packet); - } - } - } - - @Override - public void backupProgress(int progress, int max) { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - List players = server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, false, progress, max); - for (ServerPlayerEntity player : players) { - if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; - if (!server.isDedicatedServer() || player.hasPermissions(3)) { - NetworkHandler.sendToClient(player, packet); - } - } - } - - @Override - public void backupStarting() { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - List players = server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, false, 0, 0); - for (ServerPlayerEntity player : players) { - if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; - if (!server.isDedicatedServer() || player.hasPermissions(3)) { - NetworkHandler.sendToClient(player, packet); - } - } - } - - @Override - public void backupCancelled() { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - List players = server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(false, false, false, false, true, 0, 0); - for (ServerPlayerEntity player : players) { - if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; - if (!server.isDedicatedServer() || player.hasPermissions(3)) { - NetworkHandler.sendToClient(player, packet); - } - } - } -} +package co.uk.mommyheather.advancedbackups.client; + +import java.util.List; + +import co.uk.mommyheather.advancedbackups.AdvancedBackups; +import co.uk.mommyheather.advancedbackups.interfaces.IClientContactor; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; +import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; +import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.server.MinecraftServer; +import net.minecraftforge.fml.server.ServerLifecycleHooks; + +public class ClientContactor implements IClientContactor { + + @Override + public void backupComplete(boolean all) { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, false, 0, 0); + for (ServerPlayerEntity player : players) { + if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; + if (!server.isDedicatedServer() || player.hasPermissions(3) || all) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupFailed(boolean all) { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, false, 0, 0); + for (ServerPlayerEntity player : players) { + if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; + if (!server.isDedicatedServer() || player.hasPermissions(3) || all) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupProgress(int progress, int max, boolean all) { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, false, progress, max); + for (ServerPlayerEntity player : players) { + if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; + if (!server.isDedicatedServer() || player.hasPermissions(3) || all) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupStarting(boolean all) { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, false, 0, 0); + for (ServerPlayerEntity player : players) { + if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; + if (!server.isDedicatedServer() || player.hasPermissions(3) || all) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupCancelled(boolean all) { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, false, false, true, 0, 0); + for (ServerPlayerEntity player : players) { + if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; + if (!server.isDedicatedServer() || player.hasPermissions(3) || all) { + NetworkHandler.sendToClient(player, packet); + } + } + } +} From e1d5d1249f76a003e486a036b5c024943254b5a3 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Mon, 17 Jun 2024 08:59:07 +0100 Subject: [PATCH 514/580] support v3.6 core --- .../advancedbackups/AdvancedBackups.java | 307 +++++++++--------- .../client/ClientContactor.java | 156 ++++----- 2 files changed, 230 insertions(+), 233 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 5b157202..fa711cc5 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -1,155 +1,152 @@ -package co.uk.mommyheather.advancedbackups; - -import java.io.File; -import java.util.ArrayList; -import java.util.List; -import java.util.function.Consumer; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import co.uk.mommyheather.advancedbackups.client.ClientContactor; -import co.uk.mommyheather.advancedbackups.core.ABCore; -import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; -import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; -import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; -import co.uk.mommyheather.advancedbackups.network.NetworkHandler; -import co.uk.mommyheather.advancedbackups.network.PacketToastSubscribe; -import net.fabricmc.api.ModInitializer; -import net.fabricmc.fabric.api.command.v1.CommandRegistrationCallback; -import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; -import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; -import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; -import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; -import net.fabricmc.loader.impl.FabricLoaderImpl; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.server.world.ServerWorld; -import net.minecraft.util.WorldSavePath; - -public class AdvancedBackups implements ModInitializer { - // This logger is used to write text to the console and the log file. - // It is considered best practice to use your mod id as the logger's name. - // That way, it's clear which mod wrote info, warnings, and errors. - - public static final Logger LOGGER = LoggerFactory.getLogger("advanced-backups"); - - public static final Consumer infoLogger = LOGGER::info; - public static final Consumer warningLogger = LOGGER::warn; - public static final Consumer errorLogger = LOGGER::error; - - public static MinecraftServer server; - - public static final ArrayList players = new ArrayList<>(); - - @Override - public void onInitialize() { - - - ServerLifecycleEvents.SERVER_STARTING.register((server) -> { - AdvancedBackups.server = server; - ABCore.worldName = server.getSaveProperties().getLevelName(); - ABCore.worldDir = server.getSavePath(WorldSavePath.ROOT); - - ABCore.disableSaving = AdvancedBackups::disableSaving; - ABCore.enableSaving = AdvancedBackups::enableSaving; - ABCore.saveOnce = AdvancedBackups::saveOnce; - - ABCore.infoLogger = infoLogger; - ABCore.warningLogger = warningLogger; - ABCore.errorLogger = errorLogger; - - ABCore.resetActivity = AdvancedBackups::resetActivity; - - ABCore.clientContactor = new ClientContactor(); - - ABCore.modJar = new File(FabricLoaderImpl.INSTANCE.getModContainer("advancedbackups").get().getOrigin().getPaths().get(0).toAbsolutePath().toString()); - - - ConfigManager.loadOrCreateConfig(); - LOGGER.info("Config loaded!!"); - }); - - ServerLifecycleEvents.SERVER_STARTED.register((server) -> { - BackupWrapper.checkStartupBackups(); - }); - ServerLifecycleEvents.SERVER_STOPPING.register((server) -> { - BackupWrapper.checkShutdownBackups(); - }); - - ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> { - ABCore.setActivity(true); - }); - - CommandRegistrationCallback.EVENT.register((dispatcher, isDedicated) -> { - AdvancedBackupsCommand.register(dispatcher); - }); - - - ServerTickEvents.END_SERVER_TICK.register((server) -> { - BackupTimer.check(); - }); - - - ServerPlayNetworking.registerGlobalReceiver(NetworkHandler.TOAST_SUBSCRIBE_ID, PacketToastSubscribe::handle); - - - } - - public static final String savesDisabledMessage = """ - - - *************************************** - SAVING DISABLED - PREPARING FOR BACKUP! - *************************************** - """; - public static final String savesEnabledMessage = """ - - - ********************************* - SAVING ENABLED - BACKUP COMPLETE! - ********************************* - """; - public static final String saveCompleteMessage = """ - - - ************************************* - SAVE COMPLETE - PREPARING FOR BACKUP! - ************************************* - """; - - - public static void disableSaving() { - MinecraftServer server = AdvancedBackups.server; - for (ServerWorld level : server.getWorlds()) { - if (level != null && !level.savingDisabled) { - level.savingDisabled = true; - } - } - if (ConfigManager.silent.get()) return; - warningLogger.accept(savesDisabledMessage); - } - - public static void enableSaving() { - MinecraftServer server = AdvancedBackups.server; - for (ServerWorld level : server.getWorlds()) { - if (level != null && level.savingDisabled) { - level.savingDisabled = false; - } - } - if (ConfigManager.silent.get()) return; - warningLogger.accept(savesEnabledMessage); - } - - public static void saveOnce(boolean flush) { - MinecraftServer server = AdvancedBackups.server; - server.saveAll(true, flush, true); - if (ConfigManager.silent.get()) return; - warningLogger.accept(saveCompleteMessage); - } - - public static void resetActivity() { - List players = server.getPlayerManager().getPlayerList(); - ABCore.setActivity(!players.isEmpty()); - } -} +package co.uk.mommyheather.advancedbackups; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import co.uk.mommyheather.advancedbackups.client.ClientContactor; +import co.uk.mommyheather.advancedbackups.core.ABCore; +import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; +import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; +import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; +import co.uk.mommyheather.advancedbackups.network.PacketToastSubscribe; +import net.fabricmc.api.ModInitializer; +import net.fabricmc.fabric.api.command.v1.CommandRegistrationCallback; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; +import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; +import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; +import net.fabricmc.loader.impl.FabricLoaderImpl; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.WorldSavePath; + +public class AdvancedBackups implements ModInitializer { + // This logger is used to write text to the console and the log file. + // It is considered best practice to use your mod id as the logger's name. + // That way, it's clear which mod wrote info, warnings, and errors. + + public static final Logger LOGGER = LoggerFactory.getLogger("advanced-backups"); + + public static final Consumer infoLogger = LOGGER::info; + public static final Consumer warningLogger = LOGGER::warn; + public static final Consumer errorLogger = LOGGER::error; + + public static MinecraftServer server; + + public static final ArrayList players = new ArrayList<>(); + + @Override + public void onInitialize() { + + + ServerLifecycleEvents.SERVER_STARTING.register((server) -> { + AdvancedBackups.server = server; + ABCore.worldName = server.getSaveProperties().getLevelName(); + ABCore.worldDir = server.getSavePath(WorldSavePath.ROOT); + + ABCore.disableSaving = AdvancedBackups::disableSaving; + ABCore.enableSaving = AdvancedBackups::enableSaving; + ABCore.saveOnce = AdvancedBackups::saveOnce; + + ABCore.infoLogger = infoLogger; + ABCore.warningLogger = warningLogger; + ABCore.errorLogger = errorLogger; + + ABCore.resetActivity = AdvancedBackups::resetActivity; + + ABCore.clientContactor = new ClientContactor(); + + ABCore.modJar = new File(FabricLoaderImpl.INSTANCE.getModContainer("advancedbackups").get().getOrigin().getPaths().get(0).toAbsolutePath().toString()); + + + ConfigManager.loadOrCreateConfig(); + LOGGER.info("Config loaded!!"); + }); + + ServerLifecycleEvents.SERVER_STARTED.register((server) -> { + BackupWrapper.checkStartupBackups(); + }); + ServerLifecycleEvents.SERVER_STOPPING.register((server) -> { + BackupWrapper.checkShutdownBackups(); + }); + + ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> { + ABCore.setActivity(true); + }); + + CommandRegistrationCallback.EVENT.register((dispatcher, isDedicated) -> { + AdvancedBackupsCommand.register(dispatcher); + }); + + + ServerTickEvents.END_SERVER_TICK.register((server) -> { + BackupTimer.check(); + }); + + + ServerPlayNetworking.registerGlobalReceiver(NetworkHandler.TOAST_SUBSCRIBE_ID, PacketToastSubscribe::handle); + + + } + + public static final String savesDisabledMessage = """ + + + *************************************** + SAVING DISABLED - PREPARING FOR BACKUP! + *************************************** + """; + public static final String savesEnabledMessage = """ + + + ********************************* + SAVING ENABLED - BACKUP COMPLETE! + ********************************* + """; + public static final String saveCompleteMessage = """ + + + ************************************* + SAVE COMPLETE - PREPARING FOR BACKUP! + ************************************* + """; + + + public static void disableSaving() { + MinecraftServer server = AdvancedBackups.server; + for (ServerWorld level : server.getWorlds()) { + if (level != null && !level.savingDisabled) { + level.savingDisabled = true; + } + } + warningLogger.accept(savesDisabledMessage); + } + + public static void enableSaving() { + MinecraftServer server = AdvancedBackups.server; + for (ServerWorld level : server.getWorlds()) { + if (level != null && level.savingDisabled) { + level.savingDisabled = false; + } + } + warningLogger.accept(savesEnabledMessage); + } + + public static void saveOnce(boolean flush) { + MinecraftServer server = AdvancedBackups.server; + server.saveAll(true, flush, true); + warningLogger.accept(saveCompleteMessage); + } + + public static void resetActivity() { + List players = server.getPlayerManager().getPlayerList(); + ABCore.setActivity(!players.isEmpty()); + } +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java index d2072cdd..c4bef66a 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java @@ -1,78 +1,78 @@ -package co.uk.mommyheather.advancedbackups.client; - -import java.util.List; - -import co.uk.mommyheather.advancedbackups.AdvancedBackups; -import co.uk.mommyheather.advancedbackups.interfaces.IClientContactor; -import co.uk.mommyheather.advancedbackups.network.NetworkHandler; -import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.network.ServerPlayerEntity; - -public class ClientContactor implements IClientContactor { - - @Override - public void backupComplete() { - MinecraftServer server = AdvancedBackups.server; - List players = server.getPlayerManager().getPlayerList(); - PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, false, 0, 0); - for (ServerPlayerEntity player : players) { - if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; - if (!server.isDedicated() || player.hasPermissionLevel(3)) { - NetworkHandler.sendToClient(player, packet); - } - } - } - - @Override - public void backupFailed() { - MinecraftServer server = AdvancedBackups.server; - List players = server.getPlayerManager().getPlayerList(); - PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, false, 0, 0); - for (ServerPlayerEntity player : players) { - if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; - if (!server.isDedicated() || player.hasPermissionLevel(3)) { - NetworkHandler.sendToClient(player, packet); - } - } - } - - @Override - public void backupProgress(int progress, int max) { - MinecraftServer server = AdvancedBackups.server; - List players = server.getPlayerManager().getPlayerList(); - PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, false, progress, max); - for (ServerPlayerEntity player : players) { - if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; - if (!server.isDedicated() || player.hasPermissionLevel(3)) { - NetworkHandler.sendToClient(player, packet); - } - } - } - - @Override - public void backupStarting() { - MinecraftServer server = AdvancedBackups.server; - List players = server.getPlayerManager().getPlayerList(); - PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, false, 0, 0); - for (ServerPlayerEntity player : players) { - if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; - if (!server.isDedicated() || player.hasPermissionLevel(3)) { - NetworkHandler.sendToClient(player, packet); - } - } - } - - @Override - public void backupCancelled() { - MinecraftServer server = AdvancedBackups.server; - List players = server.getPlayerManager().getPlayerList(); - PacketBackupStatus packet = new PacketBackupStatus(false, false, false, false, true, 0, 0); - for (ServerPlayerEntity player : players) { - if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; - if (!server.isDedicated() || player.hasPermissionLevel(3)) { - NetworkHandler.sendToClient(player, packet); - } - } - } -} +package co.uk.mommyheather.advancedbackups.client; + +import java.util.List; + +import co.uk.mommyheather.advancedbackups.AdvancedBackups; +import co.uk.mommyheather.advancedbackups.interfaces.IClientContactor; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; +import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.network.ServerPlayerEntity; + +public class ClientContactor implements IClientContactor { + + @Override + public void backupComplete(boolean all) { + MinecraftServer server = AdvancedBackups.server; + List players = server.getPlayerManager().getPlayerList(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, false, 0, 0); + for (ServerPlayerEntity player : players) { + if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; + if (!server.isDedicated() || player.hasPermissionLevel(3) || all) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupFailed(boolean all) { + MinecraftServer server = AdvancedBackups.server; + List players = server.getPlayerManager().getPlayerList(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, false, 0, 0); + for (ServerPlayerEntity player : players) { + if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; + if (!server.isDedicated() || player.hasPermissionLevel(3) || all) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupProgress(int progress, int max, boolean all) { + MinecraftServer server = AdvancedBackups.server; + List players = server.getPlayerManager().getPlayerList(); + PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, false, progress, max); + for (ServerPlayerEntity player : players) { + if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; + if (!server.isDedicated() || player.hasPermissionLevel(3) || all) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupStarting(boolean all) { + MinecraftServer server = AdvancedBackups.server; + List players = server.getPlayerManager().getPlayerList(); + PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, false, 0, 0); + for (ServerPlayerEntity player : players) { + if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; + if (!server.isDedicated() || player.hasPermissionLevel(3) || all) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupCancelled(boolean all) { + MinecraftServer server = AdvancedBackups.server; + List players = server.getPlayerManager().getPlayerList(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, false, false, true, 0, 0); + for (ServerPlayerEntity player : players) { + if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; + if (!server.isDedicated() || player.hasPermissionLevel(3) || all) { + NetworkHandler.sendToClient(player, packet); + } + } + } +} From ceb8d48d3b1d1ead299c18752e9b469ef931eb0f Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Mon, 17 Jun 2024 09:27:50 +0100 Subject: [PATCH 515/580] support for 3.6 core --- .../advancedbackups/AdvancedBackups.java | 349 +++++++++--------- .../client/ClientContactor.java | 158 ++++---- 2 files changed, 252 insertions(+), 255 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 1a90235a..793f1543 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -1,176 +1,173 @@ -package co.uk.mommyheather.advancedbackups; - -import java.util.ArrayList; -import java.util.List; -import java.util.function.Consumer; - -import org.slf4j.Logger; - -import com.mojang.logging.LogUtils; - -import co.uk.mommyheather.advancedbackups.client.ClientContactor; -import co.uk.mommyheather.advancedbackups.client.ClientWrapper; -import co.uk.mommyheather.advancedbackups.core.ABCore; -import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; -import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; -import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; -import co.uk.mommyheather.advancedbackups.network.NetworkHandler; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.level.storage.LevelResource; -import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.event.RegisterCommandsEvent; -import net.minecraftforge.event.TickEvent; -import net.minecraftforge.event.entity.player.PlayerEvent; -import net.minecraftforge.event.server.ServerStartedEvent; -import net.minecraftforge.event.server.ServerStartingEvent; -import net.minecraftforge.event.server.ServerStoppingEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.ModList; -import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; -import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; -import net.minecraftforge.server.ServerLifecycleHooks; - -@Mod("advancedbackups") -public class AdvancedBackups -{ - - private static final Logger LOGGER = LogUtils.getLogger(); - - public static final Consumer infoLogger = LOGGER::info; - public static final Consumer warningLogger = LOGGER::warn; - public static final Consumer errorLogger = LOGGER::error; - - public static final ArrayList players = new ArrayList<>(); - - - public AdvancedBackups() - { - // Register ourselves for server and other game events we are interested in - MinecraftForge.EVENT_BUS.register(this); - FMLJavaModLoadingContext.get().getModEventBus().addListener(this::clientSetup); - NetworkHandler.register(); - ABCore.infoLogger = infoLogger; - ABCore.warningLogger = warningLogger; - ABCore.errorLogger = errorLogger; - } - - @SubscribeEvent - public void onServerStarting(ServerStartingEvent event) - { - // Do something when the server starts - ABCore.worldName = event.getServer().getWorldData().getLevelName(); - ABCore.worldDir = event.getServer().getWorldPath(LevelResource.ROOT); - - - ABCore.disableSaving = AdvancedBackups::disableSaving; - ABCore.enableSaving = AdvancedBackups::enableSaving; - ABCore.saveOnce = AdvancedBackups::saveOnce; - - - ABCore.resetActivity = AdvancedBackups::resetActivity; - - ABCore.clientContactor = new ClientContactor(); - - ABCore.modJar = ModList.get().getModFileById("advancedbackups").getFile().getFilePath().toFile(); - - - ConfigManager.loadOrCreateConfig(); - LOGGER.info("Config loaded!!"); - - - } - - public void clientSetup(FMLClientSetupEvent e) { - ClientWrapper.init(e); - } - - @SubscribeEvent - public void onServerStarted(ServerStartedEvent event) { - BackupWrapper.checkStartupBackups(); - } - - @SubscribeEvent - public void onServerStopping(ServerStoppingEvent event) { - BackupWrapper.checkShutdownBackups(); - } - - - @SubscribeEvent - public void onPlayerJoined(PlayerEvent.PlayerLoggedInEvent event) { - ABCore.setActivity(true); - } - - @SubscribeEvent - public void registerCommands(RegisterCommandsEvent event){ - AdvancedBackupsCommand.register(event.getDispatcher()); - } - - @SubscribeEvent - public void onTickEnd(TickEvent.ServerTickEvent event) { - if (!event.phase.equals(TickEvent.Phase.END)) return; - BackupTimer.check(); - } - - - public static final String savesDisabledMessage = """ - - -*************************************** -SAVING DISABLED - PREPARING FOR BACKUP! -*************************************** -"""; - public static final String savesEnabledMessage = """ - - -********************************* -SAVING ENABLED - BACKUP COMPLETE! -********************************* -"""; - public static final String saveCompleteMessage = """ - - -************************************* -SAVE COMPLETE - PREPARING FOR BACKUP! -************************************* -"""; - - - public static void disableSaving() { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - for (ServerLevel level : server.getAllLevels()) { - if (level != null && !level.noSave) { - level.noSave = true; - } - } - if (ConfigManager.silent.get()) return; - warningLogger.accept(savesDisabledMessage); - } - - public static void enableSaving() { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - for (ServerLevel level : server.getAllLevels()) { - if (level != null && level.noSave) { - level.noSave = false; - } - } - if (ConfigManager.silent.get()) return; - warningLogger.accept(savesEnabledMessage); - } - - public static void saveOnce(Boolean flush) { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - server.saveEverything(true, flush, true); - if (ConfigManager.silent.get()) return; - warningLogger.accept(saveCompleteMessage); - } - - public static void resetActivity() { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - List players = server.getPlayerList().getPlayers(); - ABCore.setActivity(!players.isEmpty()); - } - -} +package co.uk.mommyheather.advancedbackups; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; + +import org.slf4j.Logger; + +import com.mojang.logging.LogUtils; + +import co.uk.mommyheather.advancedbackups.client.ClientContactor; +import co.uk.mommyheather.advancedbackups.client.ClientWrapper; +import co.uk.mommyheather.advancedbackups.core.ABCore; +import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; +import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; +import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.level.storage.LevelResource; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.RegisterCommandsEvent; +import net.minecraftforge.event.TickEvent; +import net.minecraftforge.event.entity.player.PlayerEvent; +import net.minecraftforge.event.server.ServerStartedEvent; +import net.minecraftforge.event.server.ServerStartingEvent; +import net.minecraftforge.event.server.ServerStoppingEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.ModList; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; +import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; +import net.minecraftforge.server.ServerLifecycleHooks; + +@Mod("advancedbackups") +public class AdvancedBackups +{ + + private static final Logger LOGGER = LogUtils.getLogger(); + + public static final Consumer infoLogger = LOGGER::info; + public static final Consumer warningLogger = LOGGER::warn; + public static final Consumer errorLogger = LOGGER::error; + + public static final ArrayList players = new ArrayList<>(); + + + public AdvancedBackups() + { + // Register ourselves for server and other game events we are interested in + MinecraftForge.EVENT_BUS.register(this); + FMLJavaModLoadingContext.get().getModEventBus().addListener(this::clientSetup); + NetworkHandler.register(); + ABCore.infoLogger = infoLogger; + ABCore.warningLogger = warningLogger; + ABCore.errorLogger = errorLogger; + } + + @SubscribeEvent + public void onServerStarting(ServerStartingEvent event) + { + // Do something when the server starts + ABCore.worldName = event.getServer().getWorldData().getLevelName(); + ABCore.worldDir = event.getServer().getWorldPath(LevelResource.ROOT); + + + ABCore.disableSaving = AdvancedBackups::disableSaving; + ABCore.enableSaving = AdvancedBackups::enableSaving; + ABCore.saveOnce = AdvancedBackups::saveOnce; + + + ABCore.resetActivity = AdvancedBackups::resetActivity; + + ABCore.clientContactor = new ClientContactor(); + + ABCore.modJar = ModList.get().getModFileById("advancedbackups").getFile().getFilePath().toFile(); + + + ConfigManager.loadOrCreateConfig(); + LOGGER.info("Config loaded!!"); + + + } + + public void clientSetup(FMLClientSetupEvent e) { + ClientWrapper.init(e); + } + + @SubscribeEvent + public void onServerStarted(ServerStartedEvent event) { + BackupWrapper.checkStartupBackups(); + } + + @SubscribeEvent + public void onServerStopping(ServerStoppingEvent event) { + BackupWrapper.checkShutdownBackups(); + } + + + @SubscribeEvent + public void onPlayerJoined(PlayerEvent.PlayerLoggedInEvent event) { + ABCore.setActivity(true); + } + + @SubscribeEvent + public void registerCommands(RegisterCommandsEvent event){ + AdvancedBackupsCommand.register(event.getDispatcher()); + } + + @SubscribeEvent + public void onTickEnd(TickEvent.ServerTickEvent event) { + if (!event.phase.equals(TickEvent.Phase.END)) return; + BackupTimer.check(); + } + + + public static final String savesDisabledMessage = """ + + +*************************************** +SAVING DISABLED - PREPARING FOR BACKUP! +*************************************** +"""; + public static final String savesEnabledMessage = """ + + +********************************* +SAVING ENABLED - BACKUP COMPLETE! +********************************* +"""; + public static final String saveCompleteMessage = """ + + +************************************* +SAVE COMPLETE - PREPARING FOR BACKUP! +************************************* +"""; + + + public static void disableSaving() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + for (ServerLevel level : server.getAllLevels()) { + if (level != null && !level.noSave) { + level.noSave = true; + } + } + warningLogger.accept(savesDisabledMessage); + } + + public static void enableSaving() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + for (ServerLevel level : server.getAllLevels()) { + if (level != null && level.noSave) { + level.noSave = false; + } + } + warningLogger.accept(savesEnabledMessage); + } + + public static void saveOnce(Boolean flush) { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + server.saveEverything(true, flush, true); + warningLogger.accept(saveCompleteMessage); + } + + public static void resetActivity() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + ABCore.setActivity(!players.isEmpty()); + } + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java index 3c25b3e7..54ca8bc7 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java @@ -1,79 +1,79 @@ -package co.uk.mommyheather.advancedbackups.client; - -import java.util.List; - -import co.uk.mommyheather.advancedbackups.AdvancedBackups; -import co.uk.mommyheather.advancedbackups.interfaces.IClientContactor; -import co.uk.mommyheather.advancedbackups.network.NetworkHandler; -import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ServerPlayer; -import net.minecraftforge.server.ServerLifecycleHooks; - -public class ClientContactor implements IClientContactor { - - @Override - public void backupComplete() { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - List players = server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, false, 0, 0); - for (ServerPlayer player : players) { - if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; - if (!server.isDedicatedServer() || player.hasPermissions(3)) { - NetworkHandler.sendToClient(player, packet); - } - } - } - - @Override - public void backupFailed() { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - List players = server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, false, 0, 0); - for (ServerPlayer player : players) { - if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; - if (!server.isDedicatedServer() || player.hasPermissions(3)) { - NetworkHandler.sendToClient(player, packet); - } - } - } - - @Override - public void backupProgress(int progress, int max) { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - List players = server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, false, progress, max); - for (ServerPlayer player : players) { - if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; - if (!server.isDedicatedServer() || player.hasPermissions(3)) { - NetworkHandler.sendToClient(player, packet); - } - } - } - - @Override - public void backupStarting() { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - List players = server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, false, 0, 0); - for (ServerPlayer player : players) { - if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; - if (!server.isDedicatedServer() || player.hasPermissions(3)) { - NetworkHandler.sendToClient(player, packet); - } - } - } - - @Override - public void backupCancelled() { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - List players = server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(false, false, false, false, true, 0, 0); - for (ServerPlayer player : players) { - if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; - if (!server.isDedicatedServer() || player.hasPermissions(3)) { - NetworkHandler.sendToClient(player, packet); - } - } - } -} +package co.uk.mommyheather.advancedbackups.client; + +import java.util.List; + +import co.uk.mommyheather.advancedbackups.AdvancedBackups; +import co.uk.mommyheather.advancedbackups.interfaces.IClientContactor; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; +import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerPlayer; +import net.minecraftforge.server.ServerLifecycleHooks; + +public class ClientContactor implements IClientContactor { + + @Override + public void backupComplete(boolean all) { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, false, 0, 0); + for (ServerPlayer player : players) { + if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; + if (!server.isDedicatedServer() || player.hasPermissions(3) || all) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupFailed(boolean all) { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, false, 0, 0); + for (ServerPlayer player : players) { + if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; + if (!server.isDedicatedServer() || player.hasPermissions(3) || all) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupProgress(int progress, int max, boolean all) { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, false, progress, max); + for (ServerPlayer player : players) { + if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; + if (!server.isDedicatedServer() || player.hasPermissions(3) || all) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupStarting(boolean all) { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, false, 0, 0); + for (ServerPlayer player : players) { + if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; + if (!server.isDedicatedServer() || player.hasPermissions(3) || all) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupCancelled(boolean all) { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, false, false, true, 0, 0); + for (ServerPlayer player : players) { + if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; + if (!server.isDedicatedServer() || player.hasPermissions(3) || all) { + NetworkHandler.sendToClient(player, packet); + } + } + } +} From db8e8b2bc1f60ca195d2ec0c14c2761f032a3112 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Mon, 17 Jun 2024 09:50:20 +0100 Subject: [PATCH 516/580] support 3.6 core changes --- .../advancedbackups/AdvancedBackups.java | 303 +++++++++--------- .../client/ClientContactor.java | 156 ++++----- 2 files changed, 228 insertions(+), 231 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index ca750b99..e5122e61 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -1,153 +1,150 @@ -package co.uk.mommyheather.advancedbackups; - -import java.io.File; -import java.util.ArrayList; -import java.util.List; -import java.util.function.Consumer; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import co.uk.mommyheather.advancedbackups.client.ClientContactor; -import co.uk.mommyheather.advancedbackups.core.ABCore; -import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; -import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; -import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; -import co.uk.mommyheather.advancedbackups.network.NetworkHandler; -import co.uk.mommyheather.advancedbackups.network.PacketToastSubscribe; -import net.fabricmc.api.ModInitializer; -import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; -import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; -import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; -import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; -import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; -import net.fabricmc.loader.impl.FabricLoaderImpl; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.server.world.ServerWorld; -import net.minecraft.util.WorldSavePath; - -public class AdvancedBackups implements ModInitializer { - // This logger is used to write text to the console and the log file. - // It is considered best practice to use your mod id as the logger's name. - // That way, it's clear which mod wrote info, warnings, and errors. - - public static final Logger LOGGER = LoggerFactory.getLogger("advanced-backups"); - - public static final Consumer infoLogger = LOGGER::info; - public static final Consumer warningLogger = LOGGER::warn; - public static final Consumer errorLogger = LOGGER::error; - - public static final ArrayList players = new ArrayList<>(); - - public static MinecraftServer server; - - @Override - public void onInitialize() { - - ServerLifecycleEvents.SERVER_STARTING.register((server) -> { - AdvancedBackups.server = server; - ABCore.worldName = server.getSaveProperties().getLevelName(); - ABCore.worldDir = server.getSavePath(WorldSavePath.ROOT); - - ABCore.disableSaving = AdvancedBackups::disableSaving; - ABCore.enableSaving = AdvancedBackups::enableSaving; - ABCore.saveOnce = AdvancedBackups::saveOnce; - - ABCore.infoLogger = infoLogger; - ABCore.warningLogger = warningLogger; - ABCore.errorLogger = errorLogger; - - ABCore.resetActivity = AdvancedBackups::resetActivity; - - ABCore.clientContactor = new ClientContactor(); - ABCore.modJar = new File(FabricLoaderImpl.INSTANCE.getModContainer("advancedbackups").get().getOrigin().getPaths().get(0).toAbsolutePath().toString()); - - - ConfigManager.loadOrCreateConfig(); - LOGGER.info("Config loaded!!"); - }); - - ServerLifecycleEvents.SERVER_STARTED.register((server) -> { - BackupWrapper.checkStartupBackups(); - }); - ServerLifecycleEvents.SERVER_STOPPING.register((server) -> { - BackupWrapper.checkShutdownBackups(); - }); - - ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> { - ABCore.setActivity(true); - }); - - CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> { - AdvancedBackupsCommand.register(dispatcher); - }); - - ServerTickEvents.END_SERVER_TICK.register((server) -> { - BackupTimer.check(); - }); - - - ServerPlayNetworking.registerGlobalReceiver(NetworkHandler.TOAST_SUBSCRIBE_ID, PacketToastSubscribe::handle); - - - - } - - public static final String savesDisabledMessage = """ - - - *************************************** - SAVING DISABLED - PREPARING FOR BACKUP! - *************************************** - """; - public static final String savesEnabledMessage = """ - - - ********************************* - SAVING ENABLED - BACKUP COMPLETE! - ********************************* - """; - public static final String saveCompleteMessage = """ - - - ************************************* - SAVE COMPLETE - PREPARING FOR BACKUP! - ************************************* - """; - - - public static void disableSaving() { - MinecraftServer server = AdvancedBackups.server; - for (ServerWorld level : server.getWorlds()) { - if (level != null && !level.savingDisabled) { - level.savingDisabled = true; - } - } - if (ConfigManager.silent.get()) return; - warningLogger.accept(savesDisabledMessage); - } - - public static void enableSaving() { - MinecraftServer server = AdvancedBackups.server; - for (ServerWorld level : server.getWorlds()) { - if (level != null && level.savingDisabled) { - level.savingDisabled = false; - } - } - if (ConfigManager.silent.get()) return; - warningLogger.accept(savesEnabledMessage); - } - - public static void saveOnce(boolean flush) { - MinecraftServer server = AdvancedBackups.server; - server.saveAll(true, flush, true); - if (ConfigManager.silent.get()) return; - warningLogger.accept(saveCompleteMessage); - } - - public static void resetActivity() { - List players = server.getPlayerManager().getPlayerList(); - ABCore.setActivity(!players.isEmpty()); - } -} +package co.uk.mommyheather.advancedbackups; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import co.uk.mommyheather.advancedbackups.client.ClientContactor; +import co.uk.mommyheather.advancedbackups.core.ABCore; +import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; +import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; +import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; +import co.uk.mommyheather.advancedbackups.network.PacketToastSubscribe; +import net.fabricmc.api.ModInitializer; +import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; +import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; +import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; +import net.fabricmc.loader.impl.FabricLoaderImpl; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.WorldSavePath; + +public class AdvancedBackups implements ModInitializer { + // This logger is used to write text to the console and the log file. + // It is considered best practice to use your mod id as the logger's name. + // That way, it's clear which mod wrote info, warnings, and errors. + + public static final Logger LOGGER = LoggerFactory.getLogger("advanced-backups"); + + public static final Consumer infoLogger = LOGGER::info; + public static final Consumer warningLogger = LOGGER::warn; + public static final Consumer errorLogger = LOGGER::error; + + public static final ArrayList players = new ArrayList<>(); + + public static MinecraftServer server; + + @Override + public void onInitialize() { + + ServerLifecycleEvents.SERVER_STARTING.register((server) -> { + AdvancedBackups.server = server; + ABCore.worldName = server.getSaveProperties().getLevelName(); + ABCore.worldDir = server.getSavePath(WorldSavePath.ROOT); + + ABCore.disableSaving = AdvancedBackups::disableSaving; + ABCore.enableSaving = AdvancedBackups::enableSaving; + ABCore.saveOnce = AdvancedBackups::saveOnce; + + ABCore.infoLogger = infoLogger; + ABCore.warningLogger = warningLogger; + ABCore.errorLogger = errorLogger; + + ABCore.resetActivity = AdvancedBackups::resetActivity; + + ABCore.clientContactor = new ClientContactor(); + ABCore.modJar = new File(FabricLoaderImpl.INSTANCE.getModContainer("advancedbackups").get().getOrigin().getPaths().get(0).toAbsolutePath().toString()); + + + ConfigManager.loadOrCreateConfig(); + LOGGER.info("Config loaded!!"); + }); + + ServerLifecycleEvents.SERVER_STARTED.register((server) -> { + BackupWrapper.checkStartupBackups(); + }); + ServerLifecycleEvents.SERVER_STOPPING.register((server) -> { + BackupWrapper.checkShutdownBackups(); + }); + + ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> { + ABCore.setActivity(true); + }); + + CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> { + AdvancedBackupsCommand.register(dispatcher); + }); + + ServerTickEvents.END_SERVER_TICK.register((server) -> { + BackupTimer.check(); + }); + + + ServerPlayNetworking.registerGlobalReceiver(NetworkHandler.TOAST_SUBSCRIBE_ID, PacketToastSubscribe::handle); + + + + } + + public static final String savesDisabledMessage = """ + + + *************************************** + SAVING DISABLED - PREPARING FOR BACKUP! + *************************************** + """; + public static final String savesEnabledMessage = """ + + + ********************************* + SAVING ENABLED - BACKUP COMPLETE! + ********************************* + """; + public static final String saveCompleteMessage = """ + + + ************************************* + SAVE COMPLETE - PREPARING FOR BACKUP! + ************************************* + """; + + + public static void disableSaving() { + MinecraftServer server = AdvancedBackups.server; + for (ServerWorld level : server.getWorlds()) { + if (level != null && !level.savingDisabled) { + level.savingDisabled = true; + } + } + warningLogger.accept(savesDisabledMessage); + } + + public static void enableSaving() { + MinecraftServer server = AdvancedBackups.server; + for (ServerWorld level : server.getWorlds()) { + if (level != null && level.savingDisabled) { + level.savingDisabled = false; + } + } + warningLogger.accept(savesEnabledMessage); + } + + public static void saveOnce(boolean flush) { + MinecraftServer server = AdvancedBackups.server; + server.saveAll(true, flush, true); + warningLogger.accept(saveCompleteMessage); + } + + public static void resetActivity() { + List players = server.getPlayerManager().getPlayerList(); + ABCore.setActivity(!players.isEmpty()); + } +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java index d2072cdd..c4bef66a 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java @@ -1,78 +1,78 @@ -package co.uk.mommyheather.advancedbackups.client; - -import java.util.List; - -import co.uk.mommyheather.advancedbackups.AdvancedBackups; -import co.uk.mommyheather.advancedbackups.interfaces.IClientContactor; -import co.uk.mommyheather.advancedbackups.network.NetworkHandler; -import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.network.ServerPlayerEntity; - -public class ClientContactor implements IClientContactor { - - @Override - public void backupComplete() { - MinecraftServer server = AdvancedBackups.server; - List players = server.getPlayerManager().getPlayerList(); - PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, false, 0, 0); - for (ServerPlayerEntity player : players) { - if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; - if (!server.isDedicated() || player.hasPermissionLevel(3)) { - NetworkHandler.sendToClient(player, packet); - } - } - } - - @Override - public void backupFailed() { - MinecraftServer server = AdvancedBackups.server; - List players = server.getPlayerManager().getPlayerList(); - PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, false, 0, 0); - for (ServerPlayerEntity player : players) { - if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; - if (!server.isDedicated() || player.hasPermissionLevel(3)) { - NetworkHandler.sendToClient(player, packet); - } - } - } - - @Override - public void backupProgress(int progress, int max) { - MinecraftServer server = AdvancedBackups.server; - List players = server.getPlayerManager().getPlayerList(); - PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, false, progress, max); - for (ServerPlayerEntity player : players) { - if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; - if (!server.isDedicated() || player.hasPermissionLevel(3)) { - NetworkHandler.sendToClient(player, packet); - } - } - } - - @Override - public void backupStarting() { - MinecraftServer server = AdvancedBackups.server; - List players = server.getPlayerManager().getPlayerList(); - PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, false, 0, 0); - for (ServerPlayerEntity player : players) { - if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; - if (!server.isDedicated() || player.hasPermissionLevel(3)) { - NetworkHandler.sendToClient(player, packet); - } - } - } - - @Override - public void backupCancelled() { - MinecraftServer server = AdvancedBackups.server; - List players = server.getPlayerManager().getPlayerList(); - PacketBackupStatus packet = new PacketBackupStatus(false, false, false, false, true, 0, 0); - for (ServerPlayerEntity player : players) { - if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; - if (!server.isDedicated() || player.hasPermissionLevel(3)) { - NetworkHandler.sendToClient(player, packet); - } - } - } -} +package co.uk.mommyheather.advancedbackups.client; + +import java.util.List; + +import co.uk.mommyheather.advancedbackups.AdvancedBackups; +import co.uk.mommyheather.advancedbackups.interfaces.IClientContactor; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; +import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.network.ServerPlayerEntity; + +public class ClientContactor implements IClientContactor { + + @Override + public void backupComplete(boolean all) { + MinecraftServer server = AdvancedBackups.server; + List players = server.getPlayerManager().getPlayerList(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, false, 0, 0); + for (ServerPlayerEntity player : players) { + if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; + if (!server.isDedicated() || player.hasPermissionLevel(3) || all) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupFailed(boolean all) { + MinecraftServer server = AdvancedBackups.server; + List players = server.getPlayerManager().getPlayerList(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, false, 0, 0); + for (ServerPlayerEntity player : players) { + if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; + if (!server.isDedicated() || player.hasPermissionLevel(3) || all) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupProgress(int progress, int max, boolean all) { + MinecraftServer server = AdvancedBackups.server; + List players = server.getPlayerManager().getPlayerList(); + PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, false, progress, max); + for (ServerPlayerEntity player : players) { + if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; + if (!server.isDedicated() || player.hasPermissionLevel(3) || all) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupStarting(boolean all) { + MinecraftServer server = AdvancedBackups.server; + List players = server.getPlayerManager().getPlayerList(); + PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, false, 0, 0); + for (ServerPlayerEntity player : players) { + if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; + if (!server.isDedicated() || player.hasPermissionLevel(3) || all) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupCancelled(boolean all) { + MinecraftServer server = AdvancedBackups.server; + List players = server.getPlayerManager().getPlayerList(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, false, false, true, 0, 0); + for (ServerPlayerEntity player : players) { + if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; + if (!server.isDedicated() || player.hasPermissionLevel(3) || all) { + NetworkHandler.sendToClient(player, packet); + } + } + } +} From 561e708c3bd45ac3c3feccb8b67f1c086d115a50 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 18 Jun 2024 14:33:23 +0100 Subject: [PATCH 517/580] cleanup + 3.6 core support --- .../advancedbackups/AdvancedBackups.java | 349 +++++++++--------- .../client/AdvancedBackupsClientCommand.java | 2 - .../advancedbackups/client/BackupToast.java | 261 +++++++------ .../client/ClientContactor.java | 158 ++++---- 4 files changed, 382 insertions(+), 388 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 1a90235a..793f1543 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -1,176 +1,173 @@ -package co.uk.mommyheather.advancedbackups; - -import java.util.ArrayList; -import java.util.List; -import java.util.function.Consumer; - -import org.slf4j.Logger; - -import com.mojang.logging.LogUtils; - -import co.uk.mommyheather.advancedbackups.client.ClientContactor; -import co.uk.mommyheather.advancedbackups.client.ClientWrapper; -import co.uk.mommyheather.advancedbackups.core.ABCore; -import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; -import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; -import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; -import co.uk.mommyheather.advancedbackups.network.NetworkHandler; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.level.storage.LevelResource; -import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.event.RegisterCommandsEvent; -import net.minecraftforge.event.TickEvent; -import net.minecraftforge.event.entity.player.PlayerEvent; -import net.minecraftforge.event.server.ServerStartedEvent; -import net.minecraftforge.event.server.ServerStartingEvent; -import net.minecraftforge.event.server.ServerStoppingEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.ModList; -import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; -import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; -import net.minecraftforge.server.ServerLifecycleHooks; - -@Mod("advancedbackups") -public class AdvancedBackups -{ - - private static final Logger LOGGER = LogUtils.getLogger(); - - public static final Consumer infoLogger = LOGGER::info; - public static final Consumer warningLogger = LOGGER::warn; - public static final Consumer errorLogger = LOGGER::error; - - public static final ArrayList players = new ArrayList<>(); - - - public AdvancedBackups() - { - // Register ourselves for server and other game events we are interested in - MinecraftForge.EVENT_BUS.register(this); - FMLJavaModLoadingContext.get().getModEventBus().addListener(this::clientSetup); - NetworkHandler.register(); - ABCore.infoLogger = infoLogger; - ABCore.warningLogger = warningLogger; - ABCore.errorLogger = errorLogger; - } - - @SubscribeEvent - public void onServerStarting(ServerStartingEvent event) - { - // Do something when the server starts - ABCore.worldName = event.getServer().getWorldData().getLevelName(); - ABCore.worldDir = event.getServer().getWorldPath(LevelResource.ROOT); - - - ABCore.disableSaving = AdvancedBackups::disableSaving; - ABCore.enableSaving = AdvancedBackups::enableSaving; - ABCore.saveOnce = AdvancedBackups::saveOnce; - - - ABCore.resetActivity = AdvancedBackups::resetActivity; - - ABCore.clientContactor = new ClientContactor(); - - ABCore.modJar = ModList.get().getModFileById("advancedbackups").getFile().getFilePath().toFile(); - - - ConfigManager.loadOrCreateConfig(); - LOGGER.info("Config loaded!!"); - - - } - - public void clientSetup(FMLClientSetupEvent e) { - ClientWrapper.init(e); - } - - @SubscribeEvent - public void onServerStarted(ServerStartedEvent event) { - BackupWrapper.checkStartupBackups(); - } - - @SubscribeEvent - public void onServerStopping(ServerStoppingEvent event) { - BackupWrapper.checkShutdownBackups(); - } - - - @SubscribeEvent - public void onPlayerJoined(PlayerEvent.PlayerLoggedInEvent event) { - ABCore.setActivity(true); - } - - @SubscribeEvent - public void registerCommands(RegisterCommandsEvent event){ - AdvancedBackupsCommand.register(event.getDispatcher()); - } - - @SubscribeEvent - public void onTickEnd(TickEvent.ServerTickEvent event) { - if (!event.phase.equals(TickEvent.Phase.END)) return; - BackupTimer.check(); - } - - - public static final String savesDisabledMessage = """ - - -*************************************** -SAVING DISABLED - PREPARING FOR BACKUP! -*************************************** -"""; - public static final String savesEnabledMessage = """ - - -********************************* -SAVING ENABLED - BACKUP COMPLETE! -********************************* -"""; - public static final String saveCompleteMessage = """ - - -************************************* -SAVE COMPLETE - PREPARING FOR BACKUP! -************************************* -"""; - - - public static void disableSaving() { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - for (ServerLevel level : server.getAllLevels()) { - if (level != null && !level.noSave) { - level.noSave = true; - } - } - if (ConfigManager.silent.get()) return; - warningLogger.accept(savesDisabledMessage); - } - - public static void enableSaving() { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - for (ServerLevel level : server.getAllLevels()) { - if (level != null && level.noSave) { - level.noSave = false; - } - } - if (ConfigManager.silent.get()) return; - warningLogger.accept(savesEnabledMessage); - } - - public static void saveOnce(Boolean flush) { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - server.saveEverything(true, flush, true); - if (ConfigManager.silent.get()) return; - warningLogger.accept(saveCompleteMessage); - } - - public static void resetActivity() { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - List players = server.getPlayerList().getPlayers(); - ABCore.setActivity(!players.isEmpty()); - } - -} +package co.uk.mommyheather.advancedbackups; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; + +import org.slf4j.Logger; + +import com.mojang.logging.LogUtils; + +import co.uk.mommyheather.advancedbackups.client.ClientContactor; +import co.uk.mommyheather.advancedbackups.client.ClientWrapper; +import co.uk.mommyheather.advancedbackups.core.ABCore; +import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; +import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; +import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.level.storage.LevelResource; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.RegisterCommandsEvent; +import net.minecraftforge.event.TickEvent; +import net.minecraftforge.event.entity.player.PlayerEvent; +import net.minecraftforge.event.server.ServerStartedEvent; +import net.minecraftforge.event.server.ServerStartingEvent; +import net.minecraftforge.event.server.ServerStoppingEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.ModList; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; +import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; +import net.minecraftforge.server.ServerLifecycleHooks; + +@Mod("advancedbackups") +public class AdvancedBackups +{ + + private static final Logger LOGGER = LogUtils.getLogger(); + + public static final Consumer infoLogger = LOGGER::info; + public static final Consumer warningLogger = LOGGER::warn; + public static final Consumer errorLogger = LOGGER::error; + + public static final ArrayList players = new ArrayList<>(); + + + public AdvancedBackups() + { + // Register ourselves for server and other game events we are interested in + MinecraftForge.EVENT_BUS.register(this); + FMLJavaModLoadingContext.get().getModEventBus().addListener(this::clientSetup); + NetworkHandler.register(); + ABCore.infoLogger = infoLogger; + ABCore.warningLogger = warningLogger; + ABCore.errorLogger = errorLogger; + } + + @SubscribeEvent + public void onServerStarting(ServerStartingEvent event) + { + // Do something when the server starts + ABCore.worldName = event.getServer().getWorldData().getLevelName(); + ABCore.worldDir = event.getServer().getWorldPath(LevelResource.ROOT); + + + ABCore.disableSaving = AdvancedBackups::disableSaving; + ABCore.enableSaving = AdvancedBackups::enableSaving; + ABCore.saveOnce = AdvancedBackups::saveOnce; + + + ABCore.resetActivity = AdvancedBackups::resetActivity; + + ABCore.clientContactor = new ClientContactor(); + + ABCore.modJar = ModList.get().getModFileById("advancedbackups").getFile().getFilePath().toFile(); + + + ConfigManager.loadOrCreateConfig(); + LOGGER.info("Config loaded!!"); + + + } + + public void clientSetup(FMLClientSetupEvent e) { + ClientWrapper.init(e); + } + + @SubscribeEvent + public void onServerStarted(ServerStartedEvent event) { + BackupWrapper.checkStartupBackups(); + } + + @SubscribeEvent + public void onServerStopping(ServerStoppingEvent event) { + BackupWrapper.checkShutdownBackups(); + } + + + @SubscribeEvent + public void onPlayerJoined(PlayerEvent.PlayerLoggedInEvent event) { + ABCore.setActivity(true); + } + + @SubscribeEvent + public void registerCommands(RegisterCommandsEvent event){ + AdvancedBackupsCommand.register(event.getDispatcher()); + } + + @SubscribeEvent + public void onTickEnd(TickEvent.ServerTickEvent event) { + if (!event.phase.equals(TickEvent.Phase.END)) return; + BackupTimer.check(); + } + + + public static final String savesDisabledMessage = """ + + +*************************************** +SAVING DISABLED - PREPARING FOR BACKUP! +*************************************** +"""; + public static final String savesEnabledMessage = """ + + +********************************* +SAVING ENABLED - BACKUP COMPLETE! +********************************* +"""; + public static final String saveCompleteMessage = """ + + +************************************* +SAVE COMPLETE - PREPARING FOR BACKUP! +************************************* +"""; + + + public static void disableSaving() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + for (ServerLevel level : server.getAllLevels()) { + if (level != null && !level.noSave) { + level.noSave = true; + } + } + warningLogger.accept(savesDisabledMessage); + } + + public static void enableSaving() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + for (ServerLevel level : server.getAllLevels()) { + if (level != null && level.noSave) { + level.noSave = false; + } + } + warningLogger.accept(savesEnabledMessage); + } + + public static void saveOnce(Boolean flush) { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + server.saveEverything(true, flush, true); + warningLogger.accept(saveCompleteMessage); + } + + public static void resetActivity() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + ABCore.setActivity(!players.isEmpty()); + } + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java index d78418af..9e57671d 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/AdvancedBackupsClientCommand.java @@ -11,8 +11,6 @@ import net.minecraft.commands.arguments.ArgumentSignatures; import net.minecraft.network.chat.Component; import net.minecraft.network.protocol.game.ServerboundChatCommandPacket; -import net.minecraftforge.client.ClientCommandSourceStack; -import net.minecraftforge.server.ServerLifecycleHooks; public class AdvancedBackupsClientCommand { public static void register(CommandDispatcher commandDispatcher) { diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java index e4a485f2..7bf36bcd 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java @@ -1,131 +1,130 @@ -package co.uk.mommyheather.advancedbackups.client; - -import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.blaze3d.vertex.PoseStack; - -import co.uk.mommyheather.advancedbackups.core.config.ClientConfigManager; -import net.minecraft.ChatFormatting; -import net.minecraft.client.gui.Gui; -import net.minecraft.client.gui.components.toasts.Toast; -import net.minecraft.client.gui.components.toasts.ToastComponent; -import net.minecraft.client.renderer.GameRenderer; -import net.minecraft.client.resources.language.I18n; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Items; - -public class BackupToast implements Toast { - - public static boolean starting; - public static boolean started; - public static boolean failed; - public static boolean finished; - public static boolean cancelled; - - public static int progress; - public static int max; - - public static boolean exists = false; - - private static long time; - private static boolean timeSet = false; - - public static final ItemStack stack = new ItemStack(Items.PAPER); - - private int textColour; - private String title = "You shouldn't see this!"; - - - @Override - public Visibility render(PoseStack matrix, ToastComponent toastGui, long delta) { - RenderSystem.setShader(GameRenderer::getPositionTexShader); - RenderSystem.setShaderTexture(0, TEXTURE); - RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); - toastGui.blit(matrix, 0, 0, 0, ClientConfigManager.darkMode.get() ? 0 : this.height(), this.width(), this.height()); - toastGui.getMinecraft().getItemRenderer().renderGuiItem(stack, 8, 8); - - float percent = finished ? 100 : (float) progress / (float) max; - - Gui.fill(matrix, 4, 28, 156, 29, ColourHelper.colour - (255, (int) ClientConfigManager.progressBackgroundRed.get(), (int) ClientConfigManager.progressBackgroundGreen.get(), (int) ClientConfigManager.progressBackgroundBlue.get())); - - float f = Math.min(156, ( - 156 * percent - )); - - if (!exists) { - if (title.equals(I18n.get("advancedbackups.backup_finished"))){ - textColour = ColourHelper.colour(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); - toastGui.getMinecraft().font.draw(matrix, I18n.get(title), 25, 11, textColour); - Gui.fill(matrix, 3, 28, 156, 29, ColourHelper.colour - (255, (int) ClientConfigManager.progressBarRed.get(), (int) ClientConfigManager.progressBarGreen.get(), (int) ClientConfigManager.progressBarBlue.get())); - } - else { - textColour = ColourHelper.colour(255, (int) ClientConfigManager.errorTextRed.get(), (int) ClientConfigManager.errorTextGreen.get(), (int) ClientConfigManager.errorTextBlue.get()); - toastGui.getMinecraft().font.draw(matrix, I18n.get(title), 25, 11, textColour); - } - return Visibility.HIDE; - } - - title = "You shouldn't see this!"; - - - if (starting) { - textColour = ColourHelper.colour(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); - title = I18n.get("advancedbackups.backup_starting"); - } - else if (started) { - textColour = ColourHelper.colour(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); - title = I18n.get("advancedbackups.progress", round(percent * 100)); - } - else if (failed) { - textColour = ColourHelper.colour(255, (int) ClientConfigManager.errorTextRed.get(), (int) ClientConfigManager.errorTextGreen.get(), (int) ClientConfigManager.errorTextBlue.get()); - title = I18n.get("advancedbackups.backup_failed"); - if (!timeSet) { - time = System.currentTimeMillis(); - timeSet = true; - } - } - else if (finished) { - textColour = ColourHelper.colour(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); - title = I18n.get("advancedbackups.backup_finished"); - if (!timeSet) { - time = System.currentTimeMillis(); - timeSet = true; - } - } - else if (cancelled) { - textColour = ColourHelper.colour(255, (int) ClientConfigManager.errorTextRed.get(), (int) ClientConfigManager.errorTextGreen.get(), (int) ClientConfigManager.errorTextBlue.get()); - title = I18n.get("advancedbackups.backup_cancelled"); - if (!timeSet) { - time = System.currentTimeMillis(); - timeSet = true; - } - } - - toastGui.getMinecraft().font.draw(matrix, title, 25, 11, textColour); - - if (timeSet && System.currentTimeMillis() >= time + 5000) { - starting = false; - started = false; - failed = false; - finished = false; - progress = 0; - max = 0; - timeSet = false; - exists = false; - return Visibility.HIDE; - } - - Gui.fill(matrix, 4, 28, Math.max(4, (int) f), 29, ColourHelper.colour - (255, (int) ClientConfigManager.progressBarRed.get(), (int) ClientConfigManager.progressBarGreen.get(), (int) ClientConfigManager.progressBarBlue.get())); - - return Visibility.SHOW; - - } - - - private static String round (float value) { - return String.format("%.1f", value); - } - -} +package co.uk.mommyheather.advancedbackups.client; + +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.PoseStack; + +import co.uk.mommyheather.advancedbackups.core.config.ClientConfigManager; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.gui.components.toasts.Toast; +import net.minecraft.client.gui.components.toasts.ToastComponent; +import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.client.resources.language.I18n; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; + +public class BackupToast implements Toast { + + public static boolean starting; + public static boolean started; + public static boolean failed; + public static boolean finished; + public static boolean cancelled; + + public static int progress; + public static int max; + + public static boolean exists = false; + + private static long time; + private static boolean timeSet = false; + + public static final ItemStack stack = new ItemStack(Items.PAPER); + + private int textColour; + private String title = "You shouldn't see this!"; + + + @Override + public Visibility render(PoseStack matrix, ToastComponent toastGui, long delta) { + RenderSystem.setShader(GameRenderer::getPositionTexShader); + RenderSystem.setShaderTexture(0, TEXTURE); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + toastGui.blit(matrix, 0, 0, 0, ClientConfigManager.darkMode.get() ? 0 : this.height(), this.width(), this.height()); + toastGui.getMinecraft().getItemRenderer().renderGuiItem(stack, 8, 8); + + float percent = finished ? 100 : (float) progress / (float) max; + + Gui.fill(matrix, 4, 28, 156, 29, ColourHelper.colour + (255, (int) ClientConfigManager.progressBackgroundRed.get(), (int) ClientConfigManager.progressBackgroundGreen.get(), (int) ClientConfigManager.progressBackgroundBlue.get())); + + float f = Math.min(156, ( + 156 * percent + )); + + if (!exists) { + if (title.equals(I18n.get("advancedbackups.backup_finished"))){ + textColour = ColourHelper.colour(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); + toastGui.getMinecraft().font.draw(matrix, I18n.get(title), 25, 11, textColour); + Gui.fill(matrix, 3, 28, 156, 29, ColourHelper.colour + (255, (int) ClientConfigManager.progressBarRed.get(), (int) ClientConfigManager.progressBarGreen.get(), (int) ClientConfigManager.progressBarBlue.get())); + } + else { + textColour = ColourHelper.colour(255, (int) ClientConfigManager.errorTextRed.get(), (int) ClientConfigManager.errorTextGreen.get(), (int) ClientConfigManager.errorTextBlue.get()); + toastGui.getMinecraft().font.draw(matrix, I18n.get(title), 25, 11, textColour); + } + return Visibility.HIDE; + } + + title = "You shouldn't see this!"; + + + if (starting) { + textColour = ColourHelper.colour(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); + title = I18n.get("advancedbackups.backup_starting"); + } + else if (started) { + textColour = ColourHelper.colour(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); + title = I18n.get("advancedbackups.progress", round(percent * 100)); + } + else if (failed) { + textColour = ColourHelper.colour(255, (int) ClientConfigManager.errorTextRed.get(), (int) ClientConfigManager.errorTextGreen.get(), (int) ClientConfigManager.errorTextBlue.get()); + title = I18n.get("advancedbackups.backup_failed"); + if (!timeSet) { + time = System.currentTimeMillis(); + timeSet = true; + } + } + else if (finished) { + textColour = ColourHelper.colour(255, (int) ClientConfigManager.progressTextRed.get(), (int) ClientConfigManager.progressTextGreen.get(), (int) ClientConfigManager.progressTextBlue.get()); + title = I18n.get("advancedbackups.backup_finished"); + if (!timeSet) { + time = System.currentTimeMillis(); + timeSet = true; + } + } + else if (cancelled) { + textColour = ColourHelper.colour(255, (int) ClientConfigManager.errorTextRed.get(), (int) ClientConfigManager.errorTextGreen.get(), (int) ClientConfigManager.errorTextBlue.get()); + title = I18n.get("advancedbackups.backup_cancelled"); + if (!timeSet) { + time = System.currentTimeMillis(); + timeSet = true; + } + } + + toastGui.getMinecraft().font.draw(matrix, title, 25, 11, textColour); + + if (timeSet && System.currentTimeMillis() >= time + 5000) { + starting = false; + started = false; + failed = false; + finished = false; + progress = 0; + max = 0; + timeSet = false; + exists = false; + return Visibility.HIDE; + } + + Gui.fill(matrix, 4, 28, Math.max(4, (int) f), 29, ColourHelper.colour + (255, (int) ClientConfigManager.progressBarRed.get(), (int) ClientConfigManager.progressBarGreen.get(), (int) ClientConfigManager.progressBarBlue.get())); + + return Visibility.SHOW; + + } + + + private static String round (float value) { + return String.format("%.1f", value); + } + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java index 3c25b3e7..54ca8bc7 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java @@ -1,79 +1,79 @@ -package co.uk.mommyheather.advancedbackups.client; - -import java.util.List; - -import co.uk.mommyheather.advancedbackups.AdvancedBackups; -import co.uk.mommyheather.advancedbackups.interfaces.IClientContactor; -import co.uk.mommyheather.advancedbackups.network.NetworkHandler; -import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ServerPlayer; -import net.minecraftforge.server.ServerLifecycleHooks; - -public class ClientContactor implements IClientContactor { - - @Override - public void backupComplete() { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - List players = server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, false, 0, 0); - for (ServerPlayer player : players) { - if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; - if (!server.isDedicatedServer() || player.hasPermissions(3)) { - NetworkHandler.sendToClient(player, packet); - } - } - } - - @Override - public void backupFailed() { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - List players = server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, false, 0, 0); - for (ServerPlayer player : players) { - if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; - if (!server.isDedicatedServer() || player.hasPermissions(3)) { - NetworkHandler.sendToClient(player, packet); - } - } - } - - @Override - public void backupProgress(int progress, int max) { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - List players = server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, false, progress, max); - for (ServerPlayer player : players) { - if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; - if (!server.isDedicatedServer() || player.hasPermissions(3)) { - NetworkHandler.sendToClient(player, packet); - } - } - } - - @Override - public void backupStarting() { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - List players = server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, false, 0, 0); - for (ServerPlayer player : players) { - if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; - if (!server.isDedicatedServer() || player.hasPermissions(3)) { - NetworkHandler.sendToClient(player, packet); - } - } - } - - @Override - public void backupCancelled() { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - List players = server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(false, false, false, false, true, 0, 0); - for (ServerPlayer player : players) { - if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; - if (!server.isDedicatedServer() || player.hasPermissions(3)) { - NetworkHandler.sendToClient(player, packet); - } - } - } -} +package co.uk.mommyheather.advancedbackups.client; + +import java.util.List; + +import co.uk.mommyheather.advancedbackups.AdvancedBackups; +import co.uk.mommyheather.advancedbackups.interfaces.IClientContactor; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; +import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerPlayer; +import net.minecraftforge.server.ServerLifecycleHooks; + +public class ClientContactor implements IClientContactor { + + @Override + public void backupComplete(boolean all) { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, false, 0, 0); + for (ServerPlayer player : players) { + if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; + if (!server.isDedicatedServer() || player.hasPermissions(3) || all) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupFailed(boolean all) { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, false, 0, 0); + for (ServerPlayer player : players) { + if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; + if (!server.isDedicatedServer() || player.hasPermissions(3) || all) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupProgress(int progress, int max, boolean all) { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, false, progress, max); + for (ServerPlayer player : players) { + if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; + if (!server.isDedicatedServer() || player.hasPermissions(3) || all) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupStarting(boolean all) { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, false, 0, 0); + for (ServerPlayer player : players) { + if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; + if (!server.isDedicatedServer() || player.hasPermissions(3) || all) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupCancelled(boolean all) { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, false, false, true, 0, 0); + for (ServerPlayer player : players) { + if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; + if (!server.isDedicatedServer() || player.hasPermissions(3) || all) { + NetworkHandler.sendToClient(player, packet); + } + } + } +} From 1ea440ee7accce67e2e635b011a8d64f9ddb532e Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 18 Jun 2024 17:06:07 +0100 Subject: [PATCH 518/580] 3.6 core support --- .../advancedbackups/AdvancedBackups.java | 303 +++++++++--------- .../client/ClientContactor.java | 156 ++++----- 2 files changed, 228 insertions(+), 231 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index ca750b99..e5122e61 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -1,153 +1,150 @@ -package co.uk.mommyheather.advancedbackups; - -import java.io.File; -import java.util.ArrayList; -import java.util.List; -import java.util.function.Consumer; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import co.uk.mommyheather.advancedbackups.client.ClientContactor; -import co.uk.mommyheather.advancedbackups.core.ABCore; -import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; -import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; -import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; -import co.uk.mommyheather.advancedbackups.network.NetworkHandler; -import co.uk.mommyheather.advancedbackups.network.PacketToastSubscribe; -import net.fabricmc.api.ModInitializer; -import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; -import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; -import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; -import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; -import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; -import net.fabricmc.loader.impl.FabricLoaderImpl; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.server.world.ServerWorld; -import net.minecraft.util.WorldSavePath; - -public class AdvancedBackups implements ModInitializer { - // This logger is used to write text to the console and the log file. - // It is considered best practice to use your mod id as the logger's name. - // That way, it's clear which mod wrote info, warnings, and errors. - - public static final Logger LOGGER = LoggerFactory.getLogger("advanced-backups"); - - public static final Consumer infoLogger = LOGGER::info; - public static final Consumer warningLogger = LOGGER::warn; - public static final Consumer errorLogger = LOGGER::error; - - public static final ArrayList players = new ArrayList<>(); - - public static MinecraftServer server; - - @Override - public void onInitialize() { - - ServerLifecycleEvents.SERVER_STARTING.register((server) -> { - AdvancedBackups.server = server; - ABCore.worldName = server.getSaveProperties().getLevelName(); - ABCore.worldDir = server.getSavePath(WorldSavePath.ROOT); - - ABCore.disableSaving = AdvancedBackups::disableSaving; - ABCore.enableSaving = AdvancedBackups::enableSaving; - ABCore.saveOnce = AdvancedBackups::saveOnce; - - ABCore.infoLogger = infoLogger; - ABCore.warningLogger = warningLogger; - ABCore.errorLogger = errorLogger; - - ABCore.resetActivity = AdvancedBackups::resetActivity; - - ABCore.clientContactor = new ClientContactor(); - ABCore.modJar = new File(FabricLoaderImpl.INSTANCE.getModContainer("advancedbackups").get().getOrigin().getPaths().get(0).toAbsolutePath().toString()); - - - ConfigManager.loadOrCreateConfig(); - LOGGER.info("Config loaded!!"); - }); - - ServerLifecycleEvents.SERVER_STARTED.register((server) -> { - BackupWrapper.checkStartupBackups(); - }); - ServerLifecycleEvents.SERVER_STOPPING.register((server) -> { - BackupWrapper.checkShutdownBackups(); - }); - - ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> { - ABCore.setActivity(true); - }); - - CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> { - AdvancedBackupsCommand.register(dispatcher); - }); - - ServerTickEvents.END_SERVER_TICK.register((server) -> { - BackupTimer.check(); - }); - - - ServerPlayNetworking.registerGlobalReceiver(NetworkHandler.TOAST_SUBSCRIBE_ID, PacketToastSubscribe::handle); - - - - } - - public static final String savesDisabledMessage = """ - - - *************************************** - SAVING DISABLED - PREPARING FOR BACKUP! - *************************************** - """; - public static final String savesEnabledMessage = """ - - - ********************************* - SAVING ENABLED - BACKUP COMPLETE! - ********************************* - """; - public static final String saveCompleteMessage = """ - - - ************************************* - SAVE COMPLETE - PREPARING FOR BACKUP! - ************************************* - """; - - - public static void disableSaving() { - MinecraftServer server = AdvancedBackups.server; - for (ServerWorld level : server.getWorlds()) { - if (level != null && !level.savingDisabled) { - level.savingDisabled = true; - } - } - if (ConfigManager.silent.get()) return; - warningLogger.accept(savesDisabledMessage); - } - - public static void enableSaving() { - MinecraftServer server = AdvancedBackups.server; - for (ServerWorld level : server.getWorlds()) { - if (level != null && level.savingDisabled) { - level.savingDisabled = false; - } - } - if (ConfigManager.silent.get()) return; - warningLogger.accept(savesEnabledMessage); - } - - public static void saveOnce(boolean flush) { - MinecraftServer server = AdvancedBackups.server; - server.saveAll(true, flush, true); - if (ConfigManager.silent.get()) return; - warningLogger.accept(saveCompleteMessage); - } - - public static void resetActivity() { - List players = server.getPlayerManager().getPlayerList(); - ABCore.setActivity(!players.isEmpty()); - } -} +package co.uk.mommyheather.advancedbackups; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import co.uk.mommyheather.advancedbackups.client.ClientContactor; +import co.uk.mommyheather.advancedbackups.core.ABCore; +import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; +import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; +import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; +import co.uk.mommyheather.advancedbackups.network.PacketToastSubscribe; +import net.fabricmc.api.ModInitializer; +import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; +import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; +import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; +import net.fabricmc.loader.impl.FabricLoaderImpl; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.WorldSavePath; + +public class AdvancedBackups implements ModInitializer { + // This logger is used to write text to the console and the log file. + // It is considered best practice to use your mod id as the logger's name. + // That way, it's clear which mod wrote info, warnings, and errors. + + public static final Logger LOGGER = LoggerFactory.getLogger("advanced-backups"); + + public static final Consumer infoLogger = LOGGER::info; + public static final Consumer warningLogger = LOGGER::warn; + public static final Consumer errorLogger = LOGGER::error; + + public static final ArrayList players = new ArrayList<>(); + + public static MinecraftServer server; + + @Override + public void onInitialize() { + + ServerLifecycleEvents.SERVER_STARTING.register((server) -> { + AdvancedBackups.server = server; + ABCore.worldName = server.getSaveProperties().getLevelName(); + ABCore.worldDir = server.getSavePath(WorldSavePath.ROOT); + + ABCore.disableSaving = AdvancedBackups::disableSaving; + ABCore.enableSaving = AdvancedBackups::enableSaving; + ABCore.saveOnce = AdvancedBackups::saveOnce; + + ABCore.infoLogger = infoLogger; + ABCore.warningLogger = warningLogger; + ABCore.errorLogger = errorLogger; + + ABCore.resetActivity = AdvancedBackups::resetActivity; + + ABCore.clientContactor = new ClientContactor(); + ABCore.modJar = new File(FabricLoaderImpl.INSTANCE.getModContainer("advancedbackups").get().getOrigin().getPaths().get(0).toAbsolutePath().toString()); + + + ConfigManager.loadOrCreateConfig(); + LOGGER.info("Config loaded!!"); + }); + + ServerLifecycleEvents.SERVER_STARTED.register((server) -> { + BackupWrapper.checkStartupBackups(); + }); + ServerLifecycleEvents.SERVER_STOPPING.register((server) -> { + BackupWrapper.checkShutdownBackups(); + }); + + ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> { + ABCore.setActivity(true); + }); + + CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> { + AdvancedBackupsCommand.register(dispatcher); + }); + + ServerTickEvents.END_SERVER_TICK.register((server) -> { + BackupTimer.check(); + }); + + + ServerPlayNetworking.registerGlobalReceiver(NetworkHandler.TOAST_SUBSCRIBE_ID, PacketToastSubscribe::handle); + + + + } + + public static final String savesDisabledMessage = """ + + + *************************************** + SAVING DISABLED - PREPARING FOR BACKUP! + *************************************** + """; + public static final String savesEnabledMessage = """ + + + ********************************* + SAVING ENABLED - BACKUP COMPLETE! + ********************************* + """; + public static final String saveCompleteMessage = """ + + + ************************************* + SAVE COMPLETE - PREPARING FOR BACKUP! + ************************************* + """; + + + public static void disableSaving() { + MinecraftServer server = AdvancedBackups.server; + for (ServerWorld level : server.getWorlds()) { + if (level != null && !level.savingDisabled) { + level.savingDisabled = true; + } + } + warningLogger.accept(savesDisabledMessage); + } + + public static void enableSaving() { + MinecraftServer server = AdvancedBackups.server; + for (ServerWorld level : server.getWorlds()) { + if (level != null && level.savingDisabled) { + level.savingDisabled = false; + } + } + warningLogger.accept(savesEnabledMessage); + } + + public static void saveOnce(boolean flush) { + MinecraftServer server = AdvancedBackups.server; + server.saveAll(true, flush, true); + warningLogger.accept(saveCompleteMessage); + } + + public static void resetActivity() { + List players = server.getPlayerManager().getPlayerList(); + ABCore.setActivity(!players.isEmpty()); + } +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java index d2072cdd..c4bef66a 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java @@ -1,78 +1,78 @@ -package co.uk.mommyheather.advancedbackups.client; - -import java.util.List; - -import co.uk.mommyheather.advancedbackups.AdvancedBackups; -import co.uk.mommyheather.advancedbackups.interfaces.IClientContactor; -import co.uk.mommyheather.advancedbackups.network.NetworkHandler; -import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.network.ServerPlayerEntity; - -public class ClientContactor implements IClientContactor { - - @Override - public void backupComplete() { - MinecraftServer server = AdvancedBackups.server; - List players = server.getPlayerManager().getPlayerList(); - PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, false, 0, 0); - for (ServerPlayerEntity player : players) { - if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; - if (!server.isDedicated() || player.hasPermissionLevel(3)) { - NetworkHandler.sendToClient(player, packet); - } - } - } - - @Override - public void backupFailed() { - MinecraftServer server = AdvancedBackups.server; - List players = server.getPlayerManager().getPlayerList(); - PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, false, 0, 0); - for (ServerPlayerEntity player : players) { - if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; - if (!server.isDedicated() || player.hasPermissionLevel(3)) { - NetworkHandler.sendToClient(player, packet); - } - } - } - - @Override - public void backupProgress(int progress, int max) { - MinecraftServer server = AdvancedBackups.server; - List players = server.getPlayerManager().getPlayerList(); - PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, false, progress, max); - for (ServerPlayerEntity player : players) { - if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; - if (!server.isDedicated() || player.hasPermissionLevel(3)) { - NetworkHandler.sendToClient(player, packet); - } - } - } - - @Override - public void backupStarting() { - MinecraftServer server = AdvancedBackups.server; - List players = server.getPlayerManager().getPlayerList(); - PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, false, 0, 0); - for (ServerPlayerEntity player : players) { - if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; - if (!server.isDedicated() || player.hasPermissionLevel(3)) { - NetworkHandler.sendToClient(player, packet); - } - } - } - - @Override - public void backupCancelled() { - MinecraftServer server = AdvancedBackups.server; - List players = server.getPlayerManager().getPlayerList(); - PacketBackupStatus packet = new PacketBackupStatus(false, false, false, false, true, 0, 0); - for (ServerPlayerEntity player : players) { - if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; - if (!server.isDedicated() || player.hasPermissionLevel(3)) { - NetworkHandler.sendToClient(player, packet); - } - } - } -} +package co.uk.mommyheather.advancedbackups.client; + +import java.util.List; + +import co.uk.mommyheather.advancedbackups.AdvancedBackups; +import co.uk.mommyheather.advancedbackups.interfaces.IClientContactor; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; +import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.network.ServerPlayerEntity; + +public class ClientContactor implements IClientContactor { + + @Override + public void backupComplete(boolean all) { + MinecraftServer server = AdvancedBackups.server; + List players = server.getPlayerManager().getPlayerList(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, false, 0, 0); + for (ServerPlayerEntity player : players) { + if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; + if (!server.isDedicated() || player.hasPermissionLevel(3) || all) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupFailed(boolean all) { + MinecraftServer server = AdvancedBackups.server; + List players = server.getPlayerManager().getPlayerList(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, false, 0, 0); + for (ServerPlayerEntity player : players) { + if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; + if (!server.isDedicated() || player.hasPermissionLevel(3) || all) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupProgress(int progress, int max, boolean all) { + MinecraftServer server = AdvancedBackups.server; + List players = server.getPlayerManager().getPlayerList(); + PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, false, progress, max); + for (ServerPlayerEntity player : players) { + if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; + if (!server.isDedicated() || player.hasPermissionLevel(3) || all) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupStarting(boolean all) { + MinecraftServer server = AdvancedBackups.server; + List players = server.getPlayerManager().getPlayerList(); + PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, false, 0, 0); + for (ServerPlayerEntity player : players) { + if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; + if (!server.isDedicated() || player.hasPermissionLevel(3) || all) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupCancelled(boolean all) { + MinecraftServer server = AdvancedBackups.server; + List players = server.getPlayerManager().getPlayerList(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, false, false, true, 0, 0); + for (ServerPlayerEntity player : players) { + if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; + if (!server.isDedicated() || player.hasPermissionLevel(3) || all) { + NetworkHandler.sendToClient(player, packet); + } + } + } +} From d57f34a2c8b47e3753880be72cf97108e7d87286 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 18 Jun 2024 17:35:16 +0100 Subject: [PATCH 519/580] 3.6 support --- .../advancedbackups/AdvancedBackups.java | 345 +++++++++--------- .../client/ClientContactor.java | 158 ++++---- 2 files changed, 250 insertions(+), 253 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index ffd65cc8..782be31c 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -1,174 +1,171 @@ -package co.uk.mommyheather.advancedbackups; - -import java.util.ArrayList; -import java.util.List; -import java.util.function.Consumer; - -import org.slf4j.Logger; - -import com.mojang.logging.LogUtils; - -import co.uk.mommyheather.advancedbackups.client.ClientContactor; -import co.uk.mommyheather.advancedbackups.client.ClientWrapper; -import co.uk.mommyheather.advancedbackups.core.ABCore; -import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; -import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; -import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; -import co.uk.mommyheather.advancedbackups.network.NetworkHandler; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.level.storage.LevelResource; -import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.event.RegisterCommandsEvent; -import net.minecraftforge.event.TickEvent; -import net.minecraftforge.event.TickEvent.Phase; -import net.minecraftforge.event.entity.player.PlayerEvent; -import net.minecraftforge.event.server.ServerStartedEvent; -import net.minecraftforge.event.server.ServerStartingEvent; -import net.minecraftforge.event.server.ServerStoppingEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.ModList; -import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; -import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; -import net.minecraftforge.server.ServerLifecycleHooks; - -@Mod("advancedbackups") -public class AdvancedBackups -{ - - private static final Logger LOGGER = LogUtils.getLogger(); - - public static final Consumer infoLogger = LOGGER::info; - public static final Consumer warningLogger = LOGGER::warn; - public static final Consumer errorLogger = LOGGER::error; - - public static final ArrayList players = new ArrayList<>(); - - public AdvancedBackups() - { - // Register ourselves for server and other game events we are interested in - MinecraftForge.EVENT_BUS.register(this); - FMLJavaModLoadingContext.get().getModEventBus().addListener(this::clientSetup); - NetworkHandler.register(); - ABCore.infoLogger = infoLogger; - ABCore.warningLogger = warningLogger; - ABCore.errorLogger = errorLogger; - - } - - public void clientSetup(FMLClientSetupEvent e) { - ClientWrapper.init(e); - } - - @SubscribeEvent - public void onTickEnd(TickEvent.ServerTickEvent event) { - if (event.phase != Phase.END) return; - BackupTimer.check(); - } - - @SubscribeEvent - public void onServerStarting(ServerStartingEvent event) - { - // Do something when the server starts - ABCore.worldName = event.getServer().getWorldData().getLevelName(); - ABCore.worldDir = event.getServer().getWorldPath(LevelResource.ROOT); - - ABCore.disableSaving = AdvancedBackups::disableSaving; - ABCore.enableSaving = AdvancedBackups::enableSaving; - ABCore.saveOnce = AdvancedBackups::saveOnce; - - ABCore.resetActivity = AdvancedBackups::resetActivity; - - ABCore.clientContactor = new ClientContactor(); - ABCore.modJar = ModList.get().getModFileById("advancedbackups").getFile().getFilePath().toFile(); - - - ConfigManager.loadOrCreateConfig(); - LOGGER.info("Config loaded!!"); - - } - - @SubscribeEvent - public void onServerStarted(ServerStartedEvent event) { - BackupWrapper.checkStartupBackups(); - } - - @SubscribeEvent - public void onServerStopping(ServerStoppingEvent event) { - BackupWrapper.checkShutdownBackups(); - } - - - @SubscribeEvent - public void onPlayerJoined(PlayerEvent.PlayerLoggedInEvent event) { - ABCore.setActivity(true); - } - - @SubscribeEvent - public void registerCommands(RegisterCommandsEvent event){ - AdvancedBackupsCommand.register(event.getDispatcher()); - } - - - public static final String savesDisabledMessage = """ - - - *************************************** - SAVING DISABLED - PREPARING FOR BACKUP! - *************************************** - """; - public static final String savesEnabledMessage = """ - - - ********************************* - SAVING ENABLED - BACKUP COMPLETE! - ********************************* - """; - public static final String saveCompleteMessage = """ - - - ************************************* - SAVE COMPLETE - PREPARING FOR BACKUP! - ************************************* - """; - - - public static void disableSaving() { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - for (ServerLevel level : server.getAllLevels()) { - if (level != null && !level.noSave) { - level.noSave = true; - } - } - if (ConfigManager.silent.get()) return; - warningLogger.accept(savesDisabledMessage); - } - - public static void enableSaving() { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - for (ServerLevel level : server.getAllLevels()) { - if (level != null && level.noSave) { - level.noSave = false; - } - } - if (ConfigManager.silent.get()) return; - warningLogger.accept(savesEnabledMessage); - } - - public static void saveOnce(boolean flush) { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - server.saveEverything(true, flush, true); - if (ConfigManager.silent.get()) return; - warningLogger.accept(saveCompleteMessage); - } - - - public static void resetActivity() { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - List players = server.getPlayerList().getPlayers(); - ABCore.setActivity(!players.isEmpty()); - } - -} +package co.uk.mommyheather.advancedbackups; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; + +import org.slf4j.Logger; + +import com.mojang.logging.LogUtils; + +import co.uk.mommyheather.advancedbackups.client.ClientContactor; +import co.uk.mommyheather.advancedbackups.client.ClientWrapper; +import co.uk.mommyheather.advancedbackups.core.ABCore; +import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; +import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; +import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.level.storage.LevelResource; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.RegisterCommandsEvent; +import net.minecraftforge.event.TickEvent; +import net.minecraftforge.event.TickEvent.Phase; +import net.minecraftforge.event.entity.player.PlayerEvent; +import net.minecraftforge.event.server.ServerStartedEvent; +import net.minecraftforge.event.server.ServerStartingEvent; +import net.minecraftforge.event.server.ServerStoppingEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.ModList; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; +import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; +import net.minecraftforge.server.ServerLifecycleHooks; + +@Mod("advancedbackups") +public class AdvancedBackups +{ + + private static final Logger LOGGER = LogUtils.getLogger(); + + public static final Consumer infoLogger = LOGGER::info; + public static final Consumer warningLogger = LOGGER::warn; + public static final Consumer errorLogger = LOGGER::error; + + public static final ArrayList players = new ArrayList<>(); + + public AdvancedBackups() + { + // Register ourselves for server and other game events we are interested in + MinecraftForge.EVENT_BUS.register(this); + FMLJavaModLoadingContext.get().getModEventBus().addListener(this::clientSetup); + NetworkHandler.register(); + ABCore.infoLogger = infoLogger; + ABCore.warningLogger = warningLogger; + ABCore.errorLogger = errorLogger; + + } + + public void clientSetup(FMLClientSetupEvent e) { + ClientWrapper.init(e); + } + + @SubscribeEvent + public void onTickEnd(TickEvent.ServerTickEvent event) { + if (event.phase != Phase.END) return; + BackupTimer.check(); + } + + @SubscribeEvent + public void onServerStarting(ServerStartingEvent event) + { + // Do something when the server starts + ABCore.worldName = event.getServer().getWorldData().getLevelName(); + ABCore.worldDir = event.getServer().getWorldPath(LevelResource.ROOT); + + ABCore.disableSaving = AdvancedBackups::disableSaving; + ABCore.enableSaving = AdvancedBackups::enableSaving; + ABCore.saveOnce = AdvancedBackups::saveOnce; + + ABCore.resetActivity = AdvancedBackups::resetActivity; + + ABCore.clientContactor = new ClientContactor(); + ABCore.modJar = ModList.get().getModFileById("advancedbackups").getFile().getFilePath().toFile(); + + + ConfigManager.loadOrCreateConfig(); + LOGGER.info("Config loaded!!"); + + } + + @SubscribeEvent + public void onServerStarted(ServerStartedEvent event) { + BackupWrapper.checkStartupBackups(); + } + + @SubscribeEvent + public void onServerStopping(ServerStoppingEvent event) { + BackupWrapper.checkShutdownBackups(); + } + + + @SubscribeEvent + public void onPlayerJoined(PlayerEvent.PlayerLoggedInEvent event) { + ABCore.setActivity(true); + } + + @SubscribeEvent + public void registerCommands(RegisterCommandsEvent event){ + AdvancedBackupsCommand.register(event.getDispatcher()); + } + + + public static final String savesDisabledMessage = """ + + + *************************************** + SAVING DISABLED - PREPARING FOR BACKUP! + *************************************** + """; + public static final String savesEnabledMessage = """ + + + ********************************* + SAVING ENABLED - BACKUP COMPLETE! + ********************************* + """; + public static final String saveCompleteMessage = """ + + + ************************************* + SAVE COMPLETE - PREPARING FOR BACKUP! + ************************************* + """; + + + public static void disableSaving() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + for (ServerLevel level : server.getAllLevels()) { + if (level != null && !level.noSave) { + level.noSave = true; + } + } + warningLogger.accept(savesDisabledMessage); + } + + public static void enableSaving() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + for (ServerLevel level : server.getAllLevels()) { + if (level != null && level.noSave) { + level.noSave = false; + } + } + warningLogger.accept(savesEnabledMessage); + } + + public static void saveOnce(boolean flush) { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + server.saveEverything(true, flush, true); + warningLogger.accept(saveCompleteMessage); + } + + + public static void resetActivity() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + ABCore.setActivity(!players.isEmpty()); + } + +} diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java index 3c25b3e7..54ca8bc7 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java @@ -1,79 +1,79 @@ -package co.uk.mommyheather.advancedbackups.client; - -import java.util.List; - -import co.uk.mommyheather.advancedbackups.AdvancedBackups; -import co.uk.mommyheather.advancedbackups.interfaces.IClientContactor; -import co.uk.mommyheather.advancedbackups.network.NetworkHandler; -import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ServerPlayer; -import net.minecraftforge.server.ServerLifecycleHooks; - -public class ClientContactor implements IClientContactor { - - @Override - public void backupComplete() { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - List players = server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, false, 0, 0); - for (ServerPlayer player : players) { - if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; - if (!server.isDedicatedServer() || player.hasPermissions(3)) { - NetworkHandler.sendToClient(player, packet); - } - } - } - - @Override - public void backupFailed() { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - List players = server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, false, 0, 0); - for (ServerPlayer player : players) { - if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; - if (!server.isDedicatedServer() || player.hasPermissions(3)) { - NetworkHandler.sendToClient(player, packet); - } - } - } - - @Override - public void backupProgress(int progress, int max) { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - List players = server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, false, progress, max); - for (ServerPlayer player : players) { - if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; - if (!server.isDedicatedServer() || player.hasPermissions(3)) { - NetworkHandler.sendToClient(player, packet); - } - } - } - - @Override - public void backupStarting() { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - List players = server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, false, 0, 0); - for (ServerPlayer player : players) { - if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; - if (!server.isDedicatedServer() || player.hasPermissions(3)) { - NetworkHandler.sendToClient(player, packet); - } - } - } - - @Override - public void backupCancelled() { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - List players = server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(false, false, false, false, true, 0, 0); - for (ServerPlayer player : players) { - if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; - if (!server.isDedicatedServer() || player.hasPermissions(3)) { - NetworkHandler.sendToClient(player, packet); - } - } - } -} +package co.uk.mommyheather.advancedbackups.client; + +import java.util.List; + +import co.uk.mommyheather.advancedbackups.AdvancedBackups; +import co.uk.mommyheather.advancedbackups.interfaces.IClientContactor; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; +import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerPlayer; +import net.minecraftforge.server.ServerLifecycleHooks; + +public class ClientContactor implements IClientContactor { + + @Override + public void backupComplete(boolean all) { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, false, 0, 0); + for (ServerPlayer player : players) { + if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; + if (!server.isDedicatedServer() || player.hasPermissions(3) || all) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupFailed(boolean all) { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, false, 0, 0); + for (ServerPlayer player : players) { + if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; + if (!server.isDedicatedServer() || player.hasPermissions(3) || all) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupProgress(int progress, int max, boolean all) { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, false, progress, max); + for (ServerPlayer player : players) { + if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; + if (!server.isDedicatedServer() || player.hasPermissions(3) || all) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupStarting(boolean all) { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, false, 0, 0); + for (ServerPlayer player : players) { + if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; + if (!server.isDedicatedServer() || player.hasPermissions(3) || all) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupCancelled(boolean all) { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, false, false, true, 0, 0); + for (ServerPlayer player : players) { + if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; + if (!server.isDedicatedServer() || player.hasPermissions(3) || all) { + NetworkHandler.sendToClient(player, packet); + } + } + } +} From ff91e1a16489be182507b7c56a3129db7e295c9c Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 18 Jun 2024 17:43:35 +0100 Subject: [PATCH 520/580] 3.6 support --- .../advancedbackups/AdvancedBackups.java | 3 --- .../client/ClientContactor.java | 20 +++++++++---------- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 69adbc9f..f61736a5 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -124,7 +124,6 @@ public static void disableSaving() { level.savingDisabled = true; } } - if (ConfigManager.silent.get()) return; warningLogger.accept(savesDisabledMessage); } @@ -135,14 +134,12 @@ public static void enableSaving() { level.savingDisabled = false; } } - if (ConfigManager.silent.get()) return; warningLogger.accept(savesEnabledMessage); } public static void saveOnce(boolean flush) { MinecraftServer server = AdvancedBackups.server; server.saveAll(true, flush, true); - if (ConfigManager.silent.get()) return; warningLogger.accept(saveCompleteMessage); } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java index 770a6deb..c4bef66a 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java @@ -12,65 +12,65 @@ public class ClientContactor implements IClientContactor { @Override - public void backupComplete() { + public void backupComplete(boolean all) { MinecraftServer server = AdvancedBackups.server; List players = server.getPlayerManager().getPlayerList(); PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, false, 0, 0); for (ServerPlayerEntity player : players) { if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; - if (!server.isDedicated() || player.hasPermissionLevel(3)) { + if (!server.isDedicated() || player.hasPermissionLevel(3) || all) { NetworkHandler.sendToClient(player, packet); } } } @Override - public void backupFailed() { + public void backupFailed(boolean all) { MinecraftServer server = AdvancedBackups.server; List players = server.getPlayerManager().getPlayerList(); PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, false, 0, 0); for (ServerPlayerEntity player : players) { if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; - if (!server.isDedicated() || player.hasPermissionLevel(3)) { + if (!server.isDedicated() || player.hasPermissionLevel(3) || all) { NetworkHandler.sendToClient(player, packet); } } } @Override - public void backupProgress(int progress, int max) { + public void backupProgress(int progress, int max, boolean all) { MinecraftServer server = AdvancedBackups.server; List players = server.getPlayerManager().getPlayerList(); PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, false, progress, max); for (ServerPlayerEntity player : players) { if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; - if (!server.isDedicated() || player.hasPermissionLevel(3)) { + if (!server.isDedicated() || player.hasPermissionLevel(3) || all) { NetworkHandler.sendToClient(player, packet); } } } @Override - public void backupStarting() { + public void backupStarting(boolean all) { MinecraftServer server = AdvancedBackups.server; List players = server.getPlayerManager().getPlayerList(); PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, false, 0, 0); for (ServerPlayerEntity player : players) { if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; - if (!server.isDedicated() || player.hasPermissionLevel(3)) { + if (!server.isDedicated() || player.hasPermissionLevel(3) || all) { NetworkHandler.sendToClient(player, packet); } } } @Override - public void backupCancelled() { + public void backupCancelled(boolean all) { MinecraftServer server = AdvancedBackups.server; List players = server.getPlayerManager().getPlayerList(); PacketBackupStatus packet = new PacketBackupStatus(false, false, false, false, true, 0, 0); for (ServerPlayerEntity player : players) { if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; - if (!server.isDedicated() || player.hasPermissionLevel(3)) { + if (!server.isDedicated() || player.hasPermissionLevel(3) || all) { NetworkHandler.sendToClient(player, packet); } } From ea55ad8616e560c31a12a6cfad60f0a7fd4670d9 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 18 Jun 2024 17:53:31 +0100 Subject: [PATCH 521/580] 3.6 support --- .../advancedbackups/AdvancedBackups.java | 3 --- .../client/ClientContactor.java | 20 +++++++++---------- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index a72d4e40..885d3731 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -144,7 +144,6 @@ public static void disableSaving() { level.noSave = true; } } - if (ConfigManager.silent.get()) return; warningLogger.accept(savesDisabledMessage); } @@ -155,14 +154,12 @@ public static void enableSaving() { level.noSave = false; } } - if (ConfigManager.silent.get()) return; warningLogger.accept(savesEnabledMessage); } public static void saveOnce(boolean flush) { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); server.saveEverything(true, flush, true); - if (ConfigManager.silent.get()) return; warningLogger.accept(saveCompleteMessage); } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java index 69fd4eb0..54ca8bc7 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java @@ -13,65 +13,65 @@ public class ClientContactor implements IClientContactor { @Override - public void backupComplete() { + public void backupComplete(boolean all) { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, false, 0, 0); for (ServerPlayer player : players) { if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; - if (!server.isDedicatedServer() || player.hasPermissions(3)) { + if (!server.isDedicatedServer() || player.hasPermissions(3) || all) { NetworkHandler.sendToClient(player, packet); } } } @Override - public void backupFailed() { + public void backupFailed(boolean all) { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, false, 0, 0); for (ServerPlayer player : players) { if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; - if (!server.isDedicatedServer() || player.hasPermissions(3)) { + if (!server.isDedicatedServer() || player.hasPermissions(3) || all) { NetworkHandler.sendToClient(player, packet); } } } @Override - public void backupProgress(int progress, int max) { + public void backupProgress(int progress, int max, boolean all) { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, false, progress, max); for (ServerPlayer player : players) { if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; - if (!server.isDedicatedServer() || player.hasPermissions(3)) { + if (!server.isDedicatedServer() || player.hasPermissions(3) || all) { NetworkHandler.sendToClient(player, packet); } } } @Override - public void backupStarting() { + public void backupStarting(boolean all) { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, false, 0, 0); for (ServerPlayer player : players) { if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; - if (!server.isDedicatedServer() || player.hasPermissions(3)) { + if (!server.isDedicatedServer() || player.hasPermissions(3) || all) { NetworkHandler.sendToClient(player, packet); } } } @Override - public void backupCancelled() { + public void backupCancelled(boolean all) { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(false, false, false, false, true, 0, 0); for (ServerPlayer player : players) { if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; - if (!server.isDedicatedServer() || player.hasPermissions(3)) { + if (!server.isDedicatedServer() || player.hasPermissions(3) || all) { NetworkHandler.sendToClient(player, packet); } } From bc6c5068d118b6ef71944cc20814c52db84ccc11 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 18 Jun 2024 18:19:10 +0100 Subject: [PATCH 522/580] 3.6 support --- .../advancedbackups/AdvancedBackups.java | 3 --- .../client/ClientContactor.java | 20 +++++++++---------- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 792dbbcc..71e99634 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -144,7 +144,6 @@ public static void disableSaving() { level.noSave = true; } } - if (ConfigManager.silent.get()) return; warningLogger.accept(savesDisabledMessage); } @@ -155,14 +154,12 @@ public static void enableSaving() { level.noSave = false; } } - if (ConfigManager.silent.get()) return; warningLogger.accept(savesEnabledMessage); } public static void saveOnce(boolean flush) { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); server.saveEverything(true, flush, true); - if (ConfigManager.silent.get()) return; warningLogger.accept(saveCompleteMessage); } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java index c8bd4203..3f8426fc 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java @@ -13,65 +13,65 @@ public class ClientContactor implements IClientContactor { @Override - public void backupComplete() { + public void backupComplete(boolean all) { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, false, 0, 0); for (ServerPlayer player : players) { if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; - if (!server.isDedicatedServer() || player.hasPermissions(3)) { + if (!server.isDedicatedServer() || player.hasPermissions(3) || all) { NetworkHandler.sendToClient(player, packet); } } } @Override - public void backupFailed() { + public void backupFailed(boolean all) { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, false, 0, 0); for (ServerPlayer player : players) { if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; - if (!server.isDedicatedServer() || player.hasPermissions(3)) { + if (!server.isDedicatedServer() || player.hasPermissions(3) || all) { NetworkHandler.sendToClient(player, packet); } } } @Override - public void backupProgress(int progress, int max) { + public void backupProgress(int progress, int max, boolean all) { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, false, progress, max); for (ServerPlayer player : players) { if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; - if (!server.isDedicatedServer() || player.hasPermissions(3)) { + if (!server.isDedicatedServer() || player.hasPermissions(3) || all) { NetworkHandler.sendToClient(player, packet); } } } @Override - public void backupStarting() { + public void backupStarting(boolean all) { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, false, 0, 0); for (ServerPlayer player : players) { if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; - if (!server.isDedicatedServer() || player.hasPermissions(3)) { + if (!server.isDedicatedServer() || player.hasPermissions(3) || all) { NetworkHandler.sendToClient(player, packet); } } } @Override - public void backupCancelled() { + public void backupCancelled(boolean all) { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(false, false, false, false, true, 0, 0); for (ServerPlayer player : players) { if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; - if (!server.isDedicatedServer() || player.hasPermissions(3)) { + if (!server.isDedicatedServer() || player.hasPermissions(3) || all) { NetworkHandler.sendToClient(player, packet); } } From 66089e9659898955c81e0557b170d38f5e55d50b Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 18 Jun 2024 18:22:34 +0100 Subject: [PATCH 523/580] 3.6 support --- .../advancedbackups/AdvancedBackups.java | 3 --- .../client/ClientContactor.java | 20 +++++++++---------- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 7ea91c3b..fc81dc44 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -145,7 +145,6 @@ public static void disableSaving() { level.noSave = true; } } - if (ConfigManager.silent.get()) return; warningLogger.accept(savesDisabledMessage); } @@ -156,14 +155,12 @@ public static void enableSaving() { level.noSave = false; } } - if (ConfigManager.silent.get()) return; warningLogger.accept(savesEnabledMessage); } public static void saveOnce(boolean flush) { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); server.saveEverything(true, flush, true); - if (ConfigManager.silent.get()) return; warningLogger.accept(saveCompleteMessage); } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java index c8bd4203..3f8426fc 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java @@ -13,65 +13,65 @@ public class ClientContactor implements IClientContactor { @Override - public void backupComplete() { + public void backupComplete(boolean all) { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, false, 0, 0); for (ServerPlayer player : players) { if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; - if (!server.isDedicatedServer() || player.hasPermissions(3)) { + if (!server.isDedicatedServer() || player.hasPermissions(3) || all) { NetworkHandler.sendToClient(player, packet); } } } @Override - public void backupFailed() { + public void backupFailed(boolean all) { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, false, 0, 0); for (ServerPlayer player : players) { if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; - if (!server.isDedicatedServer() || player.hasPermissions(3)) { + if (!server.isDedicatedServer() || player.hasPermissions(3) || all) { NetworkHandler.sendToClient(player, packet); } } } @Override - public void backupProgress(int progress, int max) { + public void backupProgress(int progress, int max, boolean all) { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, false, progress, max); for (ServerPlayer player : players) { if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; - if (!server.isDedicatedServer() || player.hasPermissions(3)) { + if (!server.isDedicatedServer() || player.hasPermissions(3) || all) { NetworkHandler.sendToClient(player, packet); } } } @Override - public void backupStarting() { + public void backupStarting(boolean all) { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, false, 0, 0); for (ServerPlayer player : players) { if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; - if (!server.isDedicatedServer() || player.hasPermissions(3)) { + if (!server.isDedicatedServer() || player.hasPermissions(3) || all) { NetworkHandler.sendToClient(player, packet); } } } @Override - public void backupCancelled() { + public void backupCancelled(boolean all) { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(false, false, false, false, true, 0, 0); for (ServerPlayer player : players) { if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; - if (!server.isDedicatedServer() || player.hasPermissions(3)) { + if (!server.isDedicatedServer() || player.hasPermissions(3) || all) { NetworkHandler.sendToClient(player, packet); } } From 7f537cf9ecd5a0f52ca76d8efedd4759e3306aa1 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 18 Jun 2024 18:26:52 +0100 Subject: [PATCH 524/580] 3.6 core support --- .../advancedbackups/AdvancedBackups.java | 3 --- .../client/ClientContactor.java | 20 +++++++++---------- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 6a40ebab..8de6741d 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -127,7 +127,6 @@ public static void disableSaving() { level.savingDisabled = true; } } - if (ConfigManager.silent.get()) return; warningLogger.accept(savesDisabledMessage); } @@ -138,14 +137,12 @@ public static void enableSaving() { level.savingDisabled = false; } } - if (ConfigManager.silent.get()) return; warningLogger.accept(savesEnabledMessage); } public static void saveOnce(boolean flush) { MinecraftServer server = AdvancedBackups.server; server.saveAll(true, flush, true); - if (ConfigManager.silent.get()) return; warningLogger.accept(saveCompleteMessage); } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java index 770a6deb..c4bef66a 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java @@ -12,65 +12,65 @@ public class ClientContactor implements IClientContactor { @Override - public void backupComplete() { + public void backupComplete(boolean all) { MinecraftServer server = AdvancedBackups.server; List players = server.getPlayerManager().getPlayerList(); PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, false, 0, 0); for (ServerPlayerEntity player : players) { if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; - if (!server.isDedicated() || player.hasPermissionLevel(3)) { + if (!server.isDedicated() || player.hasPermissionLevel(3) || all) { NetworkHandler.sendToClient(player, packet); } } } @Override - public void backupFailed() { + public void backupFailed(boolean all) { MinecraftServer server = AdvancedBackups.server; List players = server.getPlayerManager().getPlayerList(); PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, false, 0, 0); for (ServerPlayerEntity player : players) { if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; - if (!server.isDedicated() || player.hasPermissionLevel(3)) { + if (!server.isDedicated() || player.hasPermissionLevel(3) || all) { NetworkHandler.sendToClient(player, packet); } } } @Override - public void backupProgress(int progress, int max) { + public void backupProgress(int progress, int max, boolean all) { MinecraftServer server = AdvancedBackups.server; List players = server.getPlayerManager().getPlayerList(); PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, false, progress, max); for (ServerPlayerEntity player : players) { if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; - if (!server.isDedicated() || player.hasPermissionLevel(3)) { + if (!server.isDedicated() || player.hasPermissionLevel(3) || all) { NetworkHandler.sendToClient(player, packet); } } } @Override - public void backupStarting() { + public void backupStarting(boolean all) { MinecraftServer server = AdvancedBackups.server; List players = server.getPlayerManager().getPlayerList(); PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, false, 0, 0); for (ServerPlayerEntity player : players) { if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; - if (!server.isDedicated() || player.hasPermissionLevel(3)) { + if (!server.isDedicated() || player.hasPermissionLevel(3) || all) { NetworkHandler.sendToClient(player, packet); } } } @Override - public void backupCancelled() { + public void backupCancelled(boolean all) { MinecraftServer server = AdvancedBackups.server; List players = server.getPlayerManager().getPlayerList(); PacketBackupStatus packet = new PacketBackupStatus(false, false, false, false, true, 0, 0); for (ServerPlayerEntity player : players) { if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; - if (!server.isDedicated() || player.hasPermissionLevel(3)) { + if (!server.isDedicated() || player.hasPermissionLevel(3) || all) { NetworkHandler.sendToClient(player, packet); } } From 638eb9433ac3120008e641ca1b0f0f7ef3745301 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 18 Jun 2024 18:34:18 +0100 Subject: [PATCH 525/580] 3.6 support --- .../advancedbackups/AdvancedBackups.java | 3 --- .../client/ClientContactor.java | 20 +++++++++---------- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index a72d4e40..885d3731 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -144,7 +144,6 @@ public static void disableSaving() { level.noSave = true; } } - if (ConfigManager.silent.get()) return; warningLogger.accept(savesDisabledMessage); } @@ -155,14 +154,12 @@ public static void enableSaving() { level.noSave = false; } } - if (ConfigManager.silent.get()) return; warningLogger.accept(savesEnabledMessage); } public static void saveOnce(boolean flush) { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); server.saveEverything(true, flush, true); - if (ConfigManager.silent.get()) return; warningLogger.accept(saveCompleteMessage); } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java index 69fd4eb0..54ca8bc7 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java @@ -13,65 +13,65 @@ public class ClientContactor implements IClientContactor { @Override - public void backupComplete() { + public void backupComplete(boolean all) { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, false, 0, 0); for (ServerPlayer player : players) { if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; - if (!server.isDedicatedServer() || player.hasPermissions(3)) { + if (!server.isDedicatedServer() || player.hasPermissions(3) || all) { NetworkHandler.sendToClient(player, packet); } } } @Override - public void backupFailed() { + public void backupFailed(boolean all) { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, false, 0, 0); for (ServerPlayer player : players) { if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; - if (!server.isDedicatedServer() || player.hasPermissions(3)) { + if (!server.isDedicatedServer() || player.hasPermissions(3) || all) { NetworkHandler.sendToClient(player, packet); } } } @Override - public void backupProgress(int progress, int max) { + public void backupProgress(int progress, int max, boolean all) { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, false, progress, max); for (ServerPlayer player : players) { if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; - if (!server.isDedicatedServer() || player.hasPermissions(3)) { + if (!server.isDedicatedServer() || player.hasPermissions(3) || all) { NetworkHandler.sendToClient(player, packet); } } } @Override - public void backupStarting() { + public void backupStarting(boolean all) { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, false, 0, 0); for (ServerPlayer player : players) { if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; - if (!server.isDedicatedServer() || player.hasPermissions(3)) { + if (!server.isDedicatedServer() || player.hasPermissions(3) || all) { NetworkHandler.sendToClient(player, packet); } } } @Override - public void backupCancelled() { + public void backupCancelled(boolean all) { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(false, false, false, false, true, 0, 0); for (ServerPlayer player : players) { if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; - if (!server.isDedicatedServer() || player.hasPermissions(3)) { + if (!server.isDedicatedServer() || player.hasPermissions(3) || all) { NetworkHandler.sendToClient(player, packet); } } From 81ab2d92fea2849a45c44c2500c25cbf50750095 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 18 Jun 2024 18:38:36 +0100 Subject: [PATCH 526/580] 3.6 support --- .../mommyheather/advancedbackups/AdvancedBackups.java | 3 --- .../advancedbackups/client/ClientContactor.java | 10 +++++----- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 77b3aed3..59312ff7 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -144,7 +144,6 @@ public static void disableSaving() { level.noSave = true; } } - if (ConfigManager.silent.get()) return; warningLogger.accept(savesDisabledMessage); } @@ -155,14 +154,12 @@ public static void enableSaving() { level.noSave = false; } } - if (ConfigManager.silent.get()) return; warningLogger.accept(savesEnabledMessage); } public static void saveOnce(boolean flush) { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); server.saveEverything(true, flush, true); - if (ConfigManager.silent.get()) return; warningLogger.accept(saveCompleteMessage); } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java index c8bd4203..1ab6303b 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java @@ -13,7 +13,7 @@ public class ClientContactor implements IClientContactor { @Override - public void backupComplete() { + public void backupComplete(boolean all) { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, false, 0, 0); @@ -26,7 +26,7 @@ public void backupComplete() { } @Override - public void backupFailed() { + public void backupFailed(boolean all) { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, false, 0, 0); @@ -39,7 +39,7 @@ public void backupFailed() { } @Override - public void backupProgress(int progress, int max) { + public void backupProgress(int progress, int max, boolean all) { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, false, progress, max); @@ -52,7 +52,7 @@ public void backupProgress(int progress, int max) { } @Override - public void backupStarting() { + public void backupStarting(boolean all) { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, false, 0, 0); @@ -65,7 +65,7 @@ public void backupStarting() { } @Override - public void backupCancelled() { + public void backupCancelled(boolean all) { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); List players = server.getPlayerList().getPlayers(); PacketBackupStatus packet = new PacketBackupStatus(false, false, false, false, true, 0, 0); From 2ebd35ddf7b522419ae74ee8901f23ba59e3a32e Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 18 Jun 2024 19:17:44 +0100 Subject: [PATCH 527/580] 3.6 core support --- .../advancedbackups/AdvancedBackups.java | 3 --- .../client/ClientContactor.java | 20 +++++++++---------- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 69adbc9f..f61736a5 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -124,7 +124,6 @@ public static void disableSaving() { level.savingDisabled = true; } } - if (ConfigManager.silent.get()) return; warningLogger.accept(savesDisabledMessage); } @@ -135,14 +134,12 @@ public static void enableSaving() { level.savingDisabled = false; } } - if (ConfigManager.silent.get()) return; warningLogger.accept(savesEnabledMessage); } public static void saveOnce(boolean flush) { MinecraftServer server = AdvancedBackups.server; server.saveAll(true, flush, true); - if (ConfigManager.silent.get()) return; warningLogger.accept(saveCompleteMessage); } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java index 770a6deb..c4bef66a 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java @@ -12,65 +12,65 @@ public class ClientContactor implements IClientContactor { @Override - public void backupComplete() { + public void backupComplete(boolean all) { MinecraftServer server = AdvancedBackups.server; List players = server.getPlayerManager().getPlayerList(); PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, false, 0, 0); for (ServerPlayerEntity player : players) { if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; - if (!server.isDedicated() || player.hasPermissionLevel(3)) { + if (!server.isDedicated() || player.hasPermissionLevel(3) || all) { NetworkHandler.sendToClient(player, packet); } } } @Override - public void backupFailed() { + public void backupFailed(boolean all) { MinecraftServer server = AdvancedBackups.server; List players = server.getPlayerManager().getPlayerList(); PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, false, 0, 0); for (ServerPlayerEntity player : players) { if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; - if (!server.isDedicated() || player.hasPermissionLevel(3)) { + if (!server.isDedicated() || player.hasPermissionLevel(3) || all) { NetworkHandler.sendToClient(player, packet); } } } @Override - public void backupProgress(int progress, int max) { + public void backupProgress(int progress, int max, boolean all) { MinecraftServer server = AdvancedBackups.server; List players = server.getPlayerManager().getPlayerList(); PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, false, progress, max); for (ServerPlayerEntity player : players) { if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; - if (!server.isDedicated() || player.hasPermissionLevel(3)) { + if (!server.isDedicated() || player.hasPermissionLevel(3) || all) { NetworkHandler.sendToClient(player, packet); } } } @Override - public void backupStarting() { + public void backupStarting(boolean all) { MinecraftServer server = AdvancedBackups.server; List players = server.getPlayerManager().getPlayerList(); PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, false, 0, 0); for (ServerPlayerEntity player : players) { if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; - if (!server.isDedicated() || player.hasPermissionLevel(3)) { + if (!server.isDedicated() || player.hasPermissionLevel(3) || all) { NetworkHandler.sendToClient(player, packet); } } } @Override - public void backupCancelled() { + public void backupCancelled(boolean all) { MinecraftServer server = AdvancedBackups.server; List players = server.getPlayerManager().getPlayerList(); PacketBackupStatus packet = new PacketBackupStatus(false, false, false, false, true, 0, 0); for (ServerPlayerEntity player : players) { if (!AdvancedBackups.players.contains(player.getUuidAsString())) continue; - if (!server.isDedicated() || player.hasPermissionLevel(3)) { + if (!server.isDedicated() || player.hasPermissionLevel(3) || all) { NetworkHandler.sendToClient(player, packet); } } From 9cd8cd7ff8cc58c14b52424598df1f2764405a30 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 18 Jun 2024 19:21:23 +0100 Subject: [PATCH 528/580] core 3.6 support --- .../advancedbackups/AdvancedBackups.java | 3 - .../client/ClientContactor.java | 158 +++++++++--------- 2 files changed, 79 insertions(+), 82 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 8362c3a4..d584d7b4 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -143,7 +143,6 @@ public static void disableSaving() { level.noSave = true; } } - if (ConfigManager.silent.get()) return; warningLogger.accept(savesDisabledMessage); } @@ -154,14 +153,12 @@ public static void enableSaving() { level.noSave = false; } } - if (ConfigManager.silent.get()) return; warningLogger.accept(savesEnabledMessage); } public static void saveOnce(boolean flush) { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); server.saveEverything(true, flush, true); - if (ConfigManager.silent.get()) return; warningLogger.accept(saveCompleteMessage); } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java index 3c25b3e7..54ca8bc7 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java @@ -1,79 +1,79 @@ -package co.uk.mommyheather.advancedbackups.client; - -import java.util.List; - -import co.uk.mommyheather.advancedbackups.AdvancedBackups; -import co.uk.mommyheather.advancedbackups.interfaces.IClientContactor; -import co.uk.mommyheather.advancedbackups.network.NetworkHandler; -import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ServerPlayer; -import net.minecraftforge.server.ServerLifecycleHooks; - -public class ClientContactor implements IClientContactor { - - @Override - public void backupComplete() { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - List players = server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, false, 0, 0); - for (ServerPlayer player : players) { - if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; - if (!server.isDedicatedServer() || player.hasPermissions(3)) { - NetworkHandler.sendToClient(player, packet); - } - } - } - - @Override - public void backupFailed() { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - List players = server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, false, 0, 0); - for (ServerPlayer player : players) { - if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; - if (!server.isDedicatedServer() || player.hasPermissions(3)) { - NetworkHandler.sendToClient(player, packet); - } - } - } - - @Override - public void backupProgress(int progress, int max) { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - List players = server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, false, progress, max); - for (ServerPlayer player : players) { - if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; - if (!server.isDedicatedServer() || player.hasPermissions(3)) { - NetworkHandler.sendToClient(player, packet); - } - } - } - - @Override - public void backupStarting() { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - List players = server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, false, 0, 0); - for (ServerPlayer player : players) { - if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; - if (!server.isDedicatedServer() || player.hasPermissions(3)) { - NetworkHandler.sendToClient(player, packet); - } - } - } - - @Override - public void backupCancelled() { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - List players = server.getPlayerList().getPlayers(); - PacketBackupStatus packet = new PacketBackupStatus(false, false, false, false, true, 0, 0); - for (ServerPlayer player : players) { - if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; - if (!server.isDedicatedServer() || player.hasPermissions(3)) { - NetworkHandler.sendToClient(player, packet); - } - } - } -} +package co.uk.mommyheather.advancedbackups.client; + +import java.util.List; + +import co.uk.mommyheather.advancedbackups.AdvancedBackups; +import co.uk.mommyheather.advancedbackups.interfaces.IClientContactor; +import co.uk.mommyheather.advancedbackups.network.NetworkHandler; +import co.uk.mommyheather.advancedbackups.network.PacketBackupStatus; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerPlayer; +import net.minecraftforge.server.ServerLifecycleHooks; + +public class ClientContactor implements IClientContactor { + + @Override + public void backupComplete(boolean all) { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, false, 0, 0); + for (ServerPlayer player : players) { + if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; + if (!server.isDedicatedServer() || player.hasPermissions(3) || all) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupFailed(boolean all) { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, false, 0, 0); + for (ServerPlayer player : players) { + if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; + if (!server.isDedicatedServer() || player.hasPermissions(3) || all) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupProgress(int progress, int max, boolean all) { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, false, progress, max); + for (ServerPlayer player : players) { + if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; + if (!server.isDedicatedServer() || player.hasPermissions(3) || all) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupStarting(boolean all) { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, false, 0, 0); + for (ServerPlayer player : players) { + if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; + if (!server.isDedicatedServer() || player.hasPermissions(3) || all) { + NetworkHandler.sendToClient(player, packet); + } + } + } + + @Override + public void backupCancelled(boolean all) { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + List players = server.getPlayerList().getPlayers(); + PacketBackupStatus packet = new PacketBackupStatus(false, false, false, false, true, 0, 0); + for (ServerPlayer player : players) { + if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; + if (!server.isDedicatedServer() || player.hasPermissions(3) || all) { + NetworkHandler.sendToClient(player, packet); + } + } + } +} From be26d4e403db3ffbe2b5f18c80dda59ab712ad96 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 18 Jun 2024 21:26:46 +0100 Subject: [PATCH 529/580] Initial commit! --- .gitattributes | 9 + .gitignore | 8 + build.gradle | 72 +++++ gradle.properties | 1 + gradle/libs.versions.toml | 8 + gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 43453 bytes gradle/wrapper/gradle-wrapper.properties | 7 + gradlew | 249 ++++++++++++++++++ gradlew.bat | 92 +++++++ settings.gradle | 5 + .../AdvancedBackups/AdvancedBackups.java | 17 ++ .../AdvancedBackupsCommand.java | 19 ++ src/main/resources/plugin.yml | 3 + 13 files changed, 490 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 build.gradle create mode 100644 gradle.properties create mode 100644 gradle/libs.versions.toml create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100644 gradlew create mode 100644 gradlew.bat create mode 100644 settings.gradle create mode 100644 src/main/java/computer/heather/AdvancedBackups/AdvancedBackups.java create mode 100644 src/main/java/computer/heather/AdvancedBackups/AdvancedBackupsCommand.java create mode 100644 src/main/resources/plugin.yml diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..c53344c0 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,9 @@ +# +# https://help.github.com/articles/dealing-with-line-endings/ +# +# Linux start script should use lf +/gradlew text eol=lf + +# These are Windows script files and should use crlf +*.bat text eol=crlf + diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..c97404b1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +# Ignore Gradle project-specific cache directory +.gradle + +# Ignore Gradle build output directory +build + +# Ignore vscode files +.vscode diff --git a/build.gradle b/build.gradle new file mode 100644 index 00000000..f71e1845 --- /dev/null +++ b/build.gradle @@ -0,0 +1,72 @@ +/* + * This file was generated by the Gradle 'init' task. + */ + +plugins { + id 'java-library' + id 'maven-publish' +} + +repositories { + mavenLocal() + maven { + url = uri('https://hub.spigotmc.org/nexus/content/repositories/snapshots/') + } + + maven { + url = uri('https://repo.maven.apache.org/maven2/') + } +} + +configurations { + // configuration that holds jars to include in the jar + extraLibs +} + +dependencies { + compileOnly libs.org.spigotmc.spigot.api +} + + + +tasks.withType(ProcessResources).configureEach { + var replaceProperties = [ + version: version + ] + inputs.properties replaceProperties + + filesMatching(['plugin.yml']) { + expand replaceProperties + [project: project] + } +} + +// Example for how to get properties into the manifest for reading at runtime. +tasks.named('jar', Jar).configure { + manifest { + attributes([ + "Main-Class" : "co.uk.mommyheather.advancedbackups.cli.AdvancedBackupsCLI", + "Specification-Title" : "advancedbackups", + "Specification-Vendor" : "mommyheather", + "Specification-Version" : "1", // We are version 1 of ourselves + "Implementation-Title" : project.name, + "Implementation-Version" : project.jar.archiveVersion, + "Implementation-Vendor" : "mommyheather", + "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ") + ]) + } + from { + configurations.extraLibs.collect { it.isDirectory() ? it : zipTree(it) } + } +} + +group = 'computer.heather.AdvancedBackups' +description = 'AdvancedBackups' +java.sourceCompatibility = JavaVersion.VERSION_21 + +publishing { + publications { + maven(MavenPublication) { + from(components.java) + } + } +} diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 00000000..b177a083 --- /dev/null +++ b/gradle.properties @@ -0,0 +1 @@ +version = "0.1-DEV" \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 00000000..a5d38769 --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,8 @@ +# This file was generated by the Gradle 'init' task. +# https://docs.gradle.org/current/userguide/platforms.html#sub::toml-dependencies-format + +[versions] +org-spigotmc-spigot-api = "1.20.6-R0.1-SNAPSHOT" + +[libraries] +org-spigotmc-spigot-api = { module = "org.spigotmc:spigot-api", version.ref = "org-spigotmc-spigot-api" } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..e6441136f3d4ba8a0da8d277868979cfbc8ad796 GIT binary patch literal 43453 zcma&N1CXTcmMvW9vTb(Rwr$&4wr$(C?dmSu>@vG-+vuvg^_??!{yS%8zW-#zn-LkA z5&1^$^{lnmUON?}LBF8_K|(?T0Ra(xUH{($5eN!MR#ZihR#HxkUPe+_R8Cn`RRs(P z_^*#_XlXmGv7!4;*Y%p4nw?{bNp@UZHv1?Um8r6)Fei3p@ClJn0ECfg1hkeuUU@Or zDaPa;U3fE=3L}DooL;8f;P0ipPt0Z~9P0)lbStMS)ag54=uL9ia-Lm3nh|@(Y?B`; zx_#arJIpXH!U{fbCbI^17}6Ri*H<>OLR%c|^mh8+)*h~K8Z!9)DPf zR2h?lbDZQ`p9P;&DQ4F0sur@TMa!Y}S8irn(%d-gi0*WxxCSk*A?3lGh=gcYN?FGl z7D=Js!i~0=u3rox^eO3i@$0=n{K1lPNU zwmfjRVmLOCRfe=seV&P*1Iq=^i`502keY8Uy-WNPwVNNtJFx?IwAyRPZo2Wo1+S(xF37LJZ~%i)kpFQ3Fw=mXfd@>%+)RpYQLnr}B~~zoof(JVm^^&f zxKV^+3D3$A1G;qh4gPVjhrC8e(VYUHv#dy^)(RoUFM?o%W-EHxufuWf(l*@-l+7vt z=l`qmR56K~F|v<^Pd*p~1_y^P0P^aPC##d8+HqX4IR1gu+7w#~TBFphJxF)T$2WEa zxa?H&6=Qe7d(#tha?_1uQys2KtHQ{)Qco)qwGjrdNL7thd^G5i8Os)CHqc>iOidS} z%nFEDdm=GXBw=yXe1W-ShHHFb?Cc70+$W~z_+}nAoHFYI1MV1wZegw*0y^tC*s%3h zhD3tN8b=Gv&rj}!SUM6|ajSPp*58KR7MPpI{oAJCtY~JECm)*m_x>AZEu>DFgUcby z1Qaw8lU4jZpQ_$;*7RME+gq1KySGG#Wql>aL~k9tLrSO()LWn*q&YxHEuzmwd1?aAtI zBJ>P=&$=l1efe1CDU;`Fd+_;&wI07?V0aAIgc(!{a z0Jg6Y=inXc3^n!U0Atk`iCFIQooHqcWhO(qrieUOW8X(x?(RD}iYDLMjSwffH2~tB z)oDgNBLB^AJBM1M^c5HdRx6fBfka`(LD-qrlh5jqH~);#nw|iyp)()xVYak3;Ybik z0j`(+69aK*B>)e_p%=wu8XC&9e{AO4c~O1U`5X9}?0mrd*m$_EUek{R?DNSh(=br# z#Q61gBzEpmy`$pA*6!87 zSDD+=@fTY7<4A?GLqpA?Pb2z$pbCc4B4zL{BeZ?F-8`s$?>*lXXtn*NC61>|*w7J* z$?!iB{6R-0=KFmyp1nnEmLsA-H0a6l+1uaH^g%c(p{iT&YFrbQ$&PRb8Up#X3@Zsk zD^^&LK~111%cqlP%!_gFNa^dTYT?rhkGl}5=fL{a`UViaXWI$k-UcHJwmaH1s=S$4 z%4)PdWJX;hh5UoK?6aWoyLxX&NhNRqKam7tcOkLh{%j3K^4Mgx1@i|Pi&}<^5>hs5 zm8?uOS>%)NzT(%PjVPGa?X%`N2TQCKbeH2l;cTnHiHppPSJ<7y-yEIiC!P*ikl&!B z%+?>VttCOQM@ShFguHVjxX^?mHX^hSaO_;pnyh^v9EumqSZTi+#f&_Vaija0Q-e*| z7ulQj6Fs*bbmsWp{`auM04gGwsYYdNNZcg|ph0OgD>7O}Asn7^Z=eI>`$2*v78;sj-}oMoEj&@)9+ycEOo92xSyY344^ z11Hb8^kdOvbf^GNAK++bYioknrpdN>+u8R?JxG=!2Kd9r=YWCOJYXYuM0cOq^FhEd zBg2puKy__7VT3-r*dG4c62Wgxi52EMCQ`bKgf*#*ou(D4-ZN$+mg&7$u!! z-^+Z%;-3IDwqZ|K=ah85OLwkO zKxNBh+4QHh)u9D?MFtpbl)us}9+V!D%w9jfAMYEb>%$A;u)rrI zuBudh;5PN}_6J_}l55P3l_)&RMlH{m!)ai-i$g)&*M`eN$XQMw{v^r@-125^RRCF0 z^2>|DxhQw(mtNEI2Kj(;KblC7x=JlK$@78`O~>V!`|1Lm-^JR$-5pUANAnb(5}B}JGjBsliK4& zk6y(;$e&h)lh2)L=bvZKbvh@>vLlreBdH8No2>$#%_Wp1U0N7Ank!6$dFSi#xzh|( zRi{Uw%-4W!{IXZ)fWx@XX6;&(m_F%c6~X8hx=BN1&q}*( zoaNjWabE{oUPb!Bt$eyd#$5j9rItB-h*5JiNi(v^e|XKAj*8(k<5-2$&ZBR5fF|JA z9&m4fbzNQnAU}r8ab>fFV%J0z5awe#UZ|bz?Ur)U9bCIKWEzi2%A+5CLqh?}K4JHi z4vtM;+uPsVz{Lfr;78W78gC;z*yTch~4YkLr&m-7%-xc ztw6Mh2d>_iO*$Rd8(-Cr1_V8EO1f*^@wRoSozS) zy1UoC@pruAaC8Z_7~_w4Q6n*&B0AjOmMWa;sIav&gu z|J5&|{=a@vR!~k-OjKEgPFCzcJ>#A1uL&7xTDn;{XBdeM}V=l3B8fE1--DHjSaxoSjNKEM9|U9#m2<3>n{Iuo`r3UZp;>GkT2YBNAh|b z^jTq-hJp(ebZh#Lk8hVBP%qXwv-@vbvoREX$TqRGTgEi$%_F9tZES@z8Bx}$#5eeG zk^UsLBH{bc2VBW)*EdS({yw=?qmevwi?BL6*=12k9zM5gJv1>y#ML4!)iiPzVaH9% zgSImetD@dam~e>{LvVh!phhzpW+iFvWpGT#CVE5TQ40n%F|p(sP5mXxna+Ev7PDwA zamaV4m*^~*xV+&p;W749xhb_X=$|LD;FHuB&JL5?*Y2-oIT(wYY2;73<^#46S~Gx| z^cez%V7x$81}UWqS13Gz80379Rj;6~WdiXWOSsdmzY39L;Hg3MH43o*y8ibNBBH`(av4|u;YPq%{R;IuYow<+GEsf@R?=@tT@!}?#>zIIn0CoyV!hq3mw zHj>OOjfJM3F{RG#6ujzo?y32m^tgSXf@v=J$ELdJ+=5j|=F-~hP$G&}tDZsZE?5rX ztGj`!S>)CFmdkccxM9eGIcGnS2AfK#gXwj%esuIBNJQP1WV~b~+D7PJTmWGTSDrR` zEAu4B8l>NPuhsk5a`rReSya2nfV1EK01+G!x8aBdTs3Io$u5!6n6KX%uv@DxAp3F@{4UYg4SWJtQ-W~0MDb|j-$lwVn znAm*Pl!?Ps&3wO=R115RWKb*JKoexo*)uhhHBncEDMSVa_PyA>k{Zm2(wMQ(5NM3# z)jkza|GoWEQo4^s*wE(gHz?Xsg4`}HUAcs42cM1-qq_=+=!Gk^y710j=66(cSWqUe zklbm8+zB_syQv5A2rj!Vbw8;|$@C!vfNmNV!yJIWDQ>{+2x zKjuFX`~~HKG~^6h5FntRpnnHt=D&rq0>IJ9#F0eM)Y-)GpRjiN7gkA8wvnG#K=q{q z9dBn8_~wm4J<3J_vl|9H{7q6u2A!cW{bp#r*-f{gOV^e=8S{nc1DxMHFwuM$;aVI^ zz6A*}m8N-&x8;aunp1w7_vtB*pa+OYBw=TMc6QK=mbA-|Cf* zvyh8D4LRJImooUaSb7t*fVfih<97Gf@VE0|z>NcBwBQze);Rh!k3K_sfunToZY;f2 z^HmC4KjHRVg+eKYj;PRN^|E0>Gj_zagfRbrki68I^#~6-HaHg3BUW%+clM1xQEdPYt_g<2K+z!$>*$9nQ>; zf9Bei{?zY^-e{q_*|W#2rJG`2fy@{%6u0i_VEWTq$*(ZN37|8lFFFt)nCG({r!q#9 z5VK_kkSJ3?zOH)OezMT{!YkCuSSn!K#-Rhl$uUM(bq*jY? zi1xbMVthJ`E>d>(f3)~fozjg^@eheMF6<)I`oeJYx4*+M&%c9VArn(OM-wp%M<-`x z7sLP1&3^%Nld9Dhm@$3f2}87!quhI@nwd@3~fZl_3LYW-B?Ia>ui`ELg z&Qfe!7m6ze=mZ`Ia9$z|ARSw|IdMpooY4YiPN8K z4B(ts3p%2i(Td=tgEHX z0UQ_>URBtG+-?0E;E7Ld^dyZ;jjw0}XZ(}-QzC6+NN=40oDb2^v!L1g9xRvE#@IBR zO!b-2N7wVfLV;mhEaXQ9XAU+>=XVA6f&T4Z-@AX!leJ8obP^P^wP0aICND?~w&NykJ#54x3_@r7IDMdRNy4Hh;h*!u(Ol(#0bJdwEo$5437-UBjQ+j=Ic>Q2z` zJNDf0yO6@mr6y1#n3)s(W|$iE_i8r@Gd@!DWDqZ7J&~gAm1#~maIGJ1sls^gxL9LLG_NhU!pTGty!TbhzQnu)I*S^54U6Yu%ZeCg`R>Q zhBv$n5j0v%O_j{QYWG!R9W?5_b&67KB$t}&e2LdMvd(PxN6Ir!H4>PNlerpBL>Zvyy!yw z-SOo8caEpDt(}|gKPBd$qND5#a5nju^O>V&;f890?yEOfkSG^HQVmEbM3Ugzu+UtH zC(INPDdraBN?P%kE;*Ae%Wto&sgw(crfZ#Qy(<4nk;S|hD3j{IQRI6Yq|f^basLY; z-HB&Je%Gg}Jt@={_C{L$!RM;$$|iD6vu#3w?v?*;&()uB|I-XqEKqZPS!reW9JkLewLb!70T7n`i!gNtb1%vN- zySZj{8-1>6E%H&=V}LM#xmt`J3XQoaD|@XygXjdZ1+P77-=;=eYpoEQ01B@L*a(uW zrZeZz?HJsw_4g0vhUgkg@VF8<-X$B8pOqCuWAl28uB|@r`19DTUQQsb^pfqB6QtiT z*`_UZ`fT}vtUY#%sq2{rchyfu*pCg;uec2$-$N_xgjZcoumE5vSI{+s@iLWoz^Mf; zuI8kDP{!XY6OP~q5}%1&L}CtfH^N<3o4L@J@zg1-mt{9L`s^z$Vgb|mr{@WiwAqKg zp#t-lhrU>F8o0s1q_9y`gQNf~Vb!F%70f}$>i7o4ho$`uciNf=xgJ>&!gSt0g;M>*x4-`U)ysFW&Vs^Vk6m%?iuWU+o&m(2Jm26Y(3%TL; zA7T)BP{WS!&xmxNw%J=$MPfn(9*^*TV;$JwRy8Zl*yUZi8jWYF>==j~&S|Xinsb%c z2?B+kpet*muEW7@AzjBA^wAJBY8i|#C{WtO_or&Nj2{=6JTTX05}|H>N2B|Wf!*3_ z7hW*j6p3TvpghEc6-wufFiY!%-GvOx*bZrhZu+7?iSrZL5q9}igiF^*R3%DE4aCHZ zqu>xS8LkW+Auv%z-<1Xs92u23R$nk@Pk}MU5!gT|c7vGlEA%G^2th&Q*zfg%-D^=f z&J_}jskj|Q;73NP4<4k*Y%pXPU2Thoqr+5uH1yEYM|VtBPW6lXaetokD0u z9qVek6Q&wk)tFbQ8(^HGf3Wp16gKmr>G;#G(HRBx?F`9AIRboK+;OfHaLJ(P>IP0w zyTbTkx_THEOs%Q&aPrxbZrJlio+hCC_HK<4%f3ZoSAyG7Dn`=X=&h@m*|UYO-4Hq0 z-Bq&+Ie!S##4A6OGoC~>ZW`Y5J)*ouaFl_e9GA*VSL!O_@xGiBw!AF}1{tB)z(w%c zS1Hmrb9OC8>0a_$BzeiN?rkPLc9%&;1CZW*4}CDDNr2gcl_3z+WC15&H1Zc2{o~i) z)LLW=WQ{?ricmC`G1GfJ0Yp4Dy~Ba;j6ZV4r{8xRs`13{dD!xXmr^Aga|C=iSmor% z8hi|pTXH)5Yf&v~exp3o+sY4B^^b*eYkkCYl*T{*=-0HniSA_1F53eCb{x~1k3*`W zr~};p1A`k{1DV9=UPnLDgz{aJH=-LQo<5%+Em!DNN252xwIf*wF_zS^!(XSm(9eoj z=*dXG&n0>)_)N5oc6v!>-bd(2ragD8O=M|wGW z!xJQS<)u70m&6OmrF0WSsr@I%T*c#Qo#Ha4d3COcX+9}hM5!7JIGF>7<~C(Ear^Sn zm^ZFkV6~Ula6+8S?oOROOA6$C&q&dp`>oR-2Ym3(HT@O7Sd5c~+kjrmM)YmgPH*tL zX+znN>`tv;5eOfX?h{AuX^LK~V#gPCu=)Tigtq9&?7Xh$qN|%A$?V*v=&-2F$zTUv z`C#WyIrChS5|Kgm_GeudCFf;)!WH7FI60j^0o#65o6`w*S7R@)88n$1nrgU(oU0M9 zx+EuMkC>(4j1;m6NoGqEkpJYJ?vc|B zOlwT3t&UgL!pX_P*6g36`ZXQ; z9~Cv}ANFnJGp(;ZhS(@FT;3e)0)Kp;h^x;$*xZn*k0U6-&FwI=uOGaODdrsp-!K$Ac32^c{+FhI-HkYd5v=`PGsg%6I`4d9Jy)uW0y%) zm&j^9WBAp*P8#kGJUhB!L?a%h$hJgQrx!6KCB_TRo%9{t0J7KW8!o1B!NC)VGLM5! zpZy5Jc{`r{1e(jd%jsG7k%I+m#CGS*BPA65ZVW~fLYw0dA-H_}O zrkGFL&P1PG9p2(%QiEWm6x;U-U&I#;Em$nx-_I^wtgw3xUPVVu zqSuKnx&dIT-XT+T10p;yjo1Y)z(x1fb8Dzfn8e yu?e%!_ptzGB|8GrCfu%p?(_ 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

NnX)EH+Nua)3Y(c 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 '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 00000000..25da30db --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,92 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 00000000..4edad9ea --- /dev/null +++ b/settings.gradle @@ -0,0 +1,5 @@ +/* + * This file was generated by the Gradle 'init' task. + */ + +rootProject.name = 'AdvancedBackups' \ No newline at end of file diff --git a/src/main/java/computer/heather/AdvancedBackups/AdvancedBackups.java b/src/main/java/computer/heather/AdvancedBackups/AdvancedBackups.java new file mode 100644 index 00000000..ca732629 --- /dev/null +++ b/src/main/java/computer/heather/AdvancedBackups/AdvancedBackups.java @@ -0,0 +1,17 @@ +package computer.heather.AdvancedBackups; + +import org.bukkit.plugin.java.JavaPlugin; + +public class AdvancedBackups extends JavaPlugin { + + @Override + public void onEnable() { + getLogger().info("onEnable called! I don't yet know how to handle this..."); + } + @Override + public void onDisable() { + getLogger().info("onDisable called! I don't yet know how to handle this..."); + } + + +} \ No newline at end of file diff --git a/src/main/java/computer/heather/AdvancedBackups/AdvancedBackupsCommand.java b/src/main/java/computer/heather/AdvancedBackups/AdvancedBackupsCommand.java new file mode 100644 index 00000000..956754d8 --- /dev/null +++ b/src/main/java/computer/heather/AdvancedBackups/AdvancedBackupsCommand.java @@ -0,0 +1,19 @@ +package computer.heather.AdvancedBackups; + +import java.util.Arrays; + +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; + +public class AdvancedBackupsCommand extends Command { + + public AdvancedBackupsCommand() { + super("backup", "/backup start | reload-config | reload-client-config | snapshot | reset-chain", "Commands for the Advanced Backups mod", Arrays.asList(new String[] {"advancedbackups"})); + } + + @Override + public boolean execute(CommandSender arg0, String arg1, String[] arg2) { + return false; + } + +} diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml new file mode 100644 index 00000000..f58f7176 --- /dev/null +++ b/src/main/resources/plugin.yml @@ -0,0 +1,3 @@ +name: AdvancedBackups +version: ${version} +main: heather.computer.AdvancedBackups.AdvancedBackups \ No newline at end of file From 9a3aa2c1be620624057663f9b2e31d0d90317a03 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 18 Jun 2024 21:38:57 +0100 Subject: [PATCH 530/580] buildscript updates --- build.gradle | 12 ++++++++---- gradle.properties | 7 ++++++- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/build.gradle b/build.gradle index f71e1845..3dea0035 100644 --- a/build.gradle +++ b/build.gradle @@ -7,6 +7,14 @@ plugins { id 'maven-publish' } +group = 'computer.heather.AdvancedBackups' +description = 'AdvancedBackups' +java.sourceCompatibility = JavaVersion.VERSION_21 + +base { + archivesName = 'AdvancedBackups-' + modloaderName + "-" + minecraftVersion +} + repositories { mavenLocal() maven { @@ -59,10 +67,6 @@ tasks.named('jar', Jar).configure { } } -group = 'computer.heather.AdvancedBackups' -description = 'AdvancedBackups' -java.sourceCompatibility = JavaVersion.VERSION_21 - publishing { publications { maven(MavenPublication) { diff --git a/gradle.properties b/gradle.properties index b177a083..8f4b2912 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1 +1,6 @@ -version = "0.1-DEV" \ No newline at end of file +version = 0.1-DEV + + +modloaderName =spigot +#We'll target 1.21, if it works on 1.20.6 then *cool* +minecraftVersion =1.21 \ No newline at end of file From d578a646d7e84ad093c8da6bb1d39bf733033e43 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 18 Jun 2024 22:03:04 +0100 Subject: [PATCH 531/580] I can't believe I'm copying fucking 1.7.10 code --- .../AdvancedBackups/AdvancedBackups.java | 13 ++- .../AdvancedBackupsCommand.java | 93 +++++++++++++++++-- 2 files changed, 96 insertions(+), 10 deletions(-) diff --git a/src/main/java/computer/heather/AdvancedBackups/AdvancedBackups.java b/src/main/java/computer/heather/AdvancedBackups/AdvancedBackups.java index ca732629..ccb988fe 100644 --- a/src/main/java/computer/heather/AdvancedBackups/AdvancedBackups.java +++ b/src/main/java/computer/heather/AdvancedBackups/AdvancedBackups.java @@ -4,14 +4,23 @@ public class AdvancedBackups extends JavaPlugin { + private static boolean enabled = false; + @Override public void onEnable() { - getLogger().info("onEnable called! I don't yet know how to handle this..."); + enabled = true; + this.getCommand("backup").setExecutor(new AdvancedBackupsCommand()); } + @Override public void onDisable() { - getLogger().info("onDisable called! I don't yet know how to handle this..."); + enabled = false; } + public boolean getEnabled() { + return enabled; + } + + } \ No newline at end of file diff --git a/src/main/java/computer/heather/AdvancedBackups/AdvancedBackupsCommand.java b/src/main/java/computer/heather/AdvancedBackups/AdvancedBackupsCommand.java index 956754d8..4b2f190e 100644 --- a/src/main/java/computer/heather/AdvancedBackups/AdvancedBackupsCommand.java +++ b/src/main/java/computer/heather/AdvancedBackups/AdvancedBackupsCommand.java @@ -1,19 +1,96 @@ package computer.heather.AdvancedBackups; -import java.util.Arrays; - import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; -public class AdvancedBackupsCommand extends Command { +import co.uk.mommyheather.advancedbackups.core.CoreCommandSystem; - public AdvancedBackupsCommand() { - super("backup", "/backup start | reload-config | reload-client-config | snapshot | reset-chain", "Commands for the Advanced Backups mod", Arrays.asList(new String[] {"advancedbackups"})); - } + +// /backup start | reload-config | reload-client-config | snapshot | reset-chain +public class AdvancedBackupsCommand implements CommandExecutor { @Override - public boolean execute(CommandSender arg0, String arg1, String[] arg2) { - return false; + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + if (args.length == 0) + { + return false; + } + else if ("start".equals(args[0])) + { + Start.execute(sender); + } + else if ("reload-config".equals(args[0])) + { + Reload.execute(sender); + } + else if ("reload-client-config".equals(args[0])) + { + ReloadClient.execute(sender); + } + else if ("reset-chain".equals(args[0])) { + ResetChain.execute(sender); + } + else if ("snapshot".equals(args[0])) { + Snapshot.execute(sender); + } + else if ("cancel".equals(args[0])) { + Cancel.execute(sender); + } + else + { + return false; + } + return true; } + public static class Reload { + public static void execute(CommandSender sender) { + CoreCommandSystem.reloadConfig((response) -> { + sender.sendMessage(response); + }); + } + } + + public static class ReloadClient { + public static void execute(CommandSender sender) { + sender.sendMessage("This can only be ran on the client!"); + } + } + + public static class Start { + public static void execute(CommandSender sender) { + CoreCommandSystem.startBackup((response) -> { + sender.sendMessage(response); + }); + } + } + + public static class ResetChain { + public static void execute(CommandSender sender) { + CoreCommandSystem.resetChainLength((response) -> { + sender.sendMessage(response); + }); + } + } + + public static class Snapshot { + public static void execute(CommandSender sender) { + CoreCommandSystem.snapshot((response) -> { + sender.sendMessage(response); + }); + } + + } + + public static class Cancel { + public static void execute(CommandSender sender) { + CoreCommandSystem.cancelBackup((response) -> { + sender.sendMessage(response); + }); + } + + } + + } From 61257e88621e095199ecd3b5f1b6da9bfdf84263 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 18 Jun 2024 22:03:33 +0100 Subject: [PATCH 532/580] dependency updates --- .gitignore | 3 +++ build.gradle | 3 +++ 2 files changed, 6 insertions(+) diff --git a/.gitignore b/.gitignore index c97404b1..f23716df 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,6 @@ build # Ignore vscode files .vscode + +#Ignore corelib +advancedbackups-corelib.jar \ No newline at end of file diff --git a/build.gradle b/build.gradle index 3dea0035..030fe112 100644 --- a/build.gradle +++ b/build.gradle @@ -33,6 +33,9 @@ configurations { dependencies { compileOnly libs.org.spigotmc.spigot.api + + implementation files ('advancedbackups-corelib.jar') + extraLibs files ('advancedbackups-corelib.jar') } From 0c91b70feb11d61784cb5bfcd4607d27526f7bda Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 18 Jun 2024 23:32:01 +0100 Subject: [PATCH 533/580] Did I ever tell you how much I hated buildtools? --- build.gradle | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 030fe112..c2f267a8 100644 --- a/build.gradle +++ b/build.gradle @@ -5,6 +5,7 @@ plugins { id 'java-library' id 'maven-publish' + id 'io.github.patrick.remapper' version "1.4.2" } group = 'computer.heather.AdvancedBackups' @@ -16,7 +17,6 @@ base { } repositories { - mavenLocal() maven { url = uri('https://hub.spigotmc.org/nexus/content/repositories/snapshots/') } @@ -24,6 +24,8 @@ repositories { maven { url = uri('https://repo.maven.apache.org/maven2/') } + mavenCentral() + mavenLocal() } configurations { @@ -32,7 +34,7 @@ configurations { } dependencies { - compileOnly libs.org.spigotmc.spigot.api + compileOnly("org.spigotmc:spigot:1.21-R0.1-SNAPSHOT:remapped-mojang") implementation files ('advancedbackups-corelib.jar') extraLibs files ('advancedbackups-corelib.jar') @@ -70,6 +72,15 @@ tasks.named('jar', Jar).configure { } } +tasks { + remap { + version.set("1.21") + } + build { + dependsOn(remap) + } +} + publishing { publications { maven(MavenPublication) { From 8be56e316a01c8909bab3a8547c24373a46250f7 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 18 Jun 2024 23:32:13 +0100 Subject: [PATCH 534/580] and some indev stuff --- .../AdvancedBackups/AdvancedBackups.java | 91 ++++++++++++++++++- 1 file changed, 87 insertions(+), 4 deletions(-) diff --git a/src/main/java/computer/heather/AdvancedBackups/AdvancedBackups.java b/src/main/java/computer/heather/AdvancedBackups/AdvancedBackups.java index ccb988fe..ad2d2ffb 100644 --- a/src/main/java/computer/heather/AdvancedBackups/AdvancedBackups.java +++ b/src/main/java/computer/heather/AdvancedBackups/AdvancedBackups.java @@ -1,26 +1,109 @@ package computer.heather.AdvancedBackups; +import java.util.function.Consumer; + +import org.bukkit.Server; +import org.bukkit.World; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.server.ServerLoadEvent; import org.bukkit.plugin.java.JavaPlugin; -public class AdvancedBackups extends JavaPlugin { +import co.uk.mommyheather.advancedbackups.core.ABCore; +import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; +public class AdvancedBackups extends JavaPlugin implements Listener { + private static boolean enabled = false; - + private static Server server = null; + + public static Consumer infoLogger; + public static Consumer warningLogger; + public static Consumer errorLogger; + @Override public void onEnable() { enabled = true; + AdvancedBackups.server = getServer(); + infoLogger = getLogger()::info; + warningLogger = getLogger()::warning; + errorLogger = getLogger()::severe; this.getCommand("backup").setExecutor(new AdvancedBackupsCommand()); - } + getServer().getPluginManager().registerEvents(this, this); + + /* + * NYI + ABCore.disableSaving = AdvancedBackups::disableSaving; + ABCore.enableSaving = AdvancedBackups::enableSaving; + ABCore.saveOnce = AdvancedBackups::saveOnce; + */ + + ABCore.infoLogger = infoLogger; + ABCore.warningLogger = warningLogger; + ABCore.errorLogger = errorLogger; + //NYI + //ABCore.clientContactor = new ABClientContactor(); + //ABCore.resetActivity = AdvancedBackups::resetActivity; + } + @Override public void onDisable() { enabled = false; + BackupWrapper.checkShutdownBackups(); } - + public boolean getEnabled() { return enabled; } + + @EventHandler + public void onServerLoad(ServerLoadEvent event) { + BackupWrapper.checkStartupBackups(); + } + + /* handled in onDisable + @EventHandler + public void onServerStop( event) { + BackupWrapper.checkShutdownBackups();; + }*/ + + @EventHandler + public void onPlayerJoin(PlayerJoinEvent event) { + ABCore.setActivity(true); + } + + public static final String savesDisabledMessage = "\n\n\n***************************************\nSAVING DISABLED - PREPARING FOR BACKUP!\n***************************************"; + public static final String savesEnabledMessage = "\n\n\n*********************************\nSAVING ENABLED - BACKUP COMPLETE!\n*********************************"; + public static final String saveCompleteMessage = "\n\n\n*************************************\nSAVE COMPLETE - PREPARING FOR BACKUP!\n*************************************"; + //fun fact : this boolean is named wrong in MCP mappings! + //reference : net.minecraft.command.server.CommandSaveOff and CommandSaveOn + //notice how off sets the boolean to true, and on sets it to false! + public static void disableSaving() { + for (World level : server.getWorlds()) { + level.setAutoSave(false); + } + warningLogger.accept(savesDisabledMessage); + } + + public static void enableSaving() { + for (World level : server.getWorlds()) { + level.setAutoSave(true); + } + warningLogger.accept(savesEnabledMessage); + } + + + public static void resetActivity() { + ABCore.setActivity(!server.getOnlinePlayers().isEmpty()); + } + + + + + } \ No newline at end of file From ffa00223d67a31ef14f75d7e88fba4f3c792413a Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 18 Jun 2024 23:41:04 +0100 Subject: [PATCH 535/580] i really just do not need this file --- gradle/libs.versions.toml | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 gradle/libs.versions.toml diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml deleted file mode 100644 index a5d38769..00000000 --- a/gradle/libs.versions.toml +++ /dev/null @@ -1,8 +0,0 @@ -# This file was generated by the Gradle 'init' task. -# https://docs.gradle.org/current/userguide/platforms.html#sub::toml-dependencies-format - -[versions] -org-spigotmc-spigot-api = "1.20.6-R0.1-SNAPSHOT" - -[libraries] -org-spigotmc-spigot-api = { module = "org.spigotmc:spigot-api", version.ref = "org-spigotmc-spigot-api" } From 9bfcbc2db87419e86f424784aa22be1a38c9dd96 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 18 Jun 2024 23:48:22 +0100 Subject: [PATCH 536/580] no good way to have a flush boolean in spigot? is this concerning? --- .../AdvancedBackups/AdvancedBackups.java | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/main/java/computer/heather/AdvancedBackups/AdvancedBackups.java b/src/main/java/computer/heather/AdvancedBackups/AdvancedBackups.java index ad2d2ffb..e10faac5 100644 --- a/src/main/java/computer/heather/AdvancedBackups/AdvancedBackups.java +++ b/src/main/java/computer/heather/AdvancedBackups/AdvancedBackups.java @@ -32,12 +32,9 @@ public void onEnable() { this.getCommand("backup").setExecutor(new AdvancedBackupsCommand()); getServer().getPluginManager().registerEvents(this, this); - /* - * NYI ABCore.disableSaving = AdvancedBackups::disableSaving; ABCore.enableSaving = AdvancedBackups::enableSaving; ABCore.saveOnce = AdvancedBackups::saveOnce; - */ ABCore.infoLogger = infoLogger; ABCore.warningLogger = warningLogger; @@ -45,7 +42,7 @@ public void onEnable() { //NYI //ABCore.clientContactor = new ABClientContactor(); - //ABCore.resetActivity = AdvancedBackups::resetActivity; + ABCore.resetActivity = AdvancedBackups::resetActivity; } @Override @@ -97,6 +94,21 @@ public static void enableSaving() { warningLogger.accept(savesEnabledMessage); } + public static void saveOnce(boolean unused) { + + server.savePlayers(); + boolean flag; + + for (World level : server.getWorlds()) { + flag = level.isAutoSave(); + level.setAutoSave(false); + level.save(); + level.setAutoSave(flag); + } + + warningLogger.accept(saveCompleteMessage); + } + public static void resetActivity() { ABCore.setActivity(!server.getOnlinePlayers().isEmpty()); From e2881878590a28d07542f89d08d4aa4f1357a926 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Wed, 19 Jun 2024 02:09:30 +0100 Subject: [PATCH 537/580] DEBUGGER --- .gitignore | 5 ++++- build.gradle | 1 + customTasks.gradle | 5 +++++ .../computer/heather/AdvancedBackups/AdvancedBackups.java | 3 +++ src/main/resources/plugin.yml | 2 +- 5 files changed, 14 insertions(+), 2 deletions(-) create mode 100644 customTasks.gradle diff --git a/.gitignore b/.gitignore index f23716df..cba32c51 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,7 @@ build .vscode #Ignore corelib -advancedbackups-corelib.jar \ No newline at end of file +advancedbackups-corelib.jar + +#Runtime +run \ No newline at end of file diff --git a/build.gradle b/build.gradle index c2f267a8..5e3bf952 100644 --- a/build.gradle +++ b/build.gradle @@ -7,6 +7,7 @@ plugins { id 'maven-publish' id 'io.github.patrick.remapper' version "1.4.2" } +apply from: 'customTasks.gradle' group = 'computer.heather.AdvancedBackups' description = 'AdvancedBackups' diff --git a/customTasks.gradle b/customTasks.gradle new file mode 100644 index 00000000..f8b7a7ca --- /dev/null +++ b/customTasks.gradle @@ -0,0 +1,5 @@ +task prepareDebug (type: Copy, dependsOn: 'jar') { + doNotTrackState("Must run!") + from jar + into "run/plugins" +} \ No newline at end of file diff --git a/src/main/java/computer/heather/AdvancedBackups/AdvancedBackups.java b/src/main/java/computer/heather/AdvancedBackups/AdvancedBackups.java index e10faac5..aea00e4e 100644 --- a/src/main/java/computer/heather/AdvancedBackups/AdvancedBackups.java +++ b/src/main/java/computer/heather/AdvancedBackups/AdvancedBackups.java @@ -12,6 +12,7 @@ import co.uk.mommyheather.advancedbackups.core.ABCore; import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; +import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; public class AdvancedBackups extends JavaPlugin implements Listener { @@ -31,6 +32,8 @@ public void onEnable() { errorLogger = getLogger()::severe; this.getCommand("backup").setExecutor(new AdvancedBackupsCommand()); getServer().getPluginManager().registerEvents(this, this); + + ConfigManager.loadOrCreateConfig(); ABCore.disableSaving = AdvancedBackups::disableSaving; ABCore.enableSaving = AdvancedBackups::enableSaving; diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index f58f7176..57dc9bfd 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,3 +1,3 @@ name: AdvancedBackups version: ${version} -main: heather.computer.AdvancedBackups.AdvancedBackups \ No newline at end of file +main: computer.heather.AdvancedBackups.AdvancedBackups \ No newline at end of file From ab56bc70883dd8fa539950ebe131602504847bbe Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Wed, 19 Jun 2024 02:10:42 +0100 Subject: [PATCH 538/580] command registration --- src/main/resources/plugin.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 57dc9bfd..09070516 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,3 +1,8 @@ name: AdvancedBackups version: ${version} -main: computer.heather.AdvancedBackups.AdvancedBackups \ No newline at end of file +main: computer.heather.AdvancedBackups.AdvancedBackups +commands: + backup: + description: Commands for Advanced Backups. + usage: /backup start | reload-config | reload-client-config | snapshot | reset-chain + permission: advancedbackups.backup \ No newline at end of file From 297f5b72e0e488a1dc73dc3716502278c357eb89 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Wed, 19 Jun 2024 02:42:55 +0100 Subject: [PATCH 539/580] backup schedule now works. Is the client contact the only thing we're missing? --- .../AdvancedBackups/AdvancedBackups.java | 41 ++++++++++++++----- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/src/main/java/computer/heather/AdvancedBackups/AdvancedBackups.java b/src/main/java/computer/heather/AdvancedBackups/AdvancedBackups.java index aea00e4e..f3a7ee5a 100644 --- a/src/main/java/computer/heather/AdvancedBackups/AdvancedBackups.java +++ b/src/main/java/computer/heather/AdvancedBackups/AdvancedBackups.java @@ -9,8 +9,10 @@ import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.server.ServerLoadEvent; import org.bukkit.plugin.java.JavaPlugin; +import org.bukkit.scheduler.BukkitRunnable; import co.uk.mommyheather.advancedbackups.core.ABCore; +import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; @@ -26,26 +28,42 @@ public class AdvancedBackups extends JavaPlugin implements Listener { @Override public void onEnable() { enabled = true; + + ABCore.disableSaving = AdvancedBackups::disableSaving; + ABCore.enableSaving = AdvancedBackups::enableSaving; + ABCore.saveOnce = AdvancedBackups::saveOnce; + AdvancedBackups.server = getServer(); + + ABCore.worldName = getServer().getWorlds().get(0).getName(); + ABCore.worldDir = getServer().getWorlds().get(0).getWorldFolder().toPath(); + ABCore.modJar = getFile(); + + infoLogger = getLogger()::info; warningLogger = getLogger()::warning; errorLogger = getLogger()::severe; + + ABCore.infoLogger = infoLogger; + ABCore.warningLogger = warningLogger; + ABCore.errorLogger = errorLogger; + this.getCommand("backup").setExecutor(new AdvancedBackupsCommand()); getServer().getPluginManager().registerEvents(this, this); ConfigManager.loadOrCreateConfig(); - ABCore.disableSaving = AdvancedBackups::disableSaving; - ABCore.enableSaving = AdvancedBackups::enableSaving; - ABCore.saveOnce = AdvancedBackups::saveOnce; - - ABCore.infoLogger = infoLogger; - ABCore.warningLogger = warningLogger; - ABCore.errorLogger = errorLogger; //NYI //ABCore.clientContactor = new ABClientContactor(); ABCore.resetActivity = AdvancedBackups::resetActivity; + + new BukkitRunnable() { + @Override + public void run() { + AdvancedBackups.this.onTickEnd(); + } + }.runTaskTimer(this, 0, 0); } @Override @@ -62,6 +80,7 @@ public boolean getEnabled() { public void onServerLoad(ServerLoadEvent event) { BackupWrapper.checkStartupBackups(); } + /* handled in onDisable @EventHandler @@ -74,15 +93,15 @@ public void onPlayerJoin(PlayerJoinEvent event) { ABCore.setActivity(true); } + public void onTickEnd() { + BackupTimer.check(); + } + public static final String savesDisabledMessage = "\n\n\n***************************************\nSAVING DISABLED - PREPARING FOR BACKUP!\n***************************************"; public static final String savesEnabledMessage = "\n\n\n*********************************\nSAVING ENABLED - BACKUP COMPLETE!\n*********************************"; public static final String saveCompleteMessage = "\n\n\n*************************************\nSAVE COMPLETE - PREPARING FOR BACKUP!\n*************************************"; - - //fun fact : this boolean is named wrong in MCP mappings! - //reference : net.minecraft.command.server.CommandSaveOff and CommandSaveOn - //notice how off sets the boolean to true, and on sets it to false! public static void disableSaving() { for (World level : server.getWorlds()) { level.setAutoSave(false); From 828ce373b60e9b71b23a57a920ac9835b59298ee Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Wed, 19 Jun 2024 04:54:29 +0100 Subject: [PATCH 540/580] is this just functional 1.21 already? barely any changes --- .../co/uk/mommyheather/advancedbackups/AdvancedBackups.java | 1 - .../co/uk/mommyheather/advancedbackups/client/BackupToast.java | 2 +- .../advancedbackups/network/PacketBackupStatus.java | 2 +- .../advancedbackups/network/PacketToastSubscribe.java | 2 +- 4 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java index 59312ff7..48bd7043 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/AdvancedBackups.java @@ -24,7 +24,6 @@ import net.neoforged.fml.ModList; import net.neoforged.fml.common.Mod; import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent; -import net.neoforged.fml.javafmlmod.FMLJavaModLoadingContext; import net.neoforged.neoforge.common.NeoForge; import net.neoforged.neoforge.event.RegisterCommandsEvent; import net.neoforged.neoforge.event.entity.player.PlayerEvent; diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java index a7b7414b..960167b1 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java @@ -26,7 +26,7 @@ public class BackupToast implements Toast { private static boolean timeSet = false; public static final ItemStack stack = new ItemStack(Items.PAPER); - private static final ResourceLocation TEXTURE = new ResourceLocation("toast/advancement"); + private static final ResourceLocation TEXTURE = ResourceLocation.parse("toast/advancement"); private int textColour; private String title = "You shouldn't see this!"; diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java index ea842bf2..75d9bf37 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java @@ -7,7 +7,7 @@ public record PacketBackupStatus(boolean starting, boolean started, boolean failed, boolean finished, boolean cancelled, int progress, int max) implements CustomPacketPayload { - public static final CustomPacketPayload.Type ID = new CustomPacketPayload.Type(new ResourceLocation("advancedbackups:backup_status")); + public static final CustomPacketPayload.Type ID = new CustomPacketPayload.Type(ResourceLocation.parse("advancedbackups:backup_status")); public static final StreamCodec CODEC = StreamCodec.of((buf, packet) -> { buf.writeBoolean(packet.starting); diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java index 514a7567..90d568de 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java @@ -11,7 +11,7 @@ public record PacketToastSubscribe(boolean enable) implements CustomPacketPayload { - public static final CustomPacketPayload.Type ID = new CustomPacketPayload.Type<>(new ResourceLocation("advancedbackups:toast_subscribe")); + public static final CustomPacketPayload.Type ID = new CustomPacketPayload.Type<>(ResourceLocation.parse("advancedbackups:toast_subscribe")); public PacketToastSubscribe(boolean enable) { this.enable = enable; From 31085040270f0335256dd156bfba738dbca9a19e Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Wed, 19 Jun 2024 04:58:50 +0100 Subject: [PATCH 541/580] some forgotten checks --- README.md | 4 ++-- build.gradle | 19 ++++++++++++++---- gradle.properties | 51 +++++++++++++++++------------------------------ settings.gradle | 8 +++----- 4 files changed, 38 insertions(+), 44 deletions(-) diff --git a/README.md b/README.md index 8fa7bc54..03c810f6 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Neoforge - 1.20.6 +# Neoforge - 1.21 -This is the branch specifically for neoforge 1.20.6. +This is the branch specifically for neoforge 1.20.1. Any differences will be listed below. For full documentation, see the `core` branch. diff --git a/build.gradle b/build.gradle index a318c9a8..c44dba73 100644 --- a/build.gradle +++ b/build.gradle @@ -3,12 +3,23 @@ plugins { id 'eclipse' id 'idea' id 'maven-publish' - id 'net.neoforged.gradle.userdev' version '7.0.109' + id 'net.neoforged.gradle.userdev' version '7.0.142' +} + + +tasks.named('wrapper', Wrapper).configure { + // Define wrapper values here so as to not have to always do so when updating gradlew.properties. + // Switching this to Wrapper.DistributionType.ALL will download the full gradle sources that comes with + // documentation attached on cursor hover of gradle classes and methods. However, this comes with increased + // file size for Gradle. If you do switch this to ALL, run the Gradle wrapper task twice afterwards. + // (Verify by checking gradle/wrapper/gradle-wrapper.properties to see if distributionUrl now points to `-all`) + distributionType = Wrapper.DistributionType.BIN } group = mod_group_id version = "${version != 'unspecified' ? version : '0.1-dev'}" //debuggins sake + configurations { // configuration that holds jars to include in the jar extraLibs @@ -24,7 +35,7 @@ base { -// Mojang ships Java 17 to end users in 1.18+, so your mod should target Java 17. +// Mojang ships Java 17 to end users in 1.20.5+, so your mod should target Java 21. java.toolchain.languageVersion = JavaLanguageVersion.of(21) //minecraft.accessTransformers.file rootProject.file('src/main/resources/META-INF/accesstransformer.cfg') @@ -95,7 +106,7 @@ dependencies { // For all intends and purposes: You can treat this dependency as if it is a normal library you would use. implementation "net.neoforged:neoforge:${neo_version}" - + implementation files ('advancedbackups-corelib.jar') extraLibs files ('advancedbackups-corelib.jar') @@ -136,7 +147,7 @@ tasks.withType(ProcessResources).configureEach { inputs.properties replaceProperties filesMatching(['META-INF/neoforge.mods.toml']) { - expand replaceProperties + expand replaceProperties + [project: project] } } diff --git a/gradle.properties b/gradle.properties index f5678413..99d32a63 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,41 +1,26 @@ # Sets default memory used for gradle commands. Can be overridden by user or command line properties. -# This is required to provide enough memory for the Minecraft decompilation process. org.gradle.jvmargs=-Xmx3G org.gradle.daemon=false - - -## Environment Properties - -# The Minecraft version must agree with the Forge version to get a valid artifact -minecraft_version=1.20.5 +org.gradle.debug=false + +#read more on this at https://github.com/neoforged/NeoGradle/blob/NG_7.0/README.md#apply-parchment-mappings +# you can also find the latest versions at: https://parchmentmc.org/docs/getting-started +neogradle.subsystems.parchment.minecraftVersion=1.20.6 +neogradle.subsystems.parchment.mappingsVersion=2024.05.01 +# Environment Properties +# You can find the latest versions here: https://projects.neoforged.net/neoforged/neoforge +# The Minecraft version must agree with the Neo version to get a valid artifact +minecraft_version=1.21 # The Minecraft version range can use any release version of Minecraft as bounds. # Snapshots, pre-releases, and release candidates are not guaranteed to sort properly # as they do not follow standard versioning conventions. -minecraft_version_range=[1.20.5,1.21) -# The Forge version must agree with the Minecraft version to get a valid artifact -neo_version=20.5.17-beta -# The Forge version range can use any version of Forge as bounds or match the loader version range -neo_version_range=[20.5,21) -# The loader version range can only use the major version of Forge/FML as bounds -loader_version_range=[2,) -# The mapping channel to use for mappings. -# The default set of supported mapping channels are ["official", "snapshot", "snapshot_nodoc", "stable", "stable_nodoc"]. -# Additional mapping channels can be registered through the "channelProviders" extension in a Gradle plugin. -# -# | Channel | Version | | -# |-----------|----------------------|--------------------------------------------------------------------------------| -# | official | MCVersion | Official field/method names from Mojang mapping files | -# | parchment | YYYY.MM.DD-MCVersion | Open community-sourced parameter names and javadocs layered on top of official | -# -# You must be aware of the Mojang license when using the 'official' or 'parchment' mappings. -# See more information here: https://github.com/neoforged/NeoForm/blob/main/Mojang.md -# -# Parchment is an unofficial project maintained by ParchmentMC, separate from Minecraft Forge. -# Additional setup is needed to use their mappings, see https://parchmentmc.org/docs/getting-started -mapping_channel=official -# The mapping version to query from the mapping channel. -# This must match the format required by the mapping channel. -mapping_version=1.20.5 +minecraft_version_range=[1.21,1.21.1) +# The Neo version must agree with the Minecraft version to get a valid artifact +neo_version=21.0.0-beta +# The Neo version range can use any version of Neo as bounds +neo_version_range=[21.0.0-beta,) +# The loader version range can only use the major version of FML as bounds +loader_version_range=[4,) @@ -64,4 +49,4 @@ pack_format_number=18 modloaderName =neoforge #We support 1.20.5, but it shouldn't be used so we won't mention it here. -minecraftVersion =1.20.6 \ No newline at end of file +minecraftVersion =1.21 \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 07fc75e5..3f804224 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,13 +1,11 @@ pluginManagement { repositories { + mavenLocal() gradlePluginPortal() - maven { - name = 'NeoForged' - url = 'https://maven.neoforged.net/releases' - } + maven { url = 'https://maven.neoforged.net/releases' } } } plugins { - id 'org.gradle.toolchains.foojay-resolver-convention' version '0.5.0' + id 'org.gradle.toolchains.foojay-resolver-convention' version '0.8.0' } \ No newline at end of file From acdef1a7f9dbb0ec8d4a4b78449c866e1cff9b8e Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Wed, 19 Jun 2024 05:50:02 +0100 Subject: [PATCH 542/580] AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA --- .../java/computer/heather/AdvancedBackups/AdvancedBackups.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/computer/heather/AdvancedBackups/AdvancedBackups.java b/src/main/java/computer/heather/AdvancedBackups/AdvancedBackups.java index f3a7ee5a..666b1ab0 100644 --- a/src/main/java/computer/heather/AdvancedBackups/AdvancedBackups.java +++ b/src/main/java/computer/heather/AdvancedBackups/AdvancedBackups.java @@ -1,5 +1,6 @@ package computer.heather.AdvancedBackups; +import java.io.File; import java.util.function.Consumer; import org.bukkit.Server; @@ -36,7 +37,7 @@ public void onEnable() { AdvancedBackups.server = getServer(); ABCore.worldName = getServer().getWorlds().get(0).getName(); - ABCore.worldDir = getServer().getWorlds().get(0).getWorldFolder().toPath(); + ABCore.worldDir = new File(getServer().getWorlds().get(0).getWorldFolder(), "./").toPath(); //need to have this parent because of some forge compatability bullshit.. if i knew how much I'd need to do this I really would've just called getParent on the offending versions ABCore.modJar = getFile(); From d79b4854fb8b6a422e411fcf1e5bb058749359d3 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Wed, 19 Jun 2024 05:52:48 +0100 Subject: [PATCH 543/580] absolution --- .../java/computer/heather/AdvancedBackups/AdvancedBackups.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/computer/heather/AdvancedBackups/AdvancedBackups.java b/src/main/java/computer/heather/AdvancedBackups/AdvancedBackups.java index 666b1ab0..82028dda 100644 --- a/src/main/java/computer/heather/AdvancedBackups/AdvancedBackups.java +++ b/src/main/java/computer/heather/AdvancedBackups/AdvancedBackups.java @@ -38,7 +38,7 @@ public void onEnable() { ABCore.worldName = getServer().getWorlds().get(0).getName(); ABCore.worldDir = new File(getServer().getWorlds().get(0).getWorldFolder(), "./").toPath(); //need to have this parent because of some forge compatability bullshit.. if i knew how much I'd need to do this I really would've just called getParent on the offending versions - ABCore.modJar = getFile(); + ABCore.modJar = getFile().getAbsoluteFile(); infoLogger = getLogger()::info; From 9e973b9adde66195f9aac75194ef81d8bf96ab3f Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Wed, 19 Jun 2024 08:48:30 +0100 Subject: [PATCH 544/580] HAHAHAHAHA I HAVE NETWORKING (and improved debugging) --- build.gradle | 2 - customTasks.gradle | 5 -- .../AdvancedBackups/AdvancedBackups.java | 21 ++++- .../network/ClientContactor.java | 81 +++++++++++++++++++ .../network/PacketListener.java | 25 ++++++ 5 files changed, 123 insertions(+), 11 deletions(-) delete mode 100644 customTasks.gradle create mode 100644 src/main/java/computer/heather/AdvancedBackups/network/ClientContactor.java create mode 100644 src/main/java/computer/heather/AdvancedBackups/network/PacketListener.java diff --git a/build.gradle b/build.gradle index 5e3bf952..48490876 100644 --- a/build.gradle +++ b/build.gradle @@ -7,8 +7,6 @@ plugins { id 'maven-publish' id 'io.github.patrick.remapper' version "1.4.2" } -apply from: 'customTasks.gradle' - group = 'computer.heather.AdvancedBackups' description = 'AdvancedBackups' java.sourceCompatibility = JavaVersion.VERSION_21 diff --git a/customTasks.gradle b/customTasks.gradle deleted file mode 100644 index f8b7a7ca..00000000 --- a/customTasks.gradle +++ /dev/null @@ -1,5 +0,0 @@ -task prepareDebug (type: Copy, dependsOn: 'jar') { - doNotTrackState("Must run!") - from jar - into "run/plugins" -} \ No newline at end of file diff --git a/src/main/java/computer/heather/AdvancedBackups/AdvancedBackups.java b/src/main/java/computer/heather/AdvancedBackups/AdvancedBackups.java index 82028dda..f4b50740 100644 --- a/src/main/java/computer/heather/AdvancedBackups/AdvancedBackups.java +++ b/src/main/java/computer/heather/AdvancedBackups/AdvancedBackups.java @@ -1,6 +1,7 @@ package computer.heather.AdvancedBackups; import java.io.File; +import java.util.ArrayList; import java.util.function.Consumer; import org.bukkit.Server; @@ -16,15 +17,20 @@ import co.uk.mommyheather.advancedbackups.core.backups.BackupTimer; import co.uk.mommyheather.advancedbackups.core.backups.BackupWrapper; import co.uk.mommyheather.advancedbackups.core.config.ConfigManager; +import computer.heather.AdvancedBackups.network.ClientContactor; +import computer.heather.AdvancedBackups.network.PacketListener; public class AdvancedBackups extends JavaPlugin implements Listener { private static boolean enabled = false; - private static Server server = null; + public static Server server = null; public static Consumer infoLogger; public static Consumer warningLogger; public static Consumer errorLogger; + + //List of players that have asked to see packets + public static final ArrayList players = new ArrayList<>(); @Override public void onEnable() { @@ -39,7 +45,6 @@ public void onEnable() { ABCore.worldName = getServer().getWorlds().get(0).getName(); ABCore.worldDir = new File(getServer().getWorlds().get(0).getWorldFolder(), "./").toPath(); //need to have this parent because of some forge compatability bullshit.. if i knew how much I'd need to do this I really would've just called getParent on the offending versions ABCore.modJar = getFile().getAbsoluteFile(); - infoLogger = getLogger()::info; warningLogger = getLogger()::warning; @@ -53,10 +58,13 @@ public void onEnable() { getServer().getPluginManager().registerEvents(this, this); ConfigManager.loadOrCreateConfig(); + + server.getMessenger().registerIncomingPluginChannel(this, "advancedbackups:toast_subscribe", new PacketListener()); + server.getMessenger().registerOutgoingPluginChannel(this, "advancedbackups:backup_status"); - //NYI - //ABCore.clientContactor = new ABClientContactor(); + ABCore.clientContactor = new ClientContactor(); + ABCore.resetActivity = AdvancedBackups::resetActivity; new BukkitRunnable() { @@ -91,6 +99,11 @@ public void onServerStop( event) { @EventHandler public void onPlayerJoin(PlayerJoinEvent event) { + /*Might not need to do this + //Gets us the actual player class, not bukkit's strange reimpl + ServerPlayer player = MinecraftServer.getServer().getPlayerList().getPlayer(event.getPlayer().getUniqueId()); + player.connection.networkmanager*/ + ABCore.setActivity(true); } diff --git a/src/main/java/computer/heather/AdvancedBackups/network/ClientContactor.java b/src/main/java/computer/heather/AdvancedBackups/network/ClientContactor.java new file mode 100644 index 00000000..5d73a15e --- /dev/null +++ b/src/main/java/computer/heather/AdvancedBackups/network/ClientContactor.java @@ -0,0 +1,81 @@ +package computer.heather.AdvancedBackups.network; + +import co.uk.mommyheather.advancedbackups.interfaces.IClientContactor; +import computer.heather.AdvancedBackups.AdvancedBackups; + +public class ClientContactor implements IClientContactor { + + private static byte[] toBytes(boolean starting, boolean started, boolean failed, boolean finished, boolean cancelled, int progress, int max) { + byte[] ret = new byte[13]; + + ret[0] = (byte) (starting ? 1 : 0); + ret[1] = (byte) (started ? 1 : 0); + ret[2] = (byte) (failed ? 1 : 0); + ret[3] = (byte) (finished ? 1 : 0); + ret[4] = (byte) (cancelled ? 1 : 0); + + ret[5] = (byte) ((progress & 0xFF000000) >> 24); + ret[6] = (byte) ((progress & 0x00FF0000) >> 16); + ret[7] = (byte) ((progress & 0x0000FF00) >> 8); + ret[8] = (byte) ((progress & 0x000000FF) >> 0); + + ret[9] = (byte) ((max & 0xFF000000) >> 24); + ret[10] = (byte) ((max & 0x00FF0000) >> 16); + ret[11] = (byte) ((max & 0x0000FF00) >> 8); + ret[12] = (byte) ((max & 0x000000FF) >> 0); + + return ret; + } + + //starting, started, failed, finished, cancelled, progress, max + @Override + public void backupComplete(boolean all) { + byte[] bytes = toBytes(false, false, false, true, false, 0, 0); + + AdvancedBackups.server.getOnlinePlayers().forEach((player) -> { + if (!AdvancedBackups.players.contains(player.getUniqueId().toString())) return; + if (player.isOp() || all) player.sendPluginMessage(AdvancedBackups.getPlugin(AdvancedBackups.class), "advancedbackups:backup_status", bytes); + }); + } + + @Override + public void backupFailed(boolean all) { + byte[] bytes = toBytes(false, false, true, false, false, 0, 0); + + AdvancedBackups.server.getOnlinePlayers().forEach((player) -> { + if (!AdvancedBackups.players.contains(player.getUniqueId().toString())) return; + if (player.isOp() || all) player.sendPluginMessage(AdvancedBackups.getPlugin(AdvancedBackups.class), "advancedbackups:backup_status", bytes); + }); + } + + @Override + public void backupProgress(int progress, int max, boolean all) { + byte[] bytes = toBytes(false, true, false, false, false, progress, max); + + AdvancedBackups.server.getOnlinePlayers().forEach((player) -> { + if (!AdvancedBackups.players.contains(player.getUniqueId().toString())) return; + if (player.isOp() || all) player.sendPluginMessage(AdvancedBackups.getPlugin(AdvancedBackups.class), "advancedbackups:backup_status", bytes); + }); + } + + @Override + public void backupStarting(boolean all) { + byte[] bytes = toBytes(true, false, false, false, false, 0, 0); + + AdvancedBackups.server.getOnlinePlayers().forEach((player) -> { + if (!AdvancedBackups.players.contains(player.getUniqueId().toString())) return; + if (player.isOp() || all) player.sendPluginMessage(AdvancedBackups.getPlugin(AdvancedBackups.class), "advancedbackups:backup_status", bytes); + }); + } + + @Override + public void backupCancelled(boolean all) { + byte[] bytes = toBytes(false, false, false, false, true, 0, 0); + + AdvancedBackups.server.getOnlinePlayers().forEach((player) -> { + if (!AdvancedBackups.players.contains(player.getUniqueId().toString())) return; + if (player.isOp() || all) player.sendPluginMessage(AdvancedBackups.getPlugin(AdvancedBackups.class), "advancedbackups:backup_status", bytes); + }); + } + +} diff --git a/src/main/java/computer/heather/AdvancedBackups/network/PacketListener.java b/src/main/java/computer/heather/AdvancedBackups/network/PacketListener.java new file mode 100644 index 00000000..c756a14b --- /dev/null +++ b/src/main/java/computer/heather/AdvancedBackups/network/PacketListener.java @@ -0,0 +1,25 @@ +package computer.heather.AdvancedBackups.network; + +import org.bukkit.entity.Player; +import org.bukkit.plugin.messaging.PluginMessageListener; + +import co.uk.mommyheather.advancedbackups.core.ABCore; +import computer.heather.AdvancedBackups.AdvancedBackups; + +public class PacketListener implements PluginMessageListener { + + @Override + public void onPluginMessageReceived(String channel, Player player, byte[] message) { + String uuid = player.getUniqueId().toString(); + Boolean subscribe = message[0] != 0; + ABCore.infoLogger.accept("Player has chosen to " + (subscribe ? "accept" : "reject") + " progress updates."); + + if (!AdvancedBackups.players.contains(uuid) && subscribe) { + AdvancedBackups.players.add(uuid); + } + else if (!subscribe) { + AdvancedBackups.players.remove(uuid); + } + } + +} From 4ce8557f7e5b7689607a93ee399eb8d580faa28a Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Wed, 19 Jun 2024 08:54:47 +0100 Subject: [PATCH 545/580] and now I can tab complete! your time is near, 3.6 --- .../AdvancedBackups/AdvancedBackupsCommand.java | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/main/java/computer/heather/AdvancedBackups/AdvancedBackupsCommand.java b/src/main/java/computer/heather/AdvancedBackups/AdvancedBackupsCommand.java index 4b2f190e..35472c56 100644 --- a/src/main/java/computer/heather/AdvancedBackups/AdvancedBackupsCommand.java +++ b/src/main/java/computer/heather/AdvancedBackups/AdvancedBackupsCommand.java @@ -1,14 +1,20 @@ package computer.heather.AdvancedBackups; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; +import org.bukkit.command.TabCompleter; +import org.bukkit.util.StringUtil; import co.uk.mommyheather.advancedbackups.core.CoreCommandSystem; // /backup start | reload-config | reload-client-config | snapshot | reset-chain -public class AdvancedBackupsCommand implements CommandExecutor { +public class AdvancedBackupsCommand implements CommandExecutor, TabCompleter { @Override public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { @@ -92,5 +98,13 @@ public static void execute(CommandSender sender) { } + @Override + public List onTabComplete(CommandSender sender, Command command, String label, String[] args) { + final List completions = new ArrayList<>(); + StringUtil.copyPartialMatches(args[0], Arrays.asList(new String[] {"start", "reload-config", "reload-client-config", "reset-chain", "snapshot", "cancel"}), completions); + + return completions; + } + } From 63af3fb603c3e7eee7cb01aab4bc1844c5687b69 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Wed, 19 Jun 2024 09:16:10 +0100 Subject: [PATCH 546/580] Another relatively easy port! --- README.md | 4 ++-- build.gradle | 2 +- gradle.properties | 10 +++++----- gradle/wrapper/gradle-wrapper.properties | 2 +- .../advancedbackups/client/BackupToast.java | 6 +----- .../advancedbackups/network/PacketBackupStatus.java | 3 ++- .../advancedbackups/network/PacketToastSubscribe.java | 3 ++- src/main/resources/fabric.mod.json | 2 +- 8 files changed, 15 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 59ab5213..15cf6302 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Fabric - 1.20.6 +# Fabric - 1.21 -This is the branch specifically for fabric 1.20.6. +This is the branch specifically for fabric 1.21. Any differences will be listed below. For full documentation, see the `core` branch. diff --git a/build.gradle b/build.gradle index f6432078..5286d2e6 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ plugins { - id 'fabric-loom' version '1.6-SNAPSHOT' + id 'fabric-loom' version '1.7-SNAPSHOT' id 'maven-publish' } diff --git a/gradle.properties b/gradle.properties index 893ab27b..0def6aa7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,9 +4,9 @@ org.gradle.parallel=true # Fabric Properties # check these on https://fabricmc.net/develop -minecraft_version=1.20.5 -yarn_mappings=1.20.5+build.1 -loader_version=0.15.10 +minecraft_version=1.21 +yarn_mappings=1.21+build.2 +loader_version=0.15.11 # Mod Properties version=2.0 @@ -15,8 +15,8 @@ maven_group=co.uk.mommyheather.advancedbackups archives_base_name=advancedbackups modloaderName =fabric #We support 1.20.6, but it shouldn't be used so we won't show in the jar name. -minecraftVersion =1.20.6 +minecraftVersion =1.21 # Dependencies -fabric_version=0.97.5+1.20.5 +fabric_version=0.100.3+1.21 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index d878609b..deaa8089 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,7 @@ #Fri May 10 17:19:51 BST 2024 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java index 5e07eee1..df2766b1 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/BackupToast.java @@ -1,17 +1,13 @@ package co.uk.mommyheather.advancedbackups.client; -import com.mojang.blaze3d.systems.RenderSystem; import co.uk.mommyheather.advancedbackups.core.config.ClientConfigManager; import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.render.GameRenderer; import net.minecraft.client.resource.language.I18n; import net.minecraft.client.toast.Toast; import net.minecraft.client.toast.ToastManager; -import net.minecraft.client.util.math.MatrixStack; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; -import net.minecraft.util.Formatting; import net.minecraft.util.Identifier; public class BackupToast implements Toast { @@ -31,7 +27,7 @@ public class BackupToast implements Toast { private static boolean timeSet = false; public static final ItemStack stack = new ItemStack(Items.PAPER); - private static final Identifier TEXTURE = new Identifier("toast/advancement"); + private static final Identifier TEXTURE = Identifier.of("toast/advancement"); public static String title = "You shouldn't see this!"; public static int textColour = 0; diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java index b5df8d78..11f58463 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java @@ -3,10 +3,11 @@ import net.minecraft.network.PacketByteBuf; import net.minecraft.network.codec.PacketCodec; import net.minecraft.network.packet.CustomPayload; +import net.minecraft.util.Identifier; public record PacketBackupStatus(boolean starting, boolean started, boolean failed, boolean finished, boolean cancelled, int progress, int max) implements CustomPayload { - public static final Id ID = CustomPayload.id("advancedbackups:backup_status"); + public static final Id ID = new CustomPayload.Id(Identifier.of("advancedbackups:backup_status")); public static final PacketCodec CODEC = PacketCodec.of((packet, buf) -> { buf.writeBoolean(packet.starting); diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java index 13c69c8f..c18b72f0 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketToastSubscribe.java @@ -7,10 +7,11 @@ import net.minecraft.network.codec.PacketCodecs; import net.minecraft.network.packet.CustomPayload; import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.util.Identifier; public record PacketToastSubscribe(boolean enable) implements CustomPayload { - public static final Id ID = CustomPayload.id("advancedbackups:toast_subscribe"); + public static final Id ID = new CustomPayload.Id(Identifier.of("advancedbackups:toast_subscribe")); public PacketToastSubscribe(boolean enable) { this.enable = enable; diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 118fa15f..13190e66 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -24,7 +24,7 @@ }, "depends": { "fabricloader": ">=0.15.10", - "minecraft": ">=1.20.5", + "minecraft": ">=1.20.6", "java": ">=21", "fabric-api": "*" } From 7e49f15effbdf8cb21668520f515be1c5d929374 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Wed, 19 Jun 2024 09:42:01 +0100 Subject: [PATCH 547/580] mhm. not executable by default. --- gradlew | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 gradlew diff --git a/gradlew b/gradlew old mode 100644 new mode 100755 From 1824e6bae38a03ac2900a5815af151f935935f47 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Fri, 21 Jun 2024 03:22:52 +0100 Subject: [PATCH 548/580] apparently i missed this for neo 1.21, whoops. --- .../advancedbackups/client/ClientContactor.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java index 1ab6303b..3f8426fc 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java @@ -19,7 +19,7 @@ public void backupComplete(boolean all) { PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, false, 0, 0); for (ServerPlayer player : players) { if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; - if (!server.isDedicatedServer() || player.hasPermissions(3)) { + if (!server.isDedicatedServer() || player.hasPermissions(3) || all) { NetworkHandler.sendToClient(player, packet); } } @@ -32,7 +32,7 @@ public void backupFailed(boolean all) { PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, false, 0, 0); for (ServerPlayer player : players) { if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; - if (!server.isDedicatedServer() || player.hasPermissions(3)) { + if (!server.isDedicatedServer() || player.hasPermissions(3) || all) { NetworkHandler.sendToClient(player, packet); } } @@ -45,7 +45,7 @@ public void backupProgress(int progress, int max, boolean all) { PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, false, progress, max); for (ServerPlayer player : players) { if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; - if (!server.isDedicatedServer() || player.hasPermissions(3)) { + if (!server.isDedicatedServer() || player.hasPermissions(3) || all) { NetworkHandler.sendToClient(player, packet); } } @@ -58,7 +58,7 @@ public void backupStarting(boolean all) { PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, false, 0, 0); for (ServerPlayer player : players) { if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; - if (!server.isDedicatedServer() || player.hasPermissions(3)) { + if (!server.isDedicatedServer() || player.hasPermissions(3) || all) { NetworkHandler.sendToClient(player, packet); } } @@ -71,7 +71,7 @@ public void backupCancelled(boolean all) { PacketBackupStatus packet = new PacketBackupStatus(false, false, false, false, true, 0, 0); for (ServerPlayer player : players) { if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; - if (!server.isDedicatedServer() || player.hasPermissions(3)) { + if (!server.isDedicatedServer() || player.hasPermissions(3) || all) { NetworkHandler.sendToClient(player, packet); } } From 0ea0e707cf3f2de448276fd63a62bf65ff1286cd Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Fri, 21 Jun 2024 15:13:40 +0100 Subject: [PATCH 549/580] hotfix for a dedicated server incompatability --- .../network/NetworkHandler.java | 3 +- .../network/PacketBackupStatus.java | 41 +++++++++++-------- 2 files changed, 26 insertions(+), 18 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java index 5d473a8c..29a66b05 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java @@ -1,7 +1,6 @@ package co.uk.mommyheather.advancedbackups.network; -import co.uk.mommyheather.advancedbackups.client.ClientWrapper; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.server.level.ServerPlayer; import net.neoforged.neoforge.network.PacketDistributor; @@ -14,7 +13,7 @@ public class NetworkHandler { public static void onRegisterPayloadHandler(RegisterPayloadHandlersEvent event) { final PayloadRegistrar registrar = event.registrar("1").optional(); //this .optional() seems to be required, but will it be a problem for our packets with non-neo servers...? - registrar.commonToClient(PacketBackupStatus.ID, PacketBackupStatus.CODEC, ClientWrapper::handle); + registrar.commonToClient(PacketBackupStatus.ID, PacketBackupStatus.CODEC, PacketBackupStatus::handle); registrar.commonToServer(PacketToastSubscribe.ID, PacketToastSubscribe.CODEC, PacketToastSubscribe::handle); } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java index 75d9bf37..7294d50e 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java @@ -1,14 +1,18 @@ package co.uk.mommyheather.advancedbackups.network; +import co.uk.mommyheather.advancedbackups.client.BackupToast; +import co.uk.mommyheather.advancedbackups.client.ClientWrapper; +import net.minecraft.client.Minecraft; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.codec.StreamCodec; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.resources.ResourceLocation; +import net.neoforged.neoforge.network.handling.IPayloadContext; public record PacketBackupStatus(boolean starting, boolean started, boolean failed, boolean finished, boolean cancelled, int progress, int max) implements CustomPacketPayload { - + public static final CustomPacketPayload.Type ID = new CustomPacketPayload.Type(ResourceLocation.parse("advancedbackups:backup_status")); - + public static final StreamCodec CODEC = StreamCodec.of((buf, packet) -> { buf.writeBoolean(packet.starting); buf.writeBoolean(packet.started); @@ -17,23 +21,28 @@ public record PacketBackupStatus(boolean starting, boolean started, boolean fail buf.writeBoolean(packet.cancelled); buf.writeInt(packet.progress); buf.writeInt(packet.max); - }, - - buf -> new PacketBackupStatus( - buf.readBoolean(), - buf.readBoolean(), - buf.readBoolean(), - buf.readBoolean(), - buf.readBoolean(), - buf.readInt(), - buf.readInt() - )); - - + }, + + buf -> new PacketBackupStatus( + buf.readBoolean(), + buf.readBoolean(), + buf.readBoolean(), + buf.readBoolean(), + buf.readBoolean(), + buf.readInt(), + buf.readInt() + )); + + @Override public CustomPacketPayload.Type type() { return ID; } - + + + public static void handle(PacketBackupStatus packet, IPayloadContext context) { + ClientWrapper.handle(packet, context); + } + } From 03ec7b7d4bd4f5a437345a346d2623839bb9e5c7 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Fri, 21 Jun 2024 15:29:47 +0100 Subject: [PATCH 550/580] backport the neo 1.21 fixes --- .../advancedbackups/client/ClientContactor.java | 10 +++++----- .../advancedbackups/network/NetworkHandler.java | 3 +-- .../advancedbackups/network/PacketBackupStatus.java | 8 ++++++++ 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java index 1ab6303b..3f8426fc 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/client/ClientContactor.java @@ -19,7 +19,7 @@ public void backupComplete(boolean all) { PacketBackupStatus packet = new PacketBackupStatus(false, false, false, true, false, 0, 0); for (ServerPlayer player : players) { if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; - if (!server.isDedicatedServer() || player.hasPermissions(3)) { + if (!server.isDedicatedServer() || player.hasPermissions(3) || all) { NetworkHandler.sendToClient(player, packet); } } @@ -32,7 +32,7 @@ public void backupFailed(boolean all) { PacketBackupStatus packet = new PacketBackupStatus(false, false, true, false, false, 0, 0); for (ServerPlayer player : players) { if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; - if (!server.isDedicatedServer() || player.hasPermissions(3)) { + if (!server.isDedicatedServer() || player.hasPermissions(3) || all) { NetworkHandler.sendToClient(player, packet); } } @@ -45,7 +45,7 @@ public void backupProgress(int progress, int max, boolean all) { PacketBackupStatus packet = new PacketBackupStatus(false, true, false, false, false, progress, max); for (ServerPlayer player : players) { if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; - if (!server.isDedicatedServer() || player.hasPermissions(3)) { + if (!server.isDedicatedServer() || player.hasPermissions(3) || all) { NetworkHandler.sendToClient(player, packet); } } @@ -58,7 +58,7 @@ public void backupStarting(boolean all) { PacketBackupStatus packet = new PacketBackupStatus(true, false, false, false, false, 0, 0); for (ServerPlayer player : players) { if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; - if (!server.isDedicatedServer() || player.hasPermissions(3)) { + if (!server.isDedicatedServer() || player.hasPermissions(3) || all) { NetworkHandler.sendToClient(player, packet); } } @@ -71,7 +71,7 @@ public void backupCancelled(boolean all) { PacketBackupStatus packet = new PacketBackupStatus(false, false, false, false, true, 0, 0); for (ServerPlayer player : players) { if (!AdvancedBackups.players.contains(player.getStringUUID())) continue; - if (!server.isDedicatedServer() || player.hasPermissions(3)) { + if (!server.isDedicatedServer() || player.hasPermissions(3) || all) { NetworkHandler.sendToClient(player, packet); } } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java index 5d473a8c..29a66b05 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/NetworkHandler.java @@ -1,7 +1,6 @@ package co.uk.mommyheather.advancedbackups.network; -import co.uk.mommyheather.advancedbackups.client.ClientWrapper; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.server.level.ServerPlayer; import net.neoforged.neoforge.network.PacketDistributor; @@ -14,7 +13,7 @@ public class NetworkHandler { public static void onRegisterPayloadHandler(RegisterPayloadHandlersEvent event) { final PayloadRegistrar registrar = event.registrar("1").optional(); //this .optional() seems to be required, but will it be a problem for our packets with non-neo servers...? - registrar.commonToClient(PacketBackupStatus.ID, PacketBackupStatus.CODEC, ClientWrapper::handle); + registrar.commonToClient(PacketBackupStatus.ID, PacketBackupStatus.CODEC, PacketBackupStatus::handle); registrar.commonToServer(PacketToastSubscribe.ID, PacketToastSubscribe.CODEC, PacketToastSubscribe::handle); } diff --git a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java index ea842bf2..87cd08d4 100644 --- a/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java +++ b/src/main/java/co/uk/mommyheather/advancedbackups/network/PacketBackupStatus.java @@ -1,9 +1,13 @@ package co.uk.mommyheather.advancedbackups.network; +import co.uk.mommyheather.advancedbackups.client.BackupToast; +import co.uk.mommyheather.advancedbackups.client.ClientWrapper; +import net.minecraft.client.Minecraft; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.codec.StreamCodec; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.resources.ResourceLocation; +import net.neoforged.neoforge.network.handling.IPayloadContext; public record PacketBackupStatus(boolean starting, boolean started, boolean failed, boolean finished, boolean cancelled, int progress, int max) implements CustomPacketPayload { @@ -35,5 +39,9 @@ public CustomPacketPayload.Type type() { return ID; } + public static void handle(PacketBackupStatus packet, IPayloadContext context) { + ClientWrapper.handle(packet, context); + } + } From 86ea48ea1d401b7df5a739eb4e199de1c60e16be Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Mon, 24 Jun 2024 18:15:39 +0100 Subject: [PATCH 551/580] #77. neo 21.0.25 removed an AT entry I needed. Fix tested in 21.0.33. --- src/main/resources/META-INF/accesstransformer.cfg | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/resources/META-INF/accesstransformer.cfg b/src/main/resources/META-INF/accesstransformer.cfg index 9d2bce8b..e0bbdfba 100644 --- a/src/main/resources/META-INF/accesstransformer.cfg +++ b/src/main/resources/META-INF/accesstransformer.cfg @@ -1 +1,2 @@ -public net.minecraft.client.multiplayer.ClientPacketListener lastSeenMessages # lastSeenMessages \ No newline at end of file +public net.minecraft.client.multiplayer.ClientPacketListener lastSeenMessages # lastSeenMessages +public net.minecraft.client.multiplayer.ClientCommonPacketListenerImpl connection # connection \ No newline at end of file From e086908ca4ac6626237f62177f35386c2e87a377 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 20 Aug 2024 21:22:44 +0100 Subject: [PATCH 552/580] mark an api version to prevent a meaningless console warning ( #80 ) --- src/main/resources/plugin.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 09070516..c00cafa1 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,5 +1,6 @@ name: AdvancedBackups version: ${version} +api-version: '1.21' main: computer.heather.AdvancedBackups.AdvancedBackups commands: backup: From d611ec60a9f86d1658431e65f6d31deb6b68b998 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 20 Aug 2024 21:34:12 +0100 Subject: [PATCH 553/580] dep bump to fix compile issue --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 48490876..d7dc4f7b 100644 --- a/build.gradle +++ b/build.gradle @@ -33,7 +33,7 @@ configurations { } dependencies { - compileOnly("org.spigotmc:spigot:1.21-R0.1-SNAPSHOT:remapped-mojang") + compileOnly("org.spigotmc:spigot:1.21.1-R0.1-SNAPSHOT:remapped-mojang") implementation files ('advancedbackups-corelib.jar') extraLibs files ('advancedbackups-corelib.jar') From 9da74e86c5e36a4a7939d02f0caedf2f0dd95cfe Mon Sep 17 00:00:00 2001 From: Heather White <66441550+MommyHeather@users.noreply.github.com> Date: Tue, 20 Aug 2024 21:42:49 +0100 Subject: [PATCH 554/580] take 2 at fixing the compiletime issue --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index d7dc4f7b..023ec5e9 100644 --- a/build.gradle +++ b/build.gradle @@ -73,7 +73,7 @@ tasks.named('jar', Jar).configure { tasks { remap { - version.set("1.21") + version.set("1.21.1") } build { dependsOn(remap) From a7f18b2a56e26baa4ea9feb63f27a377a91264e9 Mon Sep 17 00:00:00 2001 From: HoldYourWaffle Date: Tue, 3 Sep 2024 04:38:02 +0200 Subject: [PATCH 555/580] Give each project a unique name Avoids various kinds of nightmareish shenanigans... --- fabric/1.18/settings.gradle | 4 +++- fabric/1.19.2/settings.gradle | 4 +++- fabric/1.19.3/settings.gradle | 4 +++- fabric/1.20.2/settings.gradle | 4 +++- fabric/1.20.6/settings.gradle | 4 +++- fabric/1.20/settings.gradle | 4 +++- fabric/1.21/settings.gradle | 4 +++- forge/1.12/settings.gradle | 2 ++ forge/1.16/settings.gradle | 1 + forge/1.18/settings.gradle | 1 + forge/1.19.2/settings.gradle | 4 +++- forge/1.19.3/settings.gradle | 4 +++- forge/1.20.2/settings.gradle | 4 +++- forge/1.20.6/settings.gradle | 4 +++- forge/1.20/settings.gradle | 4 +++- forge/1.7.10/settings.gradle.kts | 2 ++ neoforge/1.20.2/settings.gradle | 4 +++- neoforge/1.20.4/settings.gradle | 4 +++- neoforge/1.20.6/settings.gradle | 4 +++- neoforge/1.21/settings.gradle | 4 +++- spigot/1.21/settings.gradle | 6 +----- 21 files changed, 55 insertions(+), 21 deletions(-) create mode 100644 forge/1.16/settings.gradle create mode 100644 forge/1.18/settings.gradle diff --git a/fabric/1.18/settings.gradle b/fabric/1.18/settings.gradle index 56266b41..1665c3ba 100644 --- a/fabric/1.18/settings.gradle +++ b/fabric/1.18/settings.gradle @@ -7,4 +7,6 @@ pluginManagement { mavenCentral() gradlePluginPortal() } -} \ No newline at end of file +} + +rootProject.name = 'fabric-1.18' diff --git a/fabric/1.19.2/settings.gradle b/fabric/1.19.2/settings.gradle index 56266b41..33093018 100644 --- a/fabric/1.19.2/settings.gradle +++ b/fabric/1.19.2/settings.gradle @@ -7,4 +7,6 @@ pluginManagement { mavenCentral() gradlePluginPortal() } -} \ No newline at end of file +} + +rootProject.name = 'fabric-1.19.2' diff --git a/fabric/1.19.3/settings.gradle b/fabric/1.19.3/settings.gradle index 56266b41..535da8f0 100644 --- a/fabric/1.19.3/settings.gradle +++ b/fabric/1.19.3/settings.gradle @@ -7,4 +7,6 @@ pluginManagement { mavenCentral() gradlePluginPortal() } -} \ No newline at end of file +} + +rootProject.name = 'fabric-1.19.3' diff --git a/fabric/1.20.2/settings.gradle b/fabric/1.20.2/settings.gradle index 56266b41..369e988c 100644 --- a/fabric/1.20.2/settings.gradle +++ b/fabric/1.20.2/settings.gradle @@ -7,4 +7,6 @@ pluginManagement { mavenCentral() gradlePluginPortal() } -} \ No newline at end of file +} + +rootProject.name = 'fabric-1.20.2' diff --git a/fabric/1.20.6/settings.gradle b/fabric/1.20.6/settings.gradle index 75c4d726..ad70fbd7 100644 --- a/fabric/1.20.6/settings.gradle +++ b/fabric/1.20.6/settings.gradle @@ -7,4 +7,6 @@ pluginManagement { mavenCentral() gradlePluginPortal() } -} \ No newline at end of file +} + +rootProject.name = 'fabric-1.20.6' diff --git a/fabric/1.20/settings.gradle b/fabric/1.20/settings.gradle index 56266b41..df54f372 100644 --- a/fabric/1.20/settings.gradle +++ b/fabric/1.20/settings.gradle @@ -7,4 +7,6 @@ pluginManagement { mavenCentral() gradlePluginPortal() } -} \ No newline at end of file +} + +rootProject.name = 'fabric-1.20' diff --git a/fabric/1.21/settings.gradle b/fabric/1.21/settings.gradle index 75c4d726..d8266a5a 100644 --- a/fabric/1.21/settings.gradle +++ b/fabric/1.21/settings.gradle @@ -7,4 +7,6 @@ pluginManagement { mavenCentral() gradlePluginPortal() } -} \ No newline at end of file +} + +rootProject.name = 'fabric-1.21' diff --git a/forge/1.12/settings.gradle b/forge/1.12/settings.gradle index 45230aa9..24ae1cb2 100644 --- a/forge/1.12/settings.gradle +++ b/forge/1.12/settings.gradle @@ -6,3 +6,5 @@ pluginManagement { } } } + +rootProject.name = 'forge-1.12' diff --git a/forge/1.16/settings.gradle b/forge/1.16/settings.gradle new file mode 100644 index 00000000..7175fd71 --- /dev/null +++ b/forge/1.16/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'forge-1.16' diff --git a/forge/1.18/settings.gradle b/forge/1.18/settings.gradle new file mode 100644 index 00000000..8def20d2 --- /dev/null +++ b/forge/1.18/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'forge-1.18' diff --git a/forge/1.19.2/settings.gradle b/forge/1.19.2/settings.gradle index 3703f364..f7c14937 100644 --- a/forge/1.19.2/settings.gradle +++ b/forge/1.19.2/settings.gradle @@ -3,4 +3,6 @@ pluginManagement { gradlePluginPortal() maven { url = 'https://maven.minecraftforge.net/' } } -} \ No newline at end of file +} + +rootProject.name = 'forge-1.19.2' diff --git a/forge/1.19.3/settings.gradle b/forge/1.19.3/settings.gradle index 3703f364..8ead78fa 100644 --- a/forge/1.19.3/settings.gradle +++ b/forge/1.19.3/settings.gradle @@ -3,4 +3,6 @@ pluginManagement { gradlePluginPortal() maven { url = 'https://maven.minecraftforge.net/' } } -} \ No newline at end of file +} + +rootProject.name = 'forge-1.19.3' diff --git a/forge/1.20.2/settings.gradle b/forge/1.20.2/settings.gradle index 291d399d..808294b0 100644 --- a/forge/1.20.2/settings.gradle +++ b/forge/1.20.2/settings.gradle @@ -10,4 +10,6 @@ pluginManagement { plugins { id 'org.gradle.toolchains.foojay-resolver-convention' version '0.5.0' -} \ No newline at end of file +} + +rootProject.name = 'forge-1.20.2' diff --git a/forge/1.20.6/settings.gradle b/forge/1.20.6/settings.gradle index 93f1b806..8e6fd9be 100644 --- a/forge/1.20.6/settings.gradle +++ b/forge/1.20.6/settings.gradle @@ -10,4 +10,6 @@ pluginManagement { plugins { id 'org.gradle.toolchains.foojay-resolver-convention' version '0.7.0' -} \ No newline at end of file +} + +rootProject.name = 'forge-1.20.6' diff --git a/forge/1.20/settings.gradle b/forge/1.20/settings.gradle index 24584e97..359817e6 100644 --- a/forge/1.20/settings.gradle +++ b/forge/1.20/settings.gradle @@ -10,4 +10,6 @@ pluginManagement { plugins { id 'org.gradle.toolchains.foojay-resolver-convention' version '0.5.0' -} \ No newline at end of file +} + +rootProject.name = 'forge-1.20' diff --git a/forge/1.7.10/settings.gradle.kts b/forge/1.7.10/settings.gradle.kts index 6456ce87..456eead8 100644 --- a/forge/1.7.10/settings.gradle.kts +++ b/forge/1.7.10/settings.gradle.kts @@ -22,3 +22,5 @@ plugins { // Automatic toolchain provisioning id("org.gradle.toolchains.foojay-resolver-convention") version "0.4.0" } + +rootProject.name = "forge-1.7.10" diff --git a/neoforge/1.20.2/settings.gradle b/neoforge/1.20.2/settings.gradle index 24584e97..bb205047 100644 --- a/neoforge/1.20.2/settings.gradle +++ b/neoforge/1.20.2/settings.gradle @@ -10,4 +10,6 @@ pluginManagement { plugins { id 'org.gradle.toolchains.foojay-resolver-convention' version '0.5.0' -} \ No newline at end of file +} + +rootProject.name = 'neoforge-1.20.2' diff --git a/neoforge/1.20.4/settings.gradle b/neoforge/1.20.4/settings.gradle index 24584e97..8a8f11cf 100644 --- a/neoforge/1.20.4/settings.gradle +++ b/neoforge/1.20.4/settings.gradle @@ -10,4 +10,6 @@ pluginManagement { plugins { id 'org.gradle.toolchains.foojay-resolver-convention' version '0.5.0' -} \ No newline at end of file +} + +rootProject.name = 'neoforge-1.20.4' diff --git a/neoforge/1.20.6/settings.gradle b/neoforge/1.20.6/settings.gradle index 24584e97..cf03de4a 100644 --- a/neoforge/1.20.6/settings.gradle +++ b/neoforge/1.20.6/settings.gradle @@ -10,4 +10,6 @@ pluginManagement { plugins { id 'org.gradle.toolchains.foojay-resolver-convention' version '0.5.0' -} \ No newline at end of file +} + +rootProject.name = 'neoforge-1.20.6' diff --git a/neoforge/1.21/settings.gradle b/neoforge/1.21/settings.gradle index fd1434c1..69e7ddc0 100644 --- a/neoforge/1.21/settings.gradle +++ b/neoforge/1.21/settings.gradle @@ -8,4 +8,6 @@ pluginManagement { plugins { id 'org.gradle.toolchains.foojay-resolver-convention' version '0.8.0' -} \ No newline at end of file +} + +rootProject.name = 'neoforge-1.21' diff --git a/spigot/1.21/settings.gradle b/spigot/1.21/settings.gradle index 54eff0fd..204e49e0 100644 --- a/spigot/1.21/settings.gradle +++ b/spigot/1.21/settings.gradle @@ -1,5 +1 @@ -/* - * This file was generated by the Gradle 'init' task. - */ - -rootProject.name = 'AdvancedBackups' \ No newline at end of file +rootProject.name = 'spigot-1.21' From c4966c01a8bcc81f91ecded68e12e531b3d878de Mon Sep 17 00:00:00 2001 From: HoldYourWaffle Date: Tue, 3 Sep 2024 04:27:51 +0100 Subject: [PATCH 556/580] Fix line endings --- .gitattributes | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.gitattributes b/.gitattributes index afd59d8f..3e0f77cc 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,8 +1,9 @@ # # https://help.github.com/articles/dealing-with-line-endings/ # -# Linux start script should use lf -/gradlew text eol=lf +# Linux shell scripts should use lf +gradlew text eol=lf +*.sh text eol=lf # These are Windows script files and should use crlf *.bat text eol=crlf From 1e16b88892b0508f1af1bc613a6447703f0f0ed4 Mon Sep 17 00:00:00 2001 From: HoldYourWaffle Date: Tue, 3 Sep 2024 05:37:44 +0200 Subject: [PATCH 557/580] Regenerate gradle wrappers --- core/gradle/wrapper/gradle-wrapper.jar | Bin 60756 -> 63721 bytes core/gradle/wrapper/gradle-wrapper.properties | 2 + core/gradlew | 41 ++- core/gradlew.bat | 92 ++++++ fabric/1.20.2/gradlew | 8 +- .../1.20.6/gradle/wrapper/gradle-wrapper.jar | Bin 63721 -> 43453 bytes .../gradle/wrapper/gradle-wrapper.properties | 1 - fabric/1.20.6/gradlew | 22 +- fabric/1.20.6/gradlew.bat | 20 +- fabric/1.21/gradle/wrapper/gradle-wrapper.jar | Bin 63721 -> 43453 bytes .../gradle/wrapper/gradle-wrapper.properties | 1 - fabric/1.21/gradlew | 24 +- fabric/1.21/gradlew.bat | 20 +- forge/1.12/gradle/wrapper/gradle-wrapper.jar | Bin 54708 -> 60756 bytes .../gradle/wrapper/gradle-wrapper.properties | 2 +- forge/1.12/gradlew | 286 +++++++++++------- forge/1.12/gradlew.bat | 91 ++++++ forge/1.18/gradle/wrapper/gradle-wrapper.jar | Bin 59536 -> 60756 bytes forge/1.18/gradlew | 16 +- forge/1.18/gradlew.bat | 91 ++++++ forge/1.19.2/gradlew.bat | 91 ++++++ .../1.19.3/gradle/wrapper/gradle-wrapper.jar | Bin 60756 -> 62076 bytes .../gradle/wrapper/gradle-wrapper.properties | 1 + forge/1.19.3/gradlew | 19 +- forge/1.19.3/gradlew.bat | 92 ++++++ .../1.20.2/gradle/wrapper/gradle-wrapper.jar | Bin 61574 -> 62076 bytes forge/1.20.2/gradlew | 11 +- forge/1.20.2/gradlew.bat | 92 ++++++ .../1.20.6/gradle/wrapper/gradle-wrapper.jar | Bin 61574 -> 43453 bytes .../gradle/wrapper/gradle-wrapper.properties | 1 + forge/1.20.6/gradlew | 29 +- forge/1.20.6/gradlew.bat | 92 ++++++ forge/1.20/gradle/wrapper/gradle-wrapper.jar | Bin 61574 -> 62076 bytes forge/1.20/gradlew | 11 +- forge/1.20/gradlew.bat | 92 ++++++ .../1.20.2/gradle/wrapper/gradle-wrapper.jar | Bin 61574 -> 62076 bytes neoforge/1.20.2/gradlew | 11 +- neoforge/1.20.2/gradlew.bat | 92 ++++++ .../1.20.4/gradle/wrapper/gradle-wrapper.jar | Bin 61574 -> 62076 bytes neoforge/1.20.4/gradlew | 11 +- neoforge/1.20.4/gradlew.bat | 92 ++++++ .../1.20.6/gradle/wrapper/gradle-wrapper.jar | Bin 61574 -> 43453 bytes .../gradle/wrapper/gradle-wrapper.properties | 1 + neoforge/1.20.6/gradlew | 29 +- neoforge/1.20.6/gradlew.bat | 20 +- .../1.21/gradle/wrapper/gradle-wrapper.jar | Bin 61574 -> 43453 bytes .../gradle/wrapper/gradle-wrapper.properties | 1 + neoforge/1.21/gradlew | 29 +- neoforge/1.21/gradlew.bat | 20 +- 49 files changed, 1300 insertions(+), 254 deletions(-) create mode 100644 core/gradlew.bat create mode 100644 forge/1.12/gradlew.bat create mode 100644 forge/1.18/gradlew.bat create mode 100644 forge/1.19.2/gradlew.bat create mode 100644 forge/1.19.3/gradlew.bat create mode 100644 forge/1.20.2/gradlew.bat create mode 100644 forge/1.20.6/gradlew.bat create mode 100644 forge/1.20/gradlew.bat create mode 100644 neoforge/1.20.2/gradlew.bat create mode 100644 neoforge/1.20.4/gradlew.bat diff --git a/core/gradle/wrapper/gradle-wrapper.jar b/core/gradle/wrapper/gradle-wrapper.jar index 249e5832f090a2944b7473328c07c9755baa3196..7f93135c49b765f8051ef9d0a6055ff8e46073d8 100644 GIT binary patch delta 44091 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 F{tsc4gtPzv delta 41205 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 jFA#1K+D2e>Q|zP /dev/null && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -133,22 +131,29 @@ location of your Java installation." fi else JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac case $MAX_FD in #( '' | soft) :;; #( *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -193,6 +198,10 @@ if "$cygwin" || "$msys" ; then done fi + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + # Collect all arguments for the java command; # * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of # shell script including quotes and variable substitutions, so put them in @@ -205,6 +214,12 @@ set -- \ org.gradle.wrapper.GradleWrapperMain \ "$@" +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + # Use "xargs" to parse quoted args. # # With -n1 it outputs one arg per line, with the quotes and backslashes removed. diff --git a/core/gradlew.bat b/core/gradlew.bat new file mode 100644 index 00000000..93e3f59f --- /dev/null +++ b/core/gradlew.bat @@ -0,0 +1,92 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/fabric/1.20.2/gradlew b/fabric/1.20.2/gradlew index aeb74cbb..0adc8e1a 100644 --- a/fabric/1.20.2/gradlew +++ b/fabric/1.20.2/gradlew @@ -83,7 +83,8 @@ done # This is normally unused # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -130,10 +131,13 @@ location of your Java installation." fi else JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. diff --git a/fabric/1.20.6/gradle/wrapper/gradle-wrapper.jar b/fabric/1.20.6/gradle/wrapper/gradle-wrapper.jar index 7f93135c49b765f8051ef9d0a6055ff8e46073d8..e6441136f3d4ba8a0da8d277868979cfbc8ad796 100644 GIT binary patch literal 43453 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 yu?e%!_ptzGB|8GrCfu%p?(_ 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
NnX)EH+Nua)3Y(c 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鯊%1Et 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⁢ zv5o9#E7!G0XmdzfsS{efPNi`1b44~SZ4Z8fuX!I}#8g+(wxzQwUT#Xb2(tbY1+EUhGKoT@KEU9Ktl>_0 z%bjDJg;#*gtJZv!-Zs`?^}v5eKmnbjqlvnSzE@_SP|LG_PJ6CYU+6zY6>92%E+ z=j@TZf-iW4(%U{lnYxQA;7Q!b;^brF8n0D>)`q5>|WDDXLrqYU_tKN2>=#@~OE7grMnNh?UOz-O~6 z6%rHy{#h9K0AT+lDC7q4{hw^|q6*Ry;;L%Q@)Ga}$60_q%D)rv(CtS$CQbpq9|y1e zRSrN4;$Jyl{m5bZw`$8TGvb}(LpY{-cQ)fcyJv7l3S52TLXVDsphtv&aPuDk1OzCA z4A^QtC(!11`IsNx_HnSy?>EKpHJWT^wmS~hc^p^zIIh@9f6U@I2 zC=Mve{j2^)mS#U$e{@Q?SO6%LDsXz@SY+=cK_QMmXBIU)j!$ajc-zLx3V60EXJ!qC zi<%2x8Q24YN+&8U@CIlN zrZkcT9yh%LrlGS9`G)KdP(@9Eo-AQz@8GEFWcb7U=a0H^ZVbLmz{+&M7W(nXJ4sN8 zJLR7eeK(K8`2-}j(T7JsO`L!+CvbueT%izanm-^A1Dn{`1Nw`9P?cq;7no+XfC`K(GO9?O^5zNIt4M+M8LM0=7Gz8UA@Z0N+lg+cX)NfazRu z5D)~HA^(u%w^cz+@2@_#S|u>GpB+j4KzQ^&Wcl9f z&hG#bCA(Yk0D&t&aJE^xME^&E-&xGHhXn%}psEIj641H+Nl-}boj;)Zt*t(4wZ5DN z@GXF$bL=&pBq-#vkTkh>7hl%K5|3 z{`Vn9b$iR-SoGENp}bn4;fR3>9sA%X2@1L3aE9yTra;Wb#_`xWwLSLdfu+PAu+o3| zGVnpzPr=ch{uuoHjtw7+_!L_2;knQ!DuDl0R`|%jr+}jFzXtrHIKc323?JO{l&;VF z*L1+}JU7%QJOg|5|Tc|D8fN zJORAg=_vsy{ak|o);@)Yh8Lkcg@$FG3k@ep36BRa^>~UmnRPziS>Z=`Jb2x*Q#`%A zU*i3&Vg?TluO@X0O;r2Jl6LKLUOVhSqg1*qOt^|8*c7 zo(298@+r$k_wQNGHv{|$tW(T8L+4_`FQ{kEW5Jgg{yf7ey4ss_(SNKfz(N9lx&a;< je(UuV8hP?p&}TPdm1I$XmG#(RzlD&B2izSj9sl%y5~4qc diff --git a/fabric/1.20.6/gradle/wrapper/gradle-wrapper.properties b/fabric/1.20.6/gradle/wrapper/gradle-wrapper.properties index 62131dfd..b82aa23a 100644 --- a/fabric/1.20.6/gradle/wrapper/gradle-wrapper.properties +++ b/fabric/1.20.6/gradle/wrapper/gradle-wrapper.properties @@ -1,4 +1,3 @@ -#Fri May 10 17:19:51 BST 2024 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip diff --git a/fabric/1.20.6/gradlew b/fabric/1.20.6/gradlew index aeb74cbb..1aa94a42 100644 --- a/fabric/1.20.6/gradlew +++ b/fabric/1.20.6/gradlew @@ -83,7 +83,8 @@ done # This is normally unused # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -130,10 +131,13 @@ location of your Java installation." fi else JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. @@ -141,7 +145,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -149,7 +153,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -198,11 +202,11 @@ fi # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ diff --git a/fabric/1.20.6/gradlew.bat b/fabric/1.20.6/gradlew.bat index 93e3f59f..25da30db 100644 --- a/fabric/1.20.6/gradlew.bat +++ b/fabric/1.20.6/gradlew.bat @@ -43,11 +43,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -57,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail diff --git a/fabric/1.21/gradle/wrapper/gradle-wrapper.jar b/fabric/1.21/gradle/wrapper/gradle-wrapper.jar index 7f93135c49b765f8051ef9d0a6055ff8e46073d8..e6441136f3d4ba8a0da8d277868979cfbc8ad796 100644 GIT binary patch literal 43453 zcma&N1CXTcmMvW9vTb(Rwr$&4wr$(C?dmSu>@vG-+vuvg^_??!{yS%8zW-#zn-LkA z5&1^$^{lnmUON?}LBF8_K|(?T0Ra(xUH{($5eN!MR#ZihR#HxkUPe+_R8Cn`RRs(P z_^*#_XlXmGv7!4;*Y%p4nw?{bNp@UZHv1?Um8r6)Fei3p@ClJn0ECfg1hkeuUU@Or zDaPa;U3fE=3L}DooL;8f;P0ipPt0Z~9P0)lbStMS)ag54=uL9ia-Lm3nh|@(Y?B`; zx_#arJIpXH!U{fbCbI^17}6Ri*H<>OLR%c|^mh8+)*h~K8Z!9)DPf zR2h?lbDZQ`p9P;&DQ4F0sur@TMa!Y}S8irn(%d-gi0*WxxCSk*A?3lGh=gcYN?FGl z7D=Js!i~0=u3rox^eO3i@$0=n{K1lPNU zwmfjRVmLOCRfe=seV&P*1Iq=^i`502keY8Uy-WNPwVNNtJFx?IwAyRPZo2Wo1+S(xF37LJZ~%i)kpFQ3Fw=mXfd@>%+)RpYQLnr}B~~zoof(JVm^^&f zxKV^+3D3$A1G;qh4gPVjhrC8e(VYUHv#dy^)(RoUFM?o%W-EHxufuWf(l*@-l+7vt z=l`qmR56K~F|v<^Pd*p~1_y^P0P^aPC##d8+HqX4IR1gu+7w#~TBFphJxF)T$2WEa zxa?H&6=Qe7d(#tha?_1uQys2KtHQ{)Qco)qwGjrdNL7thd^G5i8Os)CHqc>iOidS} z%nFEDdm=GXBw=yXe1W-ShHHFb?Cc70+$W~z_+}nAoHFYI1MV1wZegw*0y^tC*s%3h zhD3tN8b=Gv&rj}!SUM6|ajSPp*58KR7MPpI{oAJCtY~JECm)*m_x>AZEu>DFgUcby z1Qaw8lU4jZpQ_$;*7RME+gq1KySGG#Wql>aL~k9tLrSO()LWn*q&YxHEuzmwd1?aAtI zBJ>P=&$=l1efe1CDU;`Fd+_;&wI07?V0aAIgc(!{a z0Jg6Y=inXc3^n!U0Atk`iCFIQooHqcWhO(qrieUOW8X(x?(RD}iYDLMjSwffH2~tB z)oDgNBLB^AJBM1M^c5HdRx6fBfka`(LD-qrlh5jqH~);#nw|iyp)()xVYak3;Ybik z0j`(+69aK*B>)e_p%=wu8XC&9e{AO4c~O1U`5X9}?0mrd*m$_EUek{R?DNSh(=br# z#Q61gBzEpmy`$pA*6!87 zSDD+=@fTY7<4A?GLqpA?Pb2z$pbCc4B4zL{BeZ?F-8`s$?>*lXXtn*NC61>|*w7J* z$?!iB{6R-0=KFmyp1nnEmLsA-H0a6l+1uaH^g%c(p{iT&YFrbQ$&PRb8Up#X3@Zsk zD^^&LK~111%cqlP%!_gFNa^dTYT?rhkGl}5=fL{a`UViaXWI$k-UcHJwmaH1s=S$4 z%4)PdWJX;hh5UoK?6aWoyLxX&NhNRqKam7tcOkLh{%j3K^4Mgx1@i|Pi&}<^5>hs5 zm8?uOS>%)NzT(%PjVPGa?X%`N2TQCKbeH2l;cTnHiHppPSJ<7y-yEIiC!P*ikl&!B z%+?>VttCOQM@ShFguHVjxX^?mHX^hSaO_;pnyh^v9EumqSZTi+#f&_Vaija0Q-e*| z7ulQj6Fs*bbmsWp{`auM04gGwsYYdNNZcg|ph0OgD>7O}Asn7^Z=eI>`$2*v78;sj-}oMoEj&@)9+ycEOo92xSyY344^ z11Hb8^kdOvbf^GNAK++bYioknrpdN>+u8R?JxG=!2Kd9r=YWCOJYXYuM0cOq^FhEd zBg2puKy__7VT3-r*dG4c62Wgxi52EMCQ`bKgf*#*ou(D4-ZN$+mg&7$u!! z-^+Z%;-3IDwqZ|K=ah85OLwkO zKxNBh+4QHh)u9D?MFtpbl)us}9+V!D%w9jfAMYEb>%$A;u)rrI zuBudh;5PN}_6J_}l55P3l_)&RMlH{m!)ai-i$g)&*M`eN$XQMw{v^r@-125^RRCF0 z^2>|DxhQw(mtNEI2Kj(;KblC7x=JlK$@78`O~>V!`|1Lm-^JR$-5pUANAnb(5}B}JGjBsliK4& zk6y(;$e&h)lh2)L=bvZKbvh@>vLlreBdH8No2>$#%_Wp1U0N7Ank!6$dFSi#xzh|( zRi{Uw%-4W!{IXZ)fWx@XX6;&(m_F%c6~X8hx=BN1&q}*( zoaNjWabE{oUPb!Bt$eyd#$5j9rItB-h*5JiNi(v^e|XKAj*8(k<5-2$&ZBR5fF|JA z9&m4fbzNQnAU}r8ab>fFV%J0z5awe#UZ|bz?Ur)U9bCIKWEzi2%A+5CLqh?}K4JHi z4vtM;+uPsVz{Lfr;78W78gC;z*yTch~4YkLr&m-7%-xc ztw6Mh2d>_iO*$Rd8(-Cr1_V8EO1f*^@wRoSozS) zy1UoC@pruAaC8Z_7~_w4Q6n*&B0AjOmMWa;sIav&gu z|J5&|{=a@vR!~k-OjKEgPFCzcJ>#A1uL&7xTDn;{XBdeM}V=l3B8fE1--DHjSaxoSjNKEM9|U9#m2<3>n{Iuo`r3UZp;>GkT2YBNAh|b z^jTq-hJp(ebZh#Lk8hVBP%qXwv-@vbvoREX$TqRGTgEi$%_F9tZES@z8Bx}$#5eeG zk^UsLBH{bc2VBW)*EdS({yw=?qmevwi?BL6*=12k9zM5gJv1>y#ML4!)iiPzVaH9% zgSImetD@dam~e>{LvVh!phhzpW+iFvWpGT#CVE5TQ40n%F|p(sP5mXxna+Ev7PDwA zamaV4m*^~*xV+&p;W749xhb_X=$|LD;FHuB&JL5?*Y2-oIT(wYY2;73<^#46S~Gx| z^cez%V7x$81}UWqS13Gz80379Rj;6~WdiXWOSsdmzY39L;Hg3MH43o*y8ibNBBH`(av4|u;YPq%{R;IuYow<+GEsf@R?=@tT@!}?#>zIIn0CoyV!hq3mw zHj>OOjfJM3F{RG#6ujzo?y32m^tgSXf@v=J$ELdJ+=5j|=F-~hP$G&}tDZsZE?5rX ztGj`!S>)CFmdkccxM9eGIcGnS2AfK#gXwj%esuIBNJQP1WV~b~+D7PJTmWGTSDrR` zEAu4B8l>NPuhsk5a`rReSya2nfV1EK01+G!x8aBdTs3Io$u5!6n6KX%uv@DxAp3F@{4UYg4SWJtQ-W~0MDb|j-$lwVn znAm*Pl!?Ps&3wO=R115RWKb*JKoexo*)uhhHBncEDMSVa_PyA>k{Zm2(wMQ(5NM3# z)jkza|GoWEQo4^s*wE(gHz?Xsg4`}HUAcs42cM1-qq_=+=!Gk^y710j=66(cSWqUe zklbm8+zB_syQv5A2rj!Vbw8;|$@C!vfNmNV!yJIWDQ>{+2x zKjuFX`~~HKG~^6h5FntRpnnHt=D&rq0>IJ9#F0eM)Y-)GpRjiN7gkA8wvnG#K=q{q z9dBn8_~wm4J<3J_vl|9H{7q6u2A!cW{bp#r*-f{gOV^e=8S{nc1DxMHFwuM$;aVI^ zz6A*}m8N-&x8;aunp1w7_vtB*pa+OYBw=TMc6QK=mbA-|Cf* zvyh8D4LRJImooUaSb7t*fVfih<97Gf@VE0|z>NcBwBQze);Rh!k3K_sfunToZY;f2 z^HmC4KjHRVg+eKYj;PRN^|E0>Gj_zagfRbrki68I^#~6-HaHg3BUW%+clM1xQEdPYt_g<2K+z!$>*$9nQ>; zf9Bei{?zY^-e{q_*|W#2rJG`2fy@{%6u0i_VEWTq$*(ZN37|8lFFFt)nCG({r!q#9 z5VK_kkSJ3?zOH)OezMT{!YkCuSSn!K#-Rhl$uUM(bq*jY? zi1xbMVthJ`E>d>(f3)~fozjg^@eheMF6<)I`oeJYx4*+M&%c9VArn(OM-wp%M<-`x z7sLP1&3^%Nld9Dhm@$3f2}87!quhI@nwd@3~fZl_3LYW-B?Ia>ui`ELg z&Qfe!7m6ze=mZ`Ia9$z|ARSw|IdMpooY4YiPN8K z4B(ts3p%2i(Td=tgEHX z0UQ_>URBtG+-?0E;E7Ld^dyZ;jjw0}XZ(}-QzC6+NN=40oDb2^v!L1g9xRvE#@IBR zO!b-2N7wVfLV;mhEaXQ9XAU+>=XVA6f&T4Z-@AX!leJ8obP^P^wP0aICND?~w&NykJ#54x3_@r7IDMdRNy4Hh;h*!u(Ol(#0bJdwEo$5437-UBjQ+j=Ic>Q2z` zJNDf0yO6@mr6y1#n3)s(W|$iE_i8r@Gd@!DWDqZ7J&~gAm1#~maIGJ1sls^gxL9LLG_NhU!pTGty!TbhzQnu)I*S^54U6Yu%ZeCg`R>Q zhBv$n5j0v%O_j{QYWG!R9W?5_b&67KB$t}&e2LdMvd(PxN6Ir!H4>PNlerpBL>Zvyy!yw z-SOo8caEpDt(}|gKPBd$qND5#a5nju^O>V&;f890?yEOfkSG^HQVmEbM3Ugzu+UtH zC(INPDdraBN?P%kE;*Ae%Wto&sgw(crfZ#Qy(<4nk;S|hD3j{IQRI6Yq|f^basLY; z-HB&Je%Gg}Jt@={_C{L$!RM;$$|iD6vu#3w?v?*;&()uB|I-XqEKqZPS!reW9JkLewLb!70T7n`i!gNtb1%vN- zySZj{8-1>6E%H&=V}LM#xmt`J3XQoaD|@XygXjdZ1+P77-=;=eYpoEQ01B@L*a(uW zrZeZz?HJsw_4g0vhUgkg@VF8<-X$B8pOqCuWAl28uB|@r`19DTUQQsb^pfqB6QtiT z*`_UZ`fT}vtUY#%sq2{rchyfu*pCg;uec2$-$N_xgjZcoumE5vSI{+s@iLWoz^Mf; zuI8kDP{!XY6OP~q5}%1&L}CtfH^N<3o4L@J@zg1-mt{9L`s^z$Vgb|mr{@WiwAqKg zp#t-lhrU>F8o0s1q_9y`gQNf~Vb!F%70f}$>i7o4ho$`uciNf=xgJ>&!gSt0g;M>*x4-`U)ysFW&Vs^Vk6m%?iuWU+o&m(2Jm26Y(3%TL; zA7T)BP{WS!&xmxNw%J=$MPfn(9*^*TV;$JwRy8Zl*yUZi8jWYF>==j~&S|Xinsb%c z2?B+kpet*muEW7@AzjBA^wAJBY8i|#C{WtO_or&Nj2{=6JTTX05}|H>N2B|Wf!*3_ z7hW*j6p3TvpghEc6-wufFiY!%-GvOx*bZrhZu+7?iSrZL5q9}igiF^*R3%DE4aCHZ zqu>xS8LkW+Auv%z-<1Xs92u23R$nk@Pk}MU5!gT|c7vGlEA%G^2th&Q*zfg%-D^=f z&J_}jskj|Q;73NP4<4k*Y%pXPU2Thoqr+5uH1yEYM|VtBPW6lXaetokD0u z9qVek6Q&wk)tFbQ8(^HGf3Wp16gKmr>G;#G(HRBx?F`9AIRboK+;OfHaLJ(P>IP0w zyTbTkx_THEOs%Q&aPrxbZrJlio+hCC_HK<4%f3ZoSAyG7Dn`=X=&h@m*|UYO-4Hq0 z-Bq&+Ie!S##4A6OGoC~>ZW`Y5J)*ouaFl_e9GA*VSL!O_@xGiBw!AF}1{tB)z(w%c zS1Hmrb9OC8>0a_$BzeiN?rkPLc9%&;1CZW*4}CDDNr2gcl_3z+WC15&H1Zc2{o~i) z)LLW=WQ{?ricmC`G1GfJ0Yp4Dy~Ba;j6ZV4r{8xRs`13{dD!xXmr^Aga|C=iSmor% z8hi|pTXH)5Yf&v~exp3o+sY4B^^b*eYkkCYl*T{*=-0HniSA_1F53eCb{x~1k3*`W zr~};p1A`k{1DV9=UPnLDgz{aJH=-LQo<5%+Em!DNN252xwIf*wF_zS^!(XSm(9eoj z=*dXG&n0>)_)N5oc6v!>-bd(2ragD8O=M|wGW z!xJQS<)u70m&6OmrF0WSsr@I%T*c#Qo#Ha4d3COcX+9}hM5!7JIGF>7<~C(Ear^Sn zm^ZFkV6~Ula6+8S?oOROOA6$C&q&dp`>oR-2Ym3(HT@O7Sd5c~+kjrmM)YmgPH*tL zX+znN>`tv;5eOfX?h{AuX^LK~V#gPCu=)Tigtq9&?7Xh$qN|%A$?V*v=&-2F$zTUv z`C#WyIrChS5|Kgm_GeudCFf;)!WH7FI60j^0o#65o6`w*S7R@)88n$1nrgU(oU0M9 zx+EuMkC>(4j1;m6NoGqEkpJYJ?vc|B zOlwT3t&UgL!pX_P*6g36`ZXQ; z9~Cv}ANFnJGp(;ZhS(@FT;3e)0)Kp;h^x;$*xZn*k0U6-&FwI=uOGaODdrsp-!K$Ac32^c{+FhI-HkYd5v=`PGsg%6I`4d9Jy)uW0y%) zm&j^9WBAp*P8#kGJUhB!L?a%h$hJgQrx!6KCB_TRo%9{t0J7KW8!o1B!NC)VGLM5! zpZy5Jc{`r{1e(jd%jsG7k%I+m#CGS*BPA65ZVW~fLYw0dA-H_}O zrkGFL&P1PG9p2(%QiEWm6x;U-U&I#;Em$nx-_I^wtgw3xUPVVu zqSuKnx&dIT-XT+T10p;yjo1Y)z(x1fb8Dzfn8e yu?e%!_ptzGB|8GrCfu%p?(_ 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
NnX)EH+Nua)3Y(c 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鯊%1Et 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⁢ zv5o9#E7!G0XmdzfsS{efPNi`1b44~SZ4Z8fuX!I}#8g+(wxzQwUT#Xb2(tbY1+EUhGKoT@KEU9Ktl>_0 z%bjDJg;#*gtJZv!-Zs`?^}v5eKmnbjqlvnSzE@_SP|LG_PJ6CYU+6zY6>92%E+ z=j@TZf-iW4(%U{lnYxQA;7Q!b;^brF8n0D>)`q5>|WDDXLrqYU_tKN2>=#@~OE7grMnNh?UOz-O~6 z6%rHy{#h9K0AT+lDC7q4{hw^|q6*Ry;;L%Q@)Ga}$60_q%D)rv(CtS$CQbpq9|y1e zRSrN4;$Jyl{m5bZw`$8TGvb}(LpY{-cQ)fcyJv7l3S52TLXVDsphtv&aPuDk1OzCA z4A^QtC(!11`IsNx_HnSy?>EKpHJWT^wmS~hc^p^zIIh@9f6U@I2 zC=Mve{j2^)mS#U$e{@Q?SO6%LDsXz@SY+=cK_QMmXBIU)j!$ajc-zLx3V60EXJ!qC zi<%2x8Q24YN+&8U@CIlN zrZkcT9yh%LrlGS9`G)KdP(@9Eo-AQz@8GEFWcb7U=a0H^ZVbLmz{+&M7W(nXJ4sN8 zJLR7eeK(K8`2-}j(T7JsO`L!+CvbueT%izanm-^A1Dn{`1Nw`9P?cq;7no+XfC`K(GO9?O^5zNIt4M+M8LM0=7Gz8UA@Z0N+lg+cX)NfazRu z5D)~HA^(u%w^cz+@2@_#S|u>GpB+j4KzQ^&Wcl9f z&hG#bCA(Yk0D&t&aJE^xME^&E-&xGHhXn%}psEIj641H+Nl-}boj;)Zt*t(4wZ5DN z@GXF$bL=&pBq-#vkTkh>7hl%K5|3 z{`Vn9b$iR-SoGENp}bn4;fR3>9sA%X2@1L3aE9yTra;Wb#_`xWwLSLdfu+PAu+o3| zGVnpzPr=ch{uuoHjtw7+_!L_2;knQ!DuDl0R`|%jr+}jFzXtrHIKc323?JO{l&;VF z*L1+}JU7%QJOg|5|Tc|D8fN zJORAg=_vsy{ak|o);@)Yh8Lkcg@$FG3k@ep36BRa^>~UmnRPziS>Z=`Jb2x*Q#`%A zU*i3&Vg?TluO@X0O;r2Jl6LKLUOVhSqg1*qOt^|8*c7 zo(298@+r$k_wQNGHv{|$tW(T8L+4_`FQ{kEW5Jgg{yf7ey4ss_(SNKfz(N9lx&a;< je(UuV8hP?p&}TPdm1I$XmG#(RzlD&B2izSj9sl%y5~4qc diff --git a/fabric/1.21/gradle/wrapper/gradle-wrapper.properties b/fabric/1.21/gradle/wrapper/gradle-wrapper.properties index e80153ee..a4413138 100644 --- a/fabric/1.21/gradle/wrapper/gradle-wrapper.properties +++ b/fabric/1.21/gradle/wrapper/gradle-wrapper.properties @@ -1,4 +1,3 @@ -#Fri May 10 17:19:51 BST 2024 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip diff --git a/fabric/1.21/gradlew b/fabric/1.21/gradlew index aeb74cbb..b740cf13 100644 --- a/fabric/1.21/gradlew +++ b/fabric/1.21/gradlew @@ -55,7 +55,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -83,7 +83,8 @@ done # This is normally unused # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -130,10 +131,13 @@ location of your Java installation." fi else JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. @@ -141,7 +145,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -149,7 +153,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -198,11 +202,11 @@ fi # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ diff --git a/fabric/1.21/gradlew.bat b/fabric/1.21/gradlew.bat index 93e3f59f..25da30db 100644 --- a/fabric/1.21/gradlew.bat +++ b/fabric/1.21/gradlew.bat @@ -43,11 +43,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -57,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail diff --git a/forge/1.12/gradle/wrapper/gradle-wrapper.jar b/forge/1.12/gradle/wrapper/gradle-wrapper.jar index 7a3265ee94c0ab25cf079ac8ccdf87f41d455d42..249e5832f090a2944b7473328c07c9755baa3196 100644 GIT binary patch literal 60756 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

_x$+l{{cH8$W#CT diff --git a/forge/1.12/gradle/wrapper/gradle-wrapper.properties b/forge/1.12/gradle/wrapper/gradle-wrapper.properties index 0e9a6105..8049c684 100644 --- a/forge/1.12/gradle/wrapper/gradle-wrapper.properties +++ b/forge/1.12/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip diff --git a/forge/1.12/gradlew b/forge/1.12/gradlew index cccdd3d5..a69d9cb6 100644 --- a/forge/1.12/gradlew +++ b/forge/1.12/gradlew @@ -1,78 +1,129 @@ -#!/usr/bin/env sh +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ############################################################################## -## -## Gradle start up script for UN*X -## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# ############################################################################## # Attempt to set APP_HOME + # Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` +APP_BASE_NAME=${0##*/} # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -81,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" + JAVACMD=java which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the @@ -89,84 +140,101 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=$((i+1)) + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=$(save "$@") - -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" - -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" fi +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + exec "$JAVACMD" "$@" diff --git a/forge/1.12/gradlew.bat b/forge/1.12/gradlew.bat new file mode 100644 index 00000000..f127cfd4 --- /dev/null +++ b/forge/1.12/gradlew.bat @@ -0,0 +1,91 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/forge/1.18/gradle/wrapper/gradle-wrapper.jar b/forge/1.18/gradle/wrapper/gradle-wrapper.jar index 7454180f2ae8848c63b8b4dea2cb829da983f2fa..249e5832f090a2944b7473328c07c9755baa3196 100644 GIT binary patch delta 10158 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 delta 9041 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 diff --git a/forge/1.18/gradlew b/forge/1.18/gradlew index c53aefaa..a69d9cb6 100644 --- a/forge/1.18/gradlew +++ b/forge/1.18/gradlew @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright © 2015-2021 the original authors. +# Copyright © 2015-2021 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -32,10 +32,10 @@ # Busybox and similar reduced shells will NOT work, because this script # requires all of these POSIX shell features: # * functions; -# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», -# «${var#prefix}», «${var%suffix}», and «$( cmd )»; -# * compound commands having a testable exit status, especially «case»; -# * various built-in commands including «command», «set», and «ulimit». +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». # # Important for patching: # @@ -205,6 +205,12 @@ set -- \ org.gradle.wrapper.GradleWrapperMain \ "$@" +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + # Use "xargs" to parse quoted args. # # With -n1 it outputs one arg per line, with the quotes and backslashes removed. diff --git a/forge/1.18/gradlew.bat b/forge/1.18/gradlew.bat new file mode 100644 index 00000000..f127cfd4 --- /dev/null +++ b/forge/1.18/gradlew.bat @@ -0,0 +1,91 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/forge/1.19.2/gradlew.bat b/forge/1.19.2/gradlew.bat new file mode 100644 index 00000000..f127cfd4 --- /dev/null +++ b/forge/1.19.2/gradlew.bat @@ -0,0 +1,91 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/forge/1.19.3/gradle/wrapper/gradle-wrapper.jar b/forge/1.19.3/gradle/wrapper/gradle-wrapper.jar index 249e5832f090a2944b7473328c07c9755baa3196..c1962a79e29d3e0ab67b14947c167a862655af9b 100644 GIT binary patch delta 39834 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 G$^QWPgI3l6 delta 38507 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 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/forge/1.20.2/gradle/wrapper/gradle-wrapper.jar b/forge/1.20.2/gradle/wrapper/gradle-wrapper.jar index 943f0cbfa754578e88a3dae77fce6e3dea56edbf..c1962a79e29d3e0ab67b14947c167a862655af9b 100644 GIT binary patch delta 13895 zcmZ8|Wmp``)-~=Hdu)0n3Y-8OvyK$p9^s9MM|Aj$miotNhy-{udLczZyd9uWtD)X_{|!LhIEF9y8(e*Z zW>^w$u&x|i9OjL=#6Nl~*ERulzX>8C-}o;iSMRYdfCU5d`~U{V4>HCg0HG4Xg2uP;fn!>S9+>LbuWbc0bETMQfo9~h}yI*TSv;Oikl~t-+xqI-`P$Rj@yi{mr2zC~s1snMT3!OPBdJ%IDnPXq+pl*Z>=+?qo${lkCSKmwTlVjfb3thU6B8yFjr!tphOs*G6 zwL`RyVAUXj4p=9&@PpWK)m+REuvHaq838TEhY^7W+JAp$ zZ^y;8`Z*@VqJ{sFFj?<|7SKS@G`$Yi)gx%nOi@Lr zCv0IJlFz0bP(eDIW(uWNq?;8zEAb+uGgnkLk;y!4XhA6=Eoa<`+|;6mOq>z`%ir@z$4)Mkd3 zF=hFo zyd{*bRQ4YUe^bU*Y`__)Uhu5NIjVJ~a}{lHp-_7wI?#EB11XcqmdY>pk`JJ) zW9Rt!tK=N>fZ!UDomwMnb`0EOvTjcNl=yW@$c!OAg*=l()GjZwSyJ+o^;Zi#I5*uP z$6qeih8&g8E(pNSneK>93A(8*%gvwv!0V|SqGcj55Y7`=N*@pJx_ig3uVuf-G~LJbm`7nxNcZ>Jgqy(LTHu_C2e>STp^Pm{}f&^)XU}vzuU`UV&>e& zqsXNXSs;Wri|?NhCq0vXC5$>9Cag$adyWz^x@NCiy2${9Dc)Y;J8k1Z933W$3$H}g zCQFU1XwzGm_WUheXvnDisH_%BdzMgNwk2^mHcQu*x>U%iN*B^8U(eVz1~(%`kV1Vb z=9T0xmN?bQMyrrd?u}jer}zV&sCK6zSm!zV8A8dP6THF=4*V{_K*E*K<)I(Q^(eV!m!vu##-2g|G z{RB;{gJB_X-w{ANq?ft_n!@=O8_gj6FxW&zO$7L3@NjWt@R{NxMbpHLk6;=2$0P5P=kKc1_85inX z#s$&s0zhV1cz>nRb#|D#N8Z-=Tphm)sGH>9cz3K3I)6XpimJW0(6$GtLzN(YPu9%R zdFXG9|30AZME4r@joC0IdvBBe08mF@+5Dd97p$h=n|pi80Cn2n{ev!S$llPGLqHva zZ3*OmW%!Qj>C$F!Ffafl7#I_1(gz!aa)b{ebU*=yH%^kr=~N?|2&2Df2o9X=2B?U!#R#+Cj45=f@=EcQx+9J z=X3~A=zbX29Fqn23m3dm}0Voj^Q9BjI=MiG+NZ)YCYn@r^qv(xE3=)&i z=(ML301=rNTptvUt2tnsPb1~G*DWFWoZfv)wV|uNW%?!)jju`jN(K-0$JYi!ofNup z9K%_ucHwutbZsl~vDQ!Jtj8uI6WA6K--@?8+_=t>g|kgUeC=w`IP9m&*fuoO3#A;t z&3@=3;J0>yjM89?h5MG$S`wW+=vyYOWQGhIP`^vScM8^JL{mGan5uTJPvAg$0z}8; z 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 J*WbtZ{{Z#P!zlm& delta 13442 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 diff --git a/forge/1.20.2/gradlew b/forge/1.20.2/gradlew index 65dcd68d..aeb74cbb 100644 --- a/forge/1.20.2/gradlew +++ b/forge/1.20.2/gradlew @@ -85,9 +85,6 @@ done APP_BASE_NAME=${0##*/} APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' - # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -144,7 +141,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -152,7 +149,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -197,6 +194,10 @@ if "$cygwin" || "$msys" ; then done fi + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + # Collect all arguments for the java command; # * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of # shell script including quotes and variable substitutions, so put them in diff --git a/forge/1.20.2/gradlew.bat b/forge/1.20.2/gradlew.bat new file mode 100644 index 00000000..93e3f59f --- /dev/null +++ b/forge/1.20.2/gradlew.bat @@ -0,0 +1,92 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/forge/1.20.6/gradle/wrapper/gradle-wrapper.jar b/forge/1.20.6/gradle/wrapper/gradle-wrapper.jar index 943f0cbfa754578e88a3dae77fce6e3dea56edbf..e6441136f3d4ba8a0da8d277868979cfbc8ad796 100644 GIT binary patch literal 43453 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 yu?e%!_ptzGB|8GrCfu%p?(_ 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

NnX)EH+Nua)3Y(c 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 ScNgau(U?ep-K_E5zy1%ZQTdPn diff --git a/forge/1.20.6/gradle/wrapper/gradle-wrapper.properties b/forge/1.20.6/gradle/wrapper/gradle-wrapper.properties index 20db9ad5..b82aa23a 100644 --- a/forge/1.20.6/gradle/wrapper/gradle-wrapper.properties +++ b/forge/1.20.6/gradle/wrapper/gradle-wrapper.properties @@ -2,5 +2,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/forge/1.20.6/gradlew b/forge/1.20.6/gradlew index 65dcd68d..1aa94a42 100644 --- a/forge/1.20.6/gradlew +++ b/forge/1.20.6/gradlew @@ -83,10 +83,8 @@ done # This is normally unused # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -133,10 +131,13 @@ location of your Java installation." fi else JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. @@ -144,7 +145,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -152,7 +153,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -197,11 +198,15 @@ if "$cygwin" || "$msys" ; then done fi -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ diff --git a/forge/1.20.6/gradlew.bat b/forge/1.20.6/gradlew.bat new file mode 100644 index 00000000..25da30db --- /dev/null +++ b/forge/1.20.6/gradlew.bat @@ -0,0 +1,92 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/forge/1.20/gradle/wrapper/gradle-wrapper.jar b/forge/1.20/gradle/wrapper/gradle-wrapper.jar index 943f0cbfa754578e88a3dae77fce6e3dea56edbf..c1962a79e29d3e0ab67b14947c167a862655af9b 100644 GIT binary patch delta 13895 zcmZ8|Wmp``)-~=Hdu)0n3Y-8OvyK$p9^s9MM|Aj$miotNhy-{udLczZyd9uWtD)X_{|!LhIEF9y8(e*Z zW>^w$u&x|i9OjL=#6Nl~*ERulzX>8C-}o;iSMRYdfCU5d`~U{V4>HCg0HG4Xg2uP;fn!>S9+>LbuWbc0bETMQfo9~h}yI*TSv;Oikl~t-+xqI-`P$Rj@yi{mr2zC~s1snMT3!OPBdJ%IDnPXq+pl*Z>=+?qo${lkCSKmwTlVjfb3thU6B8yFjr!tphOs*G6 zwL`RyVAUXj4p=9&@PpWK)m+REuvHaq838TEhY^7W+JAp$ zZ^y;8`Z*@VqJ{sFFj?<|7SKS@G`$Yi)gx%nOi@Lr zCv0IJlFz0bP(eDIW(uWNq?;8zEAb+uGgnkLk;y!4XhA6=Eoa<`+|;6mOq>z`%ir@z$4)Mkd3 zF=hFo zyd{*bRQ4YUe^bU*Y`__)Uhu5NIjVJ~a}{lHp-_7wI?#EB11XcqmdY>pk`JJ) zW9Rt!tK=N>fZ!UDomwMnb`0EOvTjcNl=yW@$c!OAg*=l()GjZwSyJ+o^;Zi#I5*uP z$6qeih8&g8E(pNSneK>93A(8*%gvwv!0V|SqGcj55Y7`=N*@pJx_ig3uVuf-G~LJbm`7nxNcZ>Jgqy(LTHu_C2e>STp^Pm{}f&^)XU}vzuU`UV&>e& zqsXNXSs;Wri|?NhCq0vXC5$>9Cag$adyWz^x@NCiy2${9Dc)Y;J8k1Z933W$3$H}g zCQFU1XwzGm_WUheXvnDisH_%BdzMgNwk2^mHcQu*x>U%iN*B^8U(eVz1~(%`kV1Vb z=9T0xmN?bQMyrrd?u}jer}zV&sCK6zSm!zV8A8dP6THF=4*V{_K*E*K<)I(Q^(eV!m!vu##-2g|G z{RB;{gJB_X-w{ANq?ft_n!@=O8_gj6FxW&zO$7L3@NjWt@R{NxMbpHLk6;=2$0P5P=kKc1_85inX z#s$&s0zhV1cz>nRb#|D#N8Z-=Tphm)sGH>9cz3K3I)6XpimJW0(6$GtLzN(YPu9%R zdFXG9|30AZME4r@joC0IdvBBe08mF@+5Dd97p$h=n|pi80Cn2n{ev!S$llPGLqHva zZ3*OmW%!Qj>C$F!Ffafl7#I_1(gz!aa)b{ebU*=yH%^kr=~N?|2&2Df2o9X=2B?U!#R#+Cj45=f@=EcQx+9J z=X3~A=zbX29Fqn23m3dm}0Voj^Q9BjI=MiG+NZ)YCYn@r^qv(xE3=)&i z=(ML301=rNTptvUt2tnsPb1~G*DWFWoZfv)wV|uNW%?!)jju`jN(K-0$JYi!ofNup z9K%_ucHwutbZsl~vDQ!Jtj8uI6WA6K--@?8+_=t>g|kgUeC=w`IP9m&*fuoO3#A;t z&3@=3;J0>yjM89?h5MG$S`wW+=vyYOWQGhIP`^vScM8^JL{mGan5uTJPvAg$0z}8; z zhMi+S${H#^wF;eU-0UHJDo$QwXDjm{ns>^ltubKXtd>6Bq-=ByF%bHu>2&e&uZj2X zgWIq(l^;Ab7#I@h%#j1AtBIkB`GO*y!i;1K+_SZ-p}4jmP7#%E-=>{ zK(3*ObyAgDLnbBLObTWJWNO7<60SK6*!dD~_7JOWTB*}(*X)ox0{lq5ac$ABkcL~0 z9qCHT8^`QIe_4-BW&mIe*&0VT6w|oJ9hnOO&oZUe!rP+gStQ)h5ZPhBprHZI;So+g5}&;adp<|7#r@DG!wXmtwdwy=7i>a`x1D4 z_N$0`Q)>zTVUU%@RzlG=4Nk1hE=_klWj|6aj`KJ@S`y^%bifkdX`s!A#|mpM-x;SF zg;bju5cA0?a}%hk=3AL^#2B>5X(TSne6PDWY5gRVvn6nKl;vg?SIbv^Uz=+4aPUft z-$}QR)+_U?eX*p)V0%#0@S46_6c($OJL^bPj0Ij}up8}In#GQa&Cp<#%ZPjx(^97{ z8AfEgrNRTg-l9WJrNJzHx1EkI<|n(P3VIwFlTvMxfe=V&NL)4MubdHqZF)&Eq4`+% z7z;>s(sjUsebUfFF;~)_%@3BDl8i085o$H!*yBv%Z27d~)|jfg4DhJ&nMb((B#4hOfeBhL)g+r)f%2be?s2ox zT3j0k+Va^9`gqO)FoUV@F|((*vGxN>?5IlvC!BzW-8cyCy_)Fl8W+eg<&Lz^s>dJx zkly@2Xzzi9Uf%|1pF_Nz-3SgOx*+ShK(x=XUlP?;EfoDqAkkwyR*yjIcD#7-@=|Um z{T+V}q`6)wnSO#*N#Hp8QT7^>6R+H^_o4LBc}$aD^@(1!+Y54YF3@A|Cupsfz@Wt8 z!KwmSb9}3l)u^Y+V6W6(bL3hk;XTY4FNy3hKhID#Ep#xLM88?`xT=lw3xsgN;gKK@ zqpElV*j#e;{w`OPYcb1_szKUtRLygjq2ldhGJ$8ksyH(hF%^w`&FH|zlDK`DfuZ_g zs}!{hMk^~48&b=jWqG2*^m8?ERreHIw8dgR`Ugj*t4Uo`^U*56MmU<^ zNxcuRh+Kc2>W~lzD8S6}Xho3s9f}{o4@tIc)G;lKXi(HJhZV{qSH1-xj>P2$NHEK2 z)TjOy%>(9Ot_zPO)^tp@AsSNd+`R?}_2Vd>=eT{G&TfITkeW@p{F+FTJf(n87##z& z!%w+6-!NJ*?9Z(hbZv^BG$Y1`BOo~*k7jaZ)9%@;H6F+W!Q%IV4qSM85; z0%xWZi_wc=CCc>2rd3Rk3C79_rJH1uG?yFIm4f6Fdmts<41T*;3ek&p z3(NaDK3iIDa)MaUD{_;~fMV6obrT6_K$c+eeRBJ7jd)c%0jldoJX`EWz8M$b1s|DS z)cr6)em!+P%GjM6uQb6CQ!FvUb%_>qbKn=gHl=@K-Z*6_VaD=;!?P9pr$Z?6NrB%a zb_G4M-UkkhI>H@+kP;eS4p->q_f+&(R^7hyRsS9Xl94vA^AYlM%tdNdHQz zFQu?Rau!C@&&Dn;i5iEhn3`y>{O-m^_*h+Jp6C?D+5yn9Vq5XVQoUe#BP3}lqvHa} z@x~UctaNE9PwnRg6+15NJ5k(PC0dETm#QxXY6&uTqupm)GVrsvKC9o)&*mLo9?$Ot z!SFjh+!mr{kYE5A#urFIBv?<(6-HtqfprK#3H4dylz5j`Uc)Hz@1}A9OXe=4gf3_- z$P|^SpeQ89xlL`pftC^4tO3N)JXTqmkbruGAsraU5Y$fyMd~L3r3t8-SfkX{n4<`@ zhBKAeBP_1Rd8q`<3^dio2W9^9iYW?#m-!IKDO7ge{vC%1Y>dWLslyLNrm-!*YU3Dy ze|qm9gwdCJKZlwcvaoV%S_%X-k_?QIf2zuAG&32WtJ6NDr0i+<{w;CG_St&I_7HtR zTiR;!)_1iw&#FKwAGFuBze6(_%DLu?>|K(H5bf{br_f5|#qa zNOuJQhSU1PGQ+dltC{ik3sA?PcKcDJg;_^-LCcLGo+|3VsWx0vMNOpKz3*U1wGG0{Z@O=3gt1Ay|67ZJC zGe%Q2bP}rYtE^Lc+ybPES@Snxwlh7Ydq$c{H?d&8e>!Dvt=dFxeS0fvt=u3$KHuU; zKHr9fCbGGQBeJ~@{wdgJi6Ah40fcT>yGRWEe)%=j!AaG~XDaHNdzsU6*ZJ2XC5>lv z=IT$K4yEi0xt7i<^=rn-$1nOKKRQZ$7df4uU#`?ddlH+Oo~+H_Zq!-}6VK;|?PGiI zhbt$ffNJ|--Bn6(L{pZ#!&ykjgBXEs%hmxg3vB~;GMKcAfeq~#2~f9vw7{>?pTu{T zcxLiHNCP}pJ_fYl3^gBy_}h~U`lx1^?)q|U1cti6s?Nt*RvSgF6WD8U%3uk zwC7lEPg``Bjt5YXNFE!^nq zJC-z}n^zNvd{jVhiv9aKNd}lH0$n97EBjb`Fh+7~amqAtrK{@Sn3QZO3BBiUIo^n$ zsiS{+L+8B0e&`mFnEqM!LCLnzlclx?UwZ(L6!FZ$b53#xA2caP^zn&!GVtipn{W`U zvN9yG-?@6)3`HYt>E;wO*N_UGd``TDMJ+e<*WUe$SGeaBU)dJHbvUp$J?}caKfP>U znZQtJY@$~+#6FOn9R6m86Sq3iiaaWa3kiz1k>ntIk2*6R+6gchFxKLcBi9EMRVQrl zP~vO=WAFX7o6BB76*mwH?R^-5HX?KAu`a^Eplkmc zSXpmBvQ4t(kVfyQIR#|Wi7PYcy+x;(5j|LOp3()IiR>2j9**}<*nO2NiED?Z;)iGh&PH4nB*kN{VVt!lYX*(jAlnZkabB{Fa7)iF?pBFk(T+)xyg(Y5TUd;DX&MX&_}`_=Z_KcQ9;Ok=&YEqPyVul9sRG%P!*byO8nRS# zGwOm?IyLaeqMf=7AGF{L7v%GKmeM+;#U;vPs0=0R1WAo2JIq8N`PGDe}Q zt6VP!Fqln^U#5ZJFp?b?d*Q}Ynd3Q)jTU;{RwiqDncXA=DXTWhkWhiR{XF9aobJH{ zEYYt-`Hdwp@ZQ5$_i&f`=DA1D>lgJ>_PkLE6#)L#3R1Giq@XA zCLtGAgOI35<3Y-&55pCx#&@_R?w|x@%3$Q-X|@=Zhuo`C@cOG0@M*&sW@uXQJz-M; z=ZcUIw+bXwCV+k?WF;Ugyrm6gy8KjZmaobl;Omt^`!m*(!@&}j)uCT=+}RbLo7WiC zM*7VJG5hnkugII&>R-Jyx<}$pNBtEizA`Gn{GbTy^WPi*o!^5_gH8ME&+{<}nBbSA*p<6A z{c--0SNgk{iH@g2s&K3L#wl5fR-H5$YrMAEA$gwfPC&GdtAb=bUk$?Md6^mdF&^vj z+iAp=tz8ZK>*?)QgEVBG?CnAb`($wf9*1w->8@)hg(hpH^%IFjGqTs7<*jz0J-*C! zs)=j2cA@=KgS0+*LX^Qe*))69yFm;(i`r6`?_p2Dfi!AQh43;ix#Kv8_*W|IsGg;f zJ=0%L||IPz~u^1P?ZkuO7VD7>GEfT=K*2JP!?hLF1f0rSkXpoIojW`}iLv zt$qt5Kd$Ty5UwS~N|w!IW4-TDG6g9!ecEoE+JUM(=T{d4yASY8>tlDG_XdEUinvXN zl>XB_*;iM^53IG90-1uxg#z{ov9M-y`(|4~g#J?dVQ&7tJ+a=N9npjr(_lb@G$v24 zPeA4UfgSFXLSe$Ghn!^hh)2|+YuV|~a}U+Y9iy?b*TKn*`y{ADmlq%d|HzJn0mW<0 z5McIquX})(09`s?@%4OLy)I^TdiKP=%}XfT`s{oX5eauP0FS#ZH3$bT&E#E)1%_v48Kc&JbnK@KR+fCJ+WWg`;cXecj9ij8zP$MV%S9InmL z#D$p6%KIKx&U;|#5fPg~KlH~fC7Sh-(Ut}5+tSSriumK>DDF&sl2pa_A|~tu_*8aY z(*Ud4=(+k5;ke&7V(y`$@j|FGqk0(WA5Wc(N${j@=7U}Xs^XNgK(<|>qug3-b1T3( z0=#Hgj}+TLlDhVm<>&!j$jvWXm6SLkMW&2k+;_u9Tq#<8uKtToJ3Q^==VQ0eV{+r6 zQn5p9xfHk@%P_FbqYM3DFnxUSXF^sk#Ms{)T4quYP`fK;T+Tj&gRl6sm|74UbHHrF z7h!QzEST^cpRO6L8_~zXNp!niGl&79$k_8RSj0W{xMrR)D4`>~tNrK~*s0gkO-PC^ zu^*~aOBQF>qG>`%KGd+7W{nGqd5lc0%E_*&rn?MObfYvgPvJ%vawv{il#Km=$-hF* z1V^<{OA_t~X|u>{5ljynGhf844dJ#q31&xuibhPgP;6z{C2qw67U617_1*$=(_{mu z@T$|cK0GIz9sS4`1VcT=#Rqfsfiwbly-A61ih$VWK@T{K(t%VCA4=VJ4(eT` zLP`DnbAKO!X02C>qoh6kk2SEE|nQ8^J~0S)XyHMI1`BA+8Q-{{y-|Sc=j6N9xVnV z3^giq-U}tR!`_$ty{geQQ}xVo!CwzlXx}-}k2&VU3u7n@(1G0xP$36j1GKVJtLydS zm|^pz&9wE!Q>OWGMLY+Y?=$lIM$IKdF`8Pw)uhzhmFGtIyWl(qh0C@9BbzwDR>rEa z2gc62w3u1cW+De8tCw(3SQ8EK+t9l|ef|)GLRlRJz>SleVh^o zSq>XS(iJr>IQL-5^9LMn-MBxnO*FN{K2{7JVUpW5nZ{sz&_Z(dXDW?G7lmn%1nU|B zqC_R`=83Y=g^uel37AnfplTx)W_%O1pY@^^#~MgJg`0^G07b7RHOA>7K6Vzom_M3= zbD)3(BXXoqR6UFGHM9a3uK)SxX-0%jvKG23)#s6{vbq>#o$1tZMI5hU1c`fGME7#Ij+u%*rdsnO7yaltUc zz)OZMW*a=_Q|k2CFQ+lR%Md1Kd~``A8LX7vMtOupY7HV^E*;7o5$|Yq;EZjl%s-BLWa)nM| zOY1bfH5&%ed5t0h_`z*>GNiXhoMBw9+W7 z4U!O;)Tz3n;x64wHcYoivoslIkj9IN05|H7X~GWEx-k619Z-KjWv%8@$1wbIvAFfI z0=AQoH{3yl1z|`pSg$(!>x0)nU|wT@4i`lCchm_nrU@Y;XR$D^5wA!Ftl}*9OwXFZ zai&Zh_YNnlz=LEccY_eUXOEY1;q&Pd;dLtf$RffP4%P#4ZyIjV&0;_13^ zIVGMUzx+5jLyq55_Qz0jPBx~-{DfuUW)hKduk1gv0et-e(ZN8;IIdhtV$3N9Bg((Q zw5eHG)FFs=ewUwfdHfvHb$&&i=h{#epIdWr+=YE9)%453DlIOHLFX;%dv2LDNMrMZ zEWU|CvEYY*(2SE$Y{jAd$QU-wd*Hbe5yO+Lu6Ux|(Y>L}E_jNPR+TX@Ch(#orbP8g zv+Z(oKz1gylHHGKB*FbdpSh7VBM2KVmx2oj>?q8|s72`}5s)jT=s4;lbRw$cKh+N{ zVTxW`s~QW~rRB;e|7pxFoJ_Vm^eVjcddUh0Xp(NhCBZ@Uya;(x_wkvyH*^ds{2_H? zs*PV?33(>MyJC_<)JC=|9II5@I`QnNGgZr z5AfQVuy5}nzXlGQGV~eESn9UcL_U$gw(QjDVEW4b-o=BQGBT*a$1Fk+4bm2n^6m6w z_hn7X46IDL7iQZ8s+_(8yX!fXqM9htq_Ts}08b%snTZMmP}{6(anfizqhpR1cR61k z=sfzRN*!0HP{Z76PDg%PUY)rjwhuy71^5D3f^bR;(fQe>3U#zrWwe0OSYjHZ-eSJV zuKnE7`~*u%-HShx%*b9ZPU~(Rg=`lQI$;iBY#2k^6{Ef6e9D&EK^irorXEpE!h=>^ zVxH#pyrndMgk)Ff-ke*RFsPY@B3AM_;Kj`PIJU@EH^QsIUo1wdl_wfqd48O^9?06@ zt*>img{+gG%WiGU+&V)`jeJUPSDDLhd#nVrUr~dURh(&O#gMnA0dEg-#?fg0Wnp#P z;4QjL{Fv?Unq!!)POdN%ZI&vU*Ww};bqd3@5fb_<7mIa_w@U?X&ed5f1FCQ@57aR@ z)TUphLPht{?j%;+T}Sfla?uiG26R^?7=x!#CUXw+$_TQx_%vLhgg8LVJz@{QVxH;M zGcV^6&Z%`yWalhb>$VS`{^Ex`w@cldtZ8t!!exC zu+Msuk)M-ylAjAz8{yA&TjgR`O%H1H0T&$<*+K{2-<~=1E0~C+w@CzUg>GyIegmx$ z$vp-I6CygcS8Jm9rR{Wt@W?<)IdIk##3DUE741Dg@lQ~Lskm-7=|2%)&XCF_8|780 z9d-AgO*4e1uf}M3*FGo&%&eG;OB^Vm_x8i73V3P?d^qdJMvO&{H(jgc?n6UYZ>-FU zeO%|qJ%xvB;o+$e+CHm+Ot1UgzOrX7_G!pZrt%?TaOs9ZPg>i>-gg^Vuu6p>LEd99 zGlCZbE5(oNfEP{~x>KfOZv6XWA8zfk0@R+{;r7WV?(wWFRaGkg&mR3j$wJa7CBWz= znwfnWiE^@dC=n6jrAY4vvH*;b5{E#wK8AoUW`vT3W+8gyt9<*hPl1ID>F3bkLniI?`*u@J2zcd_cAH2?L5O|qzu1jQs$J^g9=beD zYoEgyA^AIv!P%D3;3T_C#zm7j6=+ACjtf5->)lXATb2p>g%qD7L1EbTMh(z$4oMY) zSZft;+pfN?a7x#%4}(P3Q)Gvt1F^8eu9}_PDW&}_2hhqjF#&SGUnz^`=V(U{;B;`G zt7FmRinElmq%KVXaBZL$+hD> zLe`*wO^B_i5W9q8#>l8J4;5{XbZg#@Z9|D|{gN8}jF1XBNzpi*9R3+-F)w8EbJ~In zEdim4jC?)`IzcZ1_`5oBWd#yPJNc%ajkte>^q1KY$#LzK)`jz_7$%1`N1_tdhr^wG zp92GvW>iDG)!1`I3*Y3;C)Jz7**nV;DaO_d19A_8qX%OCf-KY-GEZ#Nv;2CZQ*ht5 zY`vXc7yAb|?h#Z_dEKDC)Wp}g7hJDlI>P+ctKoq`U4!4az+ECGUSGmfHRpW&m_%7? z(o7gajY+w(Le-L(_Al|yQIvl1gk&lX-5BMZn=+~n-N}$`J#2x5x&B1EG{drVp+i;- zucW)%=6bqw%wNB|=k!-_k($v{gQB1ZX`dn0tu@(Z7b0$g5k88nHYIEE zT{wBh?|8X1yS1ITl!hS_>>{cobd%i3<#)=amBnHn>p;m6f%!T!BSP{_9DL_Wmv{PtyL9hoTep$i_uAr>^@7u^a($-HJh2k0xNsYVmt|v+kCWusAE%8~f zgZeq1{C!DL z7|_)gsX-J$DBwOYs|TpK6>I&l2*#dm_B%7y(JCJ?jaOVZJg!;eleEd~bT^pJkrk>q zB4)r!XRL!mow*tX6z6JA){(LgKapsISwxE@P|Hy&;*5I17ktf2EQSu$>0G&bDc^|D zoB?VpoqIQzg72DO!zOL#jXEsFWVZoyX*Q+>cyNC5+bi$(-R z2PXnAH)~j-X7q#KV*r7K0Tj#Pt=_Ix!xQizqfxG}vfg*swPul)E%ElLW)2B0BOb4U z$5{w|1BT44k;f7uS&T@0UH_mBvgr?Q_m;tun8!5sqbDu3_a@H76e`xzggnje$~Vo7 za$jN9vO%&+?c(NFBWd(HH(c*Tf3txzhrnp4X1859WXnbk!aVPy#xl`hJYOb;9$6q{ zkbx6NHJ;r$;+CoL5@BT|)P$#Nd4mLhJ?! z#V8L2#1$FDnc_k5#=YeMy9&SHkG_wJOT1g%-w$u1eta|QD44f{Y&WqiWW218tS?qy z$ZDkAwNCgrzLY?-u2WO8%SB`AO_vLdwg{s)2>YT(Vp}$u)h6yDPl(o)wFGQ6GTv9!92`>rC_Xgn9)BKfMk>B0lFK$_ux zk^my^G@g^?|Ds?LnEwzyJ7qzahke+uzE$SE-IhBwTL zCnKg33>Lk_tsV;Q?3Nd07IG)>PA43Q@@bD_XViZuJnF+-SR9eSm-b^YbLCU7PG6GQ zJKkO|*b;^O^%Ehg6e-0+bze&Un{k(1?Aom@b7Sm z?b{}WJ!Zfj23oRMKPiLEh^qy6lZ(sff1?M#aP;~C;P0@AuUam$iHH$i(Zc-_8++)) zGiB*fRHaTE_*K_lAl+<$IklN{WiruTjZ?Ir>rocinb-6%~rZb)Z@l>WsZ%cVnF`u(k z3MC-R0(^u8vlUE{9TX~VYef_B+y~v-T`n!_ zJXHL4N_pJy{bQGCGEJ2vO`^5M=(MU>=QoaiN4n$ZmlEhRRC09~b|CV#QExkR{!cxv z-Ih(Yq);JB({7Iv5SqD14A&CD>{9d#mQfp_-1nX*824hiHi&jI!rbzk3^mafyBi2I zXwJzh@J~^n^Qq+Rev`}V%T)Pds`2QDUxGv4pkJOaJP+l=87o}7L-RV1V*p70%Q?kQJ!b+v(*=vXQsHF z#w&NkJNb4_Kvu6hrx0e1Q_pLru87EM%Rez`mTlk~vCAr;IKZqQ$#>gK{ZQNJ$F@r9 z17m<_yD6oKG?O@e`O;WsIhdWwE)Z7*SyABxHvKJ!x|y(wVq*Eg`D2Q%Q#&zSm8c_X zY`zJhB88q%6!2%9%}+RQMhWH=sbw#8{a(embAwu zeRHhkOtBY=U&ubKu7vS#2DPzJ+WbaUn%Eu`p1cjDEU*&qFGKE(o%RZ13w1x?o_-#{ zj3y3uOaJI8nlJ`Rt11>dUer4~gzlg1qwk_n+`w_Q&I230F}#e<84l6$Ub}ga5BLCy z$uT-aXsHnb5x(Q2(qiSxMHMrLS5E#p#t6L)COeA@Vy#t82W3I7zxNN*jGG$^^A3V~ zTr=^dD(liTi!S&uFU(~grGKHPJ3#7Wm91!jh!*X-6-6}Q?cA`2ld(6Q{A_nw+16`p zBq**{Pk_!LEyI8)FurdbBN-IqyhFR52Y9f)rE-#p}V=M?A%c$M#J3kjR;+GEA#vBv7ig$61YKjN2FsuXxl6YE;g-oLfc3d7ixb z(~0wjUXzRlz7@}MhgnS+FRey=b`F|l<3w;qodOa{(-yU^k{7Owq0>0sq7~my3O9?# z;MqUiGm}Q%_f`tMUWXlWG>uF0_?>-d_6ru!DNoiMD&X~fg!7a0H9Z%=3kwQs-Q1{g zxIsDbEXG9ly4o5M4LODy_vvf8k1Dey9QW4T^up55&l zkpg05cG;FhOyo7R#xy!3{&xPzXTpzSZpRkB&$uR(?99to5LDHD?ak+~^R*OGg2wFv zUjX`1J0_eHXV^8UJXLSFxSNPlDSRKCJ@A^Jrtp08!98KQXBT1L%avWTv-8l?va+Jq zHqd)|JwByFcmK%afGyJ=rb@ELtB7tehaH#)iRz5v6?C;mDxZj)`upc|y>)S)VveGb zj?RG?$-D;ms{Mi9UTajprUthRTIksl=OfjZ8iD{zhh{YOLQV$~PKQE~HHn!A-`+on zR*Vi4Qpbff5whUZ9dr@0UMy^6)_zH48Tiz-RM+T2vk9}rr*_Wy-CfoxGjcedo-{zF zI=^!G@*UT_@;VTiU+I>Ht{NTo^Dj&T`?{QK>&9s}PXt=TxQbmKUDW->h6Eh)@|}uY zfxqy8(^9cw%+k#m9NNz`x+UB*DrrBVuFm%-eo5kp!74OI^qtOcOgmD z8KADRYxrHr>DeRsuJG&}MumPmOimcRYf)HcNZ@n+9Z>VwI;H|{kuzD-~H{S8;hQ?c2 zjtv0GZ}PmMOMCz*ca!f8t!=)0eIWsWjJ71-P|23{TZz8yg7Kf_uYY%rfKs-#-mI6~ zWDtv=K%3NLAnu*Falh$e$sp$0L0w!lpwgZ9QTM+QD_m~`Hwd`>zEy>8mki>B7c|Ao z1M1j$C*t3TL;k-)g!W*N|5no|$$~>*LSlkyga9DKJp_ntp?@6S+sqXOyh(8W{uKnw zfCBb--`KW2G6-skzsABWLHJMO%+dg)|G1h+znMw@zb^du$snNhKu5aNu>aTVhA9Aa zypI5ZZuUl#f&d5a@?81@G6)V!kn(}ZTjkqZ1;HA0Zp8~i*?9jK@7DzF5Cwb{M0EJJ zdFQYCg$>j{ouh%B3M1Qs3=ZGV(U(Iq2#NQ~M^NV>2IYUw?*FKE|8LZ9$ASPj2hfxc z)|-fz^uOHyRf8gcfie7#JF3$^?wBCp5zhlK2f^T{`>T=fi_P#-dNmI zGKjp)zxq`<#rm&d{*P?xe});I^_TmbiV9SEit=9}|1ST-{Qv(9yx`vu!D0;he=gX+ z0@?prp8cP``iuSvME>_G8=t*R-p;@1^t1OXT=hnT^!!D1c2WH6hj~s0Vcqu+jSSK~ ze?K{$!~Z?8YDWJup9~X#I?msx!{h`2w0@2N(KYpMNVp(=<47*ZAV}x_uET;%E(l>n J*WbtZ{{Z#P!zlm& delta 13442 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 diff --git a/forge/1.20/gradlew b/forge/1.20/gradlew index 65dcd68d..aeb74cbb 100644 --- a/forge/1.20/gradlew +++ b/forge/1.20/gradlew @@ -85,9 +85,6 @@ done APP_BASE_NAME=${0##*/} APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' - # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -144,7 +141,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -152,7 +149,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -197,6 +194,10 @@ if "$cygwin" || "$msys" ; then done fi + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + # Collect all arguments for the java command; # * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of # shell script including quotes and variable substitutions, so put them in diff --git a/forge/1.20/gradlew.bat b/forge/1.20/gradlew.bat new file mode 100644 index 00000000..93e3f59f --- /dev/null +++ b/forge/1.20/gradlew.bat @@ -0,0 +1,92 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/neoforge/1.20.2/gradle/wrapper/gradle-wrapper.jar b/neoforge/1.20.2/gradle/wrapper/gradle-wrapper.jar index 943f0cbfa754578e88a3dae77fce6e3dea56edbf..c1962a79e29d3e0ab67b14947c167a862655af9b 100644 GIT binary patch delta 13895 zcmZ8|Wmp``)-~=Hdu)0n3Y-8OvyK$p9^s9MM|Aj$miotNhy-{udLczZyd9uWtD)X_{|!LhIEF9y8(e*Z zW>^w$u&x|i9OjL=#6Nl~*ERulzX>8C-}o;iSMRYdfCU5d`~U{V4>HCg0HG4Xg2uP;fn!>S9+>LbuWbc0bETMQfo9~h}yI*TSv;Oikl~t-+xqI-`P$Rj@yi{mr2zC~s1snMT3!OPBdJ%IDnPXq+pl*Z>=+?qo${lkCSKmwTlVjfb3thU6B8yFjr!tphOs*G6 zwL`RyVAUXj4p=9&@PpWK)m+REuvHaq838TEhY^7W+JAp$ zZ^y;8`Z*@VqJ{sFFj?<|7SKS@G`$Yi)gx%nOi@Lr zCv0IJlFz0bP(eDIW(uWNq?;8zEAb+uGgnkLk;y!4XhA6=Eoa<`+|;6mOq>z`%ir@z$4)Mkd3 zF=hFo zyd{*bRQ4YUe^bU*Y`__)Uhu5NIjVJ~a}{lHp-_7wI?#EB11XcqmdY>pk`JJ) zW9Rt!tK=N>fZ!UDomwMnb`0EOvTjcNl=yW@$c!OAg*=l()GjZwSyJ+o^;Zi#I5*uP z$6qeih8&g8E(pNSneK>93A(8*%gvwv!0V|SqGcj55Y7`=N*@pJx_ig3uVuf-G~LJbm`7nxNcZ>Jgqy(LTHu_C2e>STp^Pm{}f&^)XU}vzuU`UV&>e& zqsXNXSs;Wri|?NhCq0vXC5$>9Cag$adyWz^x@NCiy2${9Dc)Y;J8k1Z933W$3$H}g zCQFU1XwzGm_WUheXvnDisH_%BdzMgNwk2^mHcQu*x>U%iN*B^8U(eVz1~(%`kV1Vb z=9T0xmN?bQMyrrd?u}jer}zV&sCK6zSm!zV8A8dP6THF=4*V{_K*E*K<)I(Q^(eV!m!vu##-2g|G z{RB;{gJB_X-w{ANq?ft_n!@=O8_gj6FxW&zO$7L3@NjWt@R{NxMbpHLk6;=2$0P5P=kKc1_85inX z#s$&s0zhV1cz>nRb#|D#N8Z-=Tphm)sGH>9cz3K3I)6XpimJW0(6$GtLzN(YPu9%R zdFXG9|30AZME4r@joC0IdvBBe08mF@+5Dd97p$h=n|pi80Cn2n{ev!S$llPGLqHva zZ3*OmW%!Qj>C$F!Ffafl7#I_1(gz!aa)b{ebU*=yH%^kr=~N?|2&2Df2o9X=2B?U!#R#+Cj45=f@=EcQx+9J z=X3~A=zbX29Fqn23m3dm}0Voj^Q9BjI=MiG+NZ)YCYn@r^qv(xE3=)&i z=(ML301=rNTptvUt2tnsPb1~G*DWFWoZfv)wV|uNW%?!)jju`jN(K-0$JYi!ofNup z9K%_ucHwutbZsl~vDQ!Jtj8uI6WA6K--@?8+_=t>g|kgUeC=w`IP9m&*fuoO3#A;t z&3@=3;J0>yjM89?h5MG$S`wW+=vyYOWQGhIP`^vScM8^JL{mGan5uTJPvAg$0z}8; z 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 J*WbtZ{{Z#P!zlm& delta 13442 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 diff --git a/neoforge/1.20.2/gradlew b/neoforge/1.20.2/gradlew index 65dcd68d..aeb74cbb 100644 --- a/neoforge/1.20.2/gradlew +++ b/neoforge/1.20.2/gradlew @@ -85,9 +85,6 @@ done APP_BASE_NAME=${0##*/} APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' - # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -144,7 +141,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -152,7 +149,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -197,6 +194,10 @@ if "$cygwin" || "$msys" ; then done fi + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + # Collect all arguments for the java command; # * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of # shell script including quotes and variable substitutions, so put them in diff --git a/neoforge/1.20.2/gradlew.bat b/neoforge/1.20.2/gradlew.bat new file mode 100644 index 00000000..93e3f59f --- /dev/null +++ b/neoforge/1.20.2/gradlew.bat @@ -0,0 +1,92 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/neoforge/1.20.4/gradle/wrapper/gradle-wrapper.jar b/neoforge/1.20.4/gradle/wrapper/gradle-wrapper.jar index 943f0cbfa754578e88a3dae77fce6e3dea56edbf..c1962a79e29d3e0ab67b14947c167a862655af9b 100644 GIT binary patch delta 13895 zcmZ8|Wmp``)-~=Hdu)0n3Y-8OvyK$p9^s9MM|Aj$miotNhy-{udLczZyd9uWtD)X_{|!LhIEF9y8(e*Z zW>^w$u&x|i9OjL=#6Nl~*ERulzX>8C-}o;iSMRYdfCU5d`~U{V4>HCg0HG4Xg2uP;fn!>S9+>LbuWbc0bETMQfo9~h}yI*TSv;Oikl~t-+xqI-`P$Rj@yi{mr2zC~s1snMT3!OPBdJ%IDnPXq+pl*Z>=+?qo${lkCSKmwTlVjfb3thU6B8yFjr!tphOs*G6 zwL`RyVAUXj4p=9&@PpWK)m+REuvHaq838TEhY^7W+JAp$ zZ^y;8`Z*@VqJ{sFFj?<|7SKS@G`$Yi)gx%nOi@Lr zCv0IJlFz0bP(eDIW(uWNq?;8zEAb+uGgnkLk;y!4XhA6=Eoa<`+|;6mOq>z`%ir@z$4)Mkd3 zF=hFo zyd{*bRQ4YUe^bU*Y`__)Uhu5NIjVJ~a}{lHp-_7wI?#EB11XcqmdY>pk`JJ) zW9Rt!tK=N>fZ!UDomwMnb`0EOvTjcNl=yW@$c!OAg*=l()GjZwSyJ+o^;Zi#I5*uP z$6qeih8&g8E(pNSneK>93A(8*%gvwv!0V|SqGcj55Y7`=N*@pJx_ig3uVuf-G~LJbm`7nxNcZ>Jgqy(LTHu_C2e>STp^Pm{}f&^)XU}vzuU`UV&>e& zqsXNXSs;Wri|?NhCq0vXC5$>9Cag$adyWz^x@NCiy2${9Dc)Y;J8k1Z933W$3$H}g zCQFU1XwzGm_WUheXvnDisH_%BdzMgNwk2^mHcQu*x>U%iN*B^8U(eVz1~(%`kV1Vb z=9T0xmN?bQMyrrd?u}jer}zV&sCK6zSm!zV8A8dP6THF=4*V{_K*E*K<)I(Q^(eV!m!vu##-2g|G z{RB;{gJB_X-w{ANq?ft_n!@=O8_gj6FxW&zO$7L3@NjWt@R{NxMbpHLk6;=2$0P5P=kKc1_85inX z#s$&s0zhV1cz>nRb#|D#N8Z-=Tphm)sGH>9cz3K3I)6XpimJW0(6$GtLzN(YPu9%R zdFXG9|30AZME4r@joC0IdvBBe08mF@+5Dd97p$h=n|pi80Cn2n{ev!S$llPGLqHva zZ3*OmW%!Qj>C$F!Ffafl7#I_1(gz!aa)b{ebU*=yH%^kr=~N?|2&2Df2o9X=2B?U!#R#+Cj45=f@=EcQx+9J z=X3~A=zbX29Fqn23m3dm}0Voj^Q9BjI=MiG+NZ)YCYn@r^qv(xE3=)&i z=(ML301=rNTptvUt2tnsPb1~G*DWFWoZfv)wV|uNW%?!)jju`jN(K-0$JYi!ofNup z9K%_ucHwutbZsl~vDQ!Jtj8uI6WA6K--@?8+_=t>g|kgUeC=w`IP9m&*fuoO3#A;t z&3@=3;J0>yjM89?h5MG$S`wW+=vyYOWQGhIP`^vScM8^JL{mGan5uTJPvAg$0z}8; z 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 J*WbtZ{{Z#P!zlm& delta 13442 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 diff --git a/neoforge/1.20.4/gradlew b/neoforge/1.20.4/gradlew index 65dcd68d..aeb74cbb 100644 --- a/neoforge/1.20.4/gradlew +++ b/neoforge/1.20.4/gradlew @@ -85,9 +85,6 @@ done APP_BASE_NAME=${0##*/} APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' - # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -144,7 +141,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -152,7 +149,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -197,6 +194,10 @@ if "$cygwin" || "$msys" ; then done fi + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + # Collect all arguments for the java command; # * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of # shell script including quotes and variable substitutions, so put them in diff --git a/neoforge/1.20.4/gradlew.bat b/neoforge/1.20.4/gradlew.bat new file mode 100644 index 00000000..93e3f59f --- /dev/null +++ b/neoforge/1.20.4/gradlew.bat @@ -0,0 +1,92 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/neoforge/1.20.6/gradle/wrapper/gradle-wrapper.jar b/neoforge/1.20.6/gradle/wrapper/gradle-wrapper.jar index 943f0cbfa754578e88a3dae77fce6e3dea56edbf..e6441136f3d4ba8a0da8d277868979cfbc8ad796 100644 GIT binary patch literal 43453 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 yu?e%!_ptzGB|8GrCfu%p?(_ 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

NnX)EH+Nua)3Y(c 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 ScNgau(U?ep-K_E5zy1%ZQTdPn diff --git a/neoforge/1.20.6/gradle/wrapper/gradle-wrapper.properties b/neoforge/1.20.6/gradle/wrapper/gradle-wrapper.properties index 20db9ad5..b82aa23a 100644 --- a/neoforge/1.20.6/gradle/wrapper/gradle-wrapper.properties +++ b/neoforge/1.20.6/gradle/wrapper/gradle-wrapper.properties @@ -2,5 +2,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/neoforge/1.20.6/gradlew b/neoforge/1.20.6/gradlew index 65dcd68d..1aa94a42 100644 --- a/neoforge/1.20.6/gradlew +++ b/neoforge/1.20.6/gradlew @@ -83,10 +83,8 @@ done # This is normally unused # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -133,10 +131,13 @@ location of your Java installation." fi else JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. @@ -144,7 +145,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -152,7 +153,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -197,11 +198,15 @@ if "$cygwin" || "$msys" ; then done fi -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ diff --git a/neoforge/1.20.6/gradlew.bat b/neoforge/1.20.6/gradlew.bat index 93e3f59f..25da30db 100644 --- a/neoforge/1.20.6/gradlew.bat +++ b/neoforge/1.20.6/gradlew.bat @@ -43,11 +43,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -57,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail diff --git a/neoforge/1.21/gradle/wrapper/gradle-wrapper.jar b/neoforge/1.21/gradle/wrapper/gradle-wrapper.jar index 943f0cbfa754578e88a3dae77fce6e3dea56edbf..e6441136f3d4ba8a0da8d277868979cfbc8ad796 100644 GIT binary patch literal 43453 zcma&N1CXTcmMvW9vTb(Rwr$&4wr$(C?dmSu>@vG-+vuvg^_??!{yS%8zW-#zn-LkA z5&1^$^{lnmUON?}LBF8_K|(?T0Ra(xUH{($5eN!MR#ZihR#HxkUPe+_R8Cn`RRs(P z_^*#_XlXmGv7!4;*Y%p4nw?{bNp@UZHv1?Um8r6)Fei3p@ClJn0ECfg1hkeuUU@Or zDaPa;U3fE=3L}DooL;8f;P0ipPt0Z~9P0)lbStMS)ag54=uL9ia-Lm3nh|@(Y?B`; zx_#arJIpXH!U{fbCbI^17}6Ri*H<>OLR%c|^mh8+)*h~K8Z!9)DPf zR2h?lbDZQ`p9P;&DQ4F0sur@TMa!Y}S8irn(%d-gi0*WxxCSk*A?3lGh=gcYN?FGl z7D=Js!i~0=u3rox^eO3i@$0=n{K1lPNU zwmfjRVmLOCRfe=seV&P*1Iq=^i`502keY8Uy-WNPwVNNtJFx?IwAyRPZo2Wo1+S(xF37LJZ~%i)kpFQ3Fw=mXfd@>%+)RpYQLnr}B~~zoof(JVm^^&f zxKV^+3D3$A1G;qh4gPVjhrC8e(VYUHv#dy^)(RoUFM?o%W-EHxufuWf(l*@-l+7vt z=l`qmR56K~F|v<^Pd*p~1_y^P0P^aPC##d8+HqX4IR1gu+7w#~TBFphJxF)T$2WEa zxa?H&6=Qe7d(#tha?_1uQys2KtHQ{)Qco)qwGjrdNL7thd^G5i8Os)CHqc>iOidS} z%nFEDdm=GXBw=yXe1W-ShHHFb?Cc70+$W~z_+}nAoHFYI1MV1wZegw*0y^tC*s%3h zhD3tN8b=Gv&rj}!SUM6|ajSPp*58KR7MPpI{oAJCtY~JECm)*m_x>AZEu>DFgUcby z1Qaw8lU4jZpQ_$;*7RME+gq1KySGG#Wql>aL~k9tLrSO()LWn*q&YxHEuzmwd1?aAtI zBJ>P=&$=l1efe1CDU;`Fd+_;&wI07?V0aAIgc(!{a z0Jg6Y=inXc3^n!U0Atk`iCFIQooHqcWhO(qrieUOW8X(x?(RD}iYDLMjSwffH2~tB z)oDgNBLB^AJBM1M^c5HdRx6fBfka`(LD-qrlh5jqH~);#nw|iyp)()xVYak3;Ybik z0j`(+69aK*B>)e_p%=wu8XC&9e{AO4c~O1U`5X9}?0mrd*m$_EUek{R?DNSh(=br# z#Q61gBzEpmy`$pA*6!87 zSDD+=@fTY7<4A?GLqpA?Pb2z$pbCc4B4zL{BeZ?F-8`s$?>*lXXtn*NC61>|*w7J* z$?!iB{6R-0=KFmyp1nnEmLsA-H0a6l+1uaH^g%c(p{iT&YFrbQ$&PRb8Up#X3@Zsk zD^^&LK~111%cqlP%!_gFNa^dTYT?rhkGl}5=fL{a`UViaXWI$k-UcHJwmaH1s=S$4 z%4)PdWJX;hh5UoK?6aWoyLxX&NhNRqKam7tcOkLh{%j3K^4Mgx1@i|Pi&}<^5>hs5 zm8?uOS>%)NzT(%PjVPGa?X%`N2TQCKbeH2l;cTnHiHppPSJ<7y-yEIiC!P*ikl&!B z%+?>VttCOQM@ShFguHVjxX^?mHX^hSaO_;pnyh^v9EumqSZTi+#f&_Vaija0Q-e*| z7ulQj6Fs*bbmsWp{`auM04gGwsYYdNNZcg|ph0OgD>7O}Asn7^Z=eI>`$2*v78;sj-}oMoEj&@)9+ycEOo92xSyY344^ z11Hb8^kdOvbf^GNAK++bYioknrpdN>+u8R?JxG=!2Kd9r=YWCOJYXYuM0cOq^FhEd zBg2puKy__7VT3-r*dG4c62Wgxi52EMCQ`bKgf*#*ou(D4-ZN$+mg&7$u!! z-^+Z%;-3IDwqZ|K=ah85OLwkO zKxNBh+4QHh)u9D?MFtpbl)us}9+V!D%w9jfAMYEb>%$A;u)rrI zuBudh;5PN}_6J_}l55P3l_)&RMlH{m!)ai-i$g)&*M`eN$XQMw{v^r@-125^RRCF0 z^2>|DxhQw(mtNEI2Kj(;KblC7x=JlK$@78`O~>V!`|1Lm-^JR$-5pUANAnb(5}B}JGjBsliK4& zk6y(;$e&h)lh2)L=bvZKbvh@>vLlreBdH8No2>$#%_Wp1U0N7Ank!6$dFSi#xzh|( zRi{Uw%-4W!{IXZ)fWx@XX6;&(m_F%c6~X8hx=BN1&q}*( zoaNjWabE{oUPb!Bt$eyd#$5j9rItB-h*5JiNi(v^e|XKAj*8(k<5-2$&ZBR5fF|JA z9&m4fbzNQnAU}r8ab>fFV%J0z5awe#UZ|bz?Ur)U9bCIKWEzi2%A+5CLqh?}K4JHi z4vtM;+uPsVz{Lfr;78W78gC;z*yTch~4YkLr&m-7%-xc ztw6Mh2d>_iO*$Rd8(-Cr1_V8EO1f*^@wRoSozS) zy1UoC@pruAaC8Z_7~_w4Q6n*&B0AjOmMWa;sIav&gu z|J5&|{=a@vR!~k-OjKEgPFCzcJ>#A1uL&7xTDn;{XBdeM}V=l3B8fE1--DHjSaxoSjNKEM9|U9#m2<3>n{Iuo`r3UZp;>GkT2YBNAh|b z^jTq-hJp(ebZh#Lk8hVBP%qXwv-@vbvoREX$TqRGTgEi$%_F9tZES@z8Bx}$#5eeG zk^UsLBH{bc2VBW)*EdS({yw=?qmevwi?BL6*=12k9zM5gJv1>y#ML4!)iiPzVaH9% zgSImetD@dam~e>{LvVh!phhzpW+iFvWpGT#CVE5TQ40n%F|p(sP5mXxna+Ev7PDwA zamaV4m*^~*xV+&p;W749xhb_X=$|LD;FHuB&JL5?*Y2-oIT(wYY2;73<^#46S~Gx| z^cez%V7x$81}UWqS13Gz80379Rj;6~WdiXWOSsdmzY39L;Hg3MH43o*y8ibNBBH`(av4|u;YPq%{R;IuYow<+GEsf@R?=@tT@!}?#>zIIn0CoyV!hq3mw zHj>OOjfJM3F{RG#6ujzo?y32m^tgSXf@v=J$ELdJ+=5j|=F-~hP$G&}tDZsZE?5rX ztGj`!S>)CFmdkccxM9eGIcGnS2AfK#gXwj%esuIBNJQP1WV~b~+D7PJTmWGTSDrR` zEAu4B8l>NPuhsk5a`rReSya2nfV1EK01+G!x8aBdTs3Io$u5!6n6KX%uv@DxAp3F@{4UYg4SWJtQ-W~0MDb|j-$lwVn znAm*Pl!?Ps&3wO=R115RWKb*JKoexo*)uhhHBncEDMSVa_PyA>k{Zm2(wMQ(5NM3# z)jkza|GoWEQo4^s*wE(gHz?Xsg4`}HUAcs42cM1-qq_=+=!Gk^y710j=66(cSWqUe zklbm8+zB_syQv5A2rj!Vbw8;|$@C!vfNmNV!yJIWDQ>{+2x zKjuFX`~~HKG~^6h5FntRpnnHt=D&rq0>IJ9#F0eM)Y-)GpRjiN7gkA8wvnG#K=q{q z9dBn8_~wm4J<3J_vl|9H{7q6u2A!cW{bp#r*-f{gOV^e=8S{nc1DxMHFwuM$;aVI^ zz6A*}m8N-&x8;aunp1w7_vtB*pa+OYBw=TMc6QK=mbA-|Cf* zvyh8D4LRJImooUaSb7t*fVfih<97Gf@VE0|z>NcBwBQze);Rh!k3K_sfunToZY;f2 z^HmC4KjHRVg+eKYj;PRN^|E0>Gj_zagfRbrki68I^#~6-HaHg3BUW%+clM1xQEdPYt_g<2K+z!$>*$9nQ>; zf9Bei{?zY^-e{q_*|W#2rJG`2fy@{%6u0i_VEWTq$*(ZN37|8lFFFt)nCG({r!q#9 z5VK_kkSJ3?zOH)OezMT{!YkCuSSn!K#-Rhl$uUM(bq*jY? zi1xbMVthJ`E>d>(f3)~fozjg^@eheMF6<)I`oeJYx4*+M&%c9VArn(OM-wp%M<-`x z7sLP1&3^%Nld9Dhm@$3f2}87!quhI@nwd@3~fZl_3LYW-B?Ia>ui`ELg z&Qfe!7m6ze=mZ`Ia9$z|ARSw|IdMpooY4YiPN8K z4B(ts3p%2i(Td=tgEHX z0UQ_>URBtG+-?0E;E7Ld^dyZ;jjw0}XZ(}-QzC6+NN=40oDb2^v!L1g9xRvE#@IBR zO!b-2N7wVfLV;mhEaXQ9XAU+>=XVA6f&T4Z-@AX!leJ8obP^P^wP0aICND?~w&NykJ#54x3_@r7IDMdRNy4Hh;h*!u(Ol(#0bJdwEo$5437-UBjQ+j=Ic>Q2z` zJNDf0yO6@mr6y1#n3)s(W|$iE_i8r@Gd@!DWDqZ7J&~gAm1#~maIGJ1sls^gxL9LLG_NhU!pTGty!TbhzQnu)I*S^54U6Yu%ZeCg`R>Q zhBv$n5j0v%O_j{QYWG!R9W?5_b&67KB$t}&e2LdMvd(PxN6Ir!H4>PNlerpBL>Zvyy!yw z-SOo8caEpDt(}|gKPBd$qND5#a5nju^O>V&;f890?yEOfkSG^HQVmEbM3Ugzu+UtH zC(INPDdraBN?P%kE;*Ae%Wto&sgw(crfZ#Qy(<4nk;S|hD3j{IQRI6Yq|f^basLY; z-HB&Je%Gg}Jt@={_C{L$!RM;$$|iD6vu#3w?v?*;&()uB|I-XqEKqZPS!reW9JkLewLb!70T7n`i!gNtb1%vN- zySZj{8-1>6E%H&=V}LM#xmt`J3XQoaD|@XygXjdZ1+P77-=;=eYpoEQ01B@L*a(uW zrZeZz?HJsw_4g0vhUgkg@VF8<-X$B8pOqCuWAl28uB|@r`19DTUQQsb^pfqB6QtiT z*`_UZ`fT}vtUY#%sq2{rchyfu*pCg;uec2$-$N_xgjZcoumE5vSI{+s@iLWoz^Mf; zuI8kDP{!XY6OP~q5}%1&L}CtfH^N<3o4L@J@zg1-mt{9L`s^z$Vgb|mr{@WiwAqKg zp#t-lhrU>F8o0s1q_9y`gQNf~Vb!F%70f}$>i7o4ho$`uciNf=xgJ>&!gSt0g;M>*x4-`U)ysFW&Vs^Vk6m%?iuWU+o&m(2Jm26Y(3%TL; zA7T)BP{WS!&xmxNw%J=$MPfn(9*^*TV;$JwRy8Zl*yUZi8jWYF>==j~&S|Xinsb%c z2?B+kpet*muEW7@AzjBA^wAJBY8i|#C{WtO_or&Nj2{=6JTTX05}|H>N2B|Wf!*3_ z7hW*j6p3TvpghEc6-wufFiY!%-GvOx*bZrhZu+7?iSrZL5q9}igiF^*R3%DE4aCHZ zqu>xS8LkW+Auv%z-<1Xs92u23R$nk@Pk}MU5!gT|c7vGlEA%G^2th&Q*zfg%-D^=f z&J_}jskj|Q;73NP4<4k*Y%pXPU2Thoqr+5uH1yEYM|VtBPW6lXaetokD0u z9qVek6Q&wk)tFbQ8(^HGf3Wp16gKmr>G;#G(HRBx?F`9AIRboK+;OfHaLJ(P>IP0w zyTbTkx_THEOs%Q&aPrxbZrJlio+hCC_HK<4%f3ZoSAyG7Dn`=X=&h@m*|UYO-4Hq0 z-Bq&+Ie!S##4A6OGoC~>ZW`Y5J)*ouaFl_e9GA*VSL!O_@xGiBw!AF}1{tB)z(w%c zS1Hmrb9OC8>0a_$BzeiN?rkPLc9%&;1CZW*4}CDDNr2gcl_3z+WC15&H1Zc2{o~i) z)LLW=WQ{?ricmC`G1GfJ0Yp4Dy~Ba;j6ZV4r{8xRs`13{dD!xXmr^Aga|C=iSmor% z8hi|pTXH)5Yf&v~exp3o+sY4B^^b*eYkkCYl*T{*=-0HniSA_1F53eCb{x~1k3*`W zr~};p1A`k{1DV9=UPnLDgz{aJH=-LQo<5%+Em!DNN252xwIf*wF_zS^!(XSm(9eoj z=*dXG&n0>)_)N5oc6v!>-bd(2ragD8O=M|wGW z!xJQS<)u70m&6OmrF0WSsr@I%T*c#Qo#Ha4d3COcX+9}hM5!7JIGF>7<~C(Ear^Sn zm^ZFkV6~Ula6+8S?oOROOA6$C&q&dp`>oR-2Ym3(HT@O7Sd5c~+kjrmM)YmgPH*tL zX+znN>`tv;5eOfX?h{AuX^LK~V#gPCu=)Tigtq9&?7Xh$qN|%A$?V*v=&-2F$zTUv z`C#WyIrChS5|Kgm_GeudCFf;)!WH7FI60j^0o#65o6`w*S7R@)88n$1nrgU(oU0M9 zx+EuMkC>(4j1;m6NoGqEkpJYJ?vc|B zOlwT3t&UgL!pX_P*6g36`ZXQ; z9~Cv}ANFnJGp(;ZhS(@FT;3e)0)Kp;h^x;$*xZn*k0U6-&FwI=uOGaODdrsp-!K$Ac32^c{+FhI-HkYd5v=`PGsg%6I`4d9Jy)uW0y%) zm&j^9WBAp*P8#kGJUhB!L?a%h$hJgQrx!6KCB_TRo%9{t0J7KW8!o1B!NC)VGLM5! zpZy5Jc{`r{1e(jd%jsG7k%I+m#CGS*BPA65ZVW~fLYw0dA-H_}O zrkGFL&P1PG9p2(%QiEWm6x;U-U&I#;Em$nx-_I^wtgw3xUPVVu zqSuKnx&dIT-XT+T10p;yjo1Y)z(x1fb8Dzfn8e yu?e%!_ptzGB|8GrCfu%p?(_ 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

NnX)EH+Nua)3Y(c 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 ScNgau(U?ep-K_E5zy1%ZQTdPn diff --git a/neoforge/1.21/gradle/wrapper/gradle-wrapper.properties b/neoforge/1.21/gradle/wrapper/gradle-wrapper.properties index 20db9ad5..b82aa23a 100644 --- a/neoforge/1.21/gradle/wrapper/gradle-wrapper.properties +++ b/neoforge/1.21/gradle/wrapper/gradle-wrapper.properties @@ -2,5 +2,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/neoforge/1.21/gradlew b/neoforge/1.21/gradlew index 65dcd68d..1aa94a42 100644 --- a/neoforge/1.21/gradlew +++ b/neoforge/1.21/gradlew @@ -83,10 +83,8 @@ done # This is normally unused # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -133,10 +131,13 @@ location of your Java installation." fi else JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. @@ -144,7 +145,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -152,7 +153,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -197,11 +198,15 @@ if "$cygwin" || "$msys" ; then done fi -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ diff --git a/neoforge/1.21/gradlew.bat b/neoforge/1.21/gradlew.bat index 93e3f59f..25da30db 100644 --- a/neoforge/1.21/gradlew.bat +++ b/neoforge/1.21/gradlew.bat @@ -43,11 +43,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -57,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail From 9af4188e66e94c24d875f3607a3ab17aa9ea3768 Mon Sep 17 00:00:00 2001 From: HoldYourWaffle Date: Tue, 3 Sep 2024 06:23:45 +0200 Subject: [PATCH 558/580] Update Gradle wrappers to the latest version that doesn't immediately scream Forge 1.20 screamed at 8.10, max 8.6? --- core/gradle/wrapper/gradle-wrapper.jar | Bin 63721 -> 43583 bytes core/gradle/wrapper/gradle-wrapper.properties | 2 +- core/gradlew | 21 +- core/gradlew.bat | 22 +- fabric/1.18/gradle/wrapper/gradle-wrapper.jar | Bin 62076 -> 43583 bytes .../gradle/wrapper/gradle-wrapper.properties | 3 +- fabric/1.18/gradlew | 27 +- fabric/1.18/gradlew.bat | 22 +- .../1.19.2/gradle/wrapper/gradle-wrapper.jar | Bin 62076 -> 43583 bytes .../gradle/wrapper/gradle-wrapper.properties | 3 +- fabric/1.19.2/gradlew | 27 +- fabric/1.19.2/gradlew.bat | 22 +- .../1.19.3/gradle/wrapper/gradle-wrapper.jar | Bin 62076 -> 43583 bytes .../gradle/wrapper/gradle-wrapper.properties | 3 +- fabric/1.19.3/gradlew | 27 +- fabric/1.19.3/gradlew.bat | 22 +- .../1.20.2/gradle/wrapper/gradle-wrapper.jar | Bin 63721 -> 43583 bytes .../gradle/wrapper/gradle-wrapper.properties | 2 +- fabric/1.20.2/gradlew | 21 +- fabric/1.20.2/gradlew.bat | 22 +- .../1.20.6/gradle/wrapper/gradle-wrapper.jar | Bin 43453 -> 43583 bytes .../gradle/wrapper/gradle-wrapper.properties | 2 +- fabric/1.20.6/gradlew | 7 +- fabric/1.20.6/gradlew.bat | 2 + fabric/1.20/gradle/wrapper/gradle-wrapper.jar | Bin 62076 -> 43583 bytes .../gradle/wrapper/gradle-wrapper.properties | 3 +- fabric/1.20/gradlew | 27 +- fabric/1.20/gradlew.bat | 22 +- fabric/1.21/gradle/wrapper/gradle-wrapper.jar | Bin 43453 -> 43583 bytes .../gradle/wrapper/gradle-wrapper.properties | 2 +- fabric/1.21/gradlew | 5 +- fabric/1.21/gradlew.bat | 2 + forge/1.12/gradle/wrapper/gradle-wrapper.jar | Bin 60756 -> 61624 bytes .../gradle/wrapper/gradle-wrapper.properties | 3 +- forge/1.12/gradlew | 12 +- forge/1.12/gradlew.bat | 1 + forge/1.16/gradle/wrapper/gradle-wrapper.jar | Bin 54413 -> 59203 bytes .../gradle/wrapper/gradle-wrapper.properties | 2 +- forge/1.16/gradlew | 282 +++++++++++------- forge/1.16/gradlew.bat | 89 ++++++ forge/1.18/gradle/wrapper/gradle-wrapper.jar | Bin 60756 -> 61624 bytes .../gradle/wrapper/gradle-wrapper.properties | 3 +- forge/1.18/gradlew | 12 +- forge/1.18/gradlew.bat | 1 + .../1.19.2/gradle/wrapper/gradle-wrapper.jar | Bin 60756 -> 61624 bytes .../gradle/wrapper/gradle-wrapper.properties | 3 +- forge/1.19.2/gradlew | 12 +- forge/1.19.2/gradlew.bat | 1 + .../1.19.3/gradle/wrapper/gradle-wrapper.jar | Bin 62076 -> 43583 bytes .../gradle/wrapper/gradle-wrapper.properties | 3 +- forge/1.19.3/gradlew | 27 +- forge/1.19.3/gradlew.bat | 22 +- .../1.20.2/gradle/wrapper/gradle-wrapper.jar | Bin 62076 -> 43583 bytes .../gradle/wrapper/gradle-wrapper.properties | 3 +- forge/1.20.2/gradlew | 27 +- forge/1.20.2/gradlew.bat | 22 +- .../1.20.6/gradle/wrapper/gradle-wrapper.jar | Bin 43453 -> 43583 bytes .../gradle/wrapper/gradle-wrapper.properties | 2 +- forge/1.20.6/gradlew | 7 +- forge/1.20.6/gradlew.bat | 2 + forge/1.20/gradle/wrapper/gradle-wrapper.jar | Bin 62076 -> 43462 bytes .../gradle/wrapper/gradle-wrapper.properties | 3 +- forge/1.20/gradlew | 22 +- forge/1.20/gradlew.bat | 20 +- .../gradle/wrapper/gradle-wrapper.properties | 2 +- .../1.20.2/gradle/wrapper/gradle-wrapper.jar | Bin 62076 -> 43583 bytes .../gradle/wrapper/gradle-wrapper.properties | 3 +- neoforge/1.20.2/gradlew | 27 +- neoforge/1.20.2/gradlew.bat | 22 +- .../1.20.4/gradle/wrapper/gradle-wrapper.jar | Bin 62076 -> 43583 bytes .../gradle/wrapper/gradle-wrapper.properties | 3 +- neoforge/1.20.4/gradlew | 27 +- neoforge/1.20.4/gradlew.bat | 22 +- .../1.20.6/gradle/wrapper/gradle-wrapper.jar | Bin 43453 -> 43583 bytes .../gradle/wrapper/gradle-wrapper.properties | 2 +- neoforge/1.20.6/gradlew | 7 +- neoforge/1.20.6/gradlew.bat | 2 + .../1.21/gradle/wrapper/gradle-wrapper.jar | Bin 43453 -> 43583 bytes .../gradle/wrapper/gradle-wrapper.properties | 2 +- neoforge/1.21/gradlew | 7 +- neoforge/1.21/gradlew.bat | 2 + spigot/1.21/gradle/wrapper/gradle-wrapper.jar | Bin 43453 -> 43583 bytes .../gradle/wrapper/gradle-wrapper.properties | 2 +- spigot/1.21/gradlew | 7 +- spigot/1.21/gradlew.bat | 2 + 85 files changed, 666 insertions(+), 372 deletions(-) create mode 100644 forge/1.16/gradlew.bat diff --git a/core/gradle/wrapper/gradle-wrapper.jar b/core/gradle/wrapper/gradle-wrapper.jar index 7f93135c49b765f8051ef9d0a6055ff8e46073d8..a4b76b9530d66f5e68d973ea569d8e19de379189 100644 GIT binary patch literal 43583 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 yu?e%!_ptzGB|8GrCfu%p?(_ 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 GZ~q4|mN%#X literal 63721 zcmb5Wb9gP!wgnp7wrv|bwr$&XvSZt}Z6`anZSUAlc9NHKf9JdJ;NJVr`=eI(_pMp0 zy1VAAG3FfAOI`{X1O)&90s;U4K;XLp008~hCjbEC_fbYfS%6kTR+JtXK>nW$ZR+`W ze|#J8f4A@M|F5BpfUJb5h>|j$jOe}0oE!`Zf6fM>CR?!y@zU(cL8NsKk`a z6tx5mAkdjD;J=LcJ;;Aw8p!v#ouk>mUDZF@ zK>yvw%+bKu+T{Nk@LZ;zkYy0HBKw06_IWcMHo*0HKpTsEFZhn5qCHH9j z)|XpN&{`!0a>Vl+PmdQc)Yg4A(AG-z!+@Q#eHr&g<9D?7E)_aEB?s_rx>UE9TUq|? z;(ggJt>9l?C|zoO@5)tu?EV0x_7T17q4fF-q3{yZ^ipUbKcRZ4Qftd!xO(#UGhb2y>?*@{xq%`(-`2T^vc=#< zx!+@4pRdk&*1ht2OWk^Z5IAQ0YTAXLkL{(D*$gENaD)7A%^XXrCchN&z2x+*>o2FwPFjWpeaL=!tzv#JOW#( z$B)Nel<+$bkH1KZv3&-}=SiG~w2sbDbAWarg%5>YbC|}*d9hBjBkR(@tyM0T)FO$# zPtRXukGPnOd)~z=?avu+4Co@wF}1T)-uh5jI<1$HLtyDrVak{gw`mcH@Q-@wg{v^c zRzu}hMKFHV<8w}o*yg6p@Sq%=gkd~;`_VGTS?L@yVu`xuGy+dH6YOwcP6ZE`_0rK% zAx5!FjDuss`FQ3eF|mhrWkjux(Pny^k$u_)dyCSEbAsecHsq#8B3n3kDU(zW5yE|( zgc>sFQywFj5}U*qtF9Y(bi*;>B7WJykcAXF86@)z|0-Vm@jt!EPoLA6>r)?@DIobIZ5Sx zsc@OC{b|3%vaMbyeM|O^UxEYlEMHK4r)V-{r)_yz`w1*xV0|lh-LQOP`OP`Pk1aW( z8DSlGN>Ts|n*xj+%If~+E_BxK)~5T#w6Q1WEKt{!Xtbd`J;`2a>8boRo;7u2M&iOop4qcy<)z023=oghSFV zST;?S;ye+dRQe>ygiJ6HCv4;~3DHtJ({fWeE~$H@mKn@Oh6Z(_sO>01JwH5oA4nvK zr5Sr^g+LC zLt(i&ecdmqsIJGNOSUyUpglvhhrY8lGkzO=0USEKNL%8zHshS>Qziu|`eyWP^5xL4 zRP122_dCJl>hZc~?58w~>`P_s18VoU|7(|Eit0-lZRgLTZKNq5{k zE?V=`7=R&ro(X%LTS*f+#H-mGo_j3dm@F_krAYegDLk6UV{`UKE;{YSsn$ z(yz{v1@p|p!0>g04!eRSrSVb>MQYPr8_MA|MpoGzqyd*$@4j|)cD_%^Hrd>SorF>@ zBX+V<@vEB5PRLGR(uP9&U&5=(HVc?6B58NJT_igiAH*q~Wb`dDZpJSKfy5#Aag4IX zj~uv74EQ_Q_1qaXWI!7Vf@ZrdUhZFE;L&P_Xr8l@GMkhc#=plV0+g(ki>+7fO%?Jb zl+bTy7q{w^pTb{>(Xf2q1BVdq?#f=!geqssXp z4pMu*q;iiHmA*IjOj4`4S&|8@gSw*^{|PT}Aw~}ZXU`6=vZB=GGeMm}V6W46|pU&58~P+?LUs%n@J}CSrICkeng6YJ^M? zS(W?K4nOtoBe4tvBXs@@`i?4G$S2W&;$z8VBSM;Mn9 zxcaEiQ9=vS|bIJ>*tf9AH~m&U%2+Dim<)E=}KORp+cZ^!@wI`h1NVBXu{@%hB2Cq(dXx_aQ9x3mr*fwL5!ZryQqi|KFJuzvP zK1)nrKZ7U+B{1ZmJub?4)Ln^J6k!i0t~VO#=q1{?T)%OV?MN}k5M{}vjyZu#M0_*u z8jwZKJ#Df~1jcLXZL7bnCEhB6IzQZ-GcoQJ!16I*39iazoVGugcKA{lhiHg4Ta2fD zk1Utyc5%QzZ$s3;p0N+N8VX{sd!~l*Ta3|t>lhI&G`sr6L~G5Lul`>m z{!^INm?J|&7X=;{XveF!(b*=?9NAp4y&r&N3(GKcW4rS(Ejk|Lzs1PrxPI_owB-`H zg3(Rruh^&)`TKA6+_!n>RdI6pw>Vt1_j&+bKIaMTYLiqhZ#y_=J8`TK{Jd<7l9&sY z^^`hmi7^14s16B6)1O;vJWOF$=$B5ONW;;2&|pUvJlmeUS&F;DbSHCrEb0QBDR|my zIs+pE0Y^`qJTyH-_mP=)Y+u^LHcuZhsM3+P||?+W#V!_6E-8boP#R-*na4!o-Q1 zVthtYhK{mDhF(&7Okzo9dTi03X(AE{8cH$JIg%MEQca`S zy@8{Fjft~~BdzWC(di#X{ny;!yYGK9b@=b|zcKZ{vv4D8i+`ilOPl;PJl{!&5-0!w z^fOl#|}vVg%=n)@_e1BrP)`A zKPgs`O0EO}Y2KWLuo`iGaKu1k#YR6BMySxQf2V++Wo{6EHmK>A~Q5o73yM z-RbxC7Qdh0Cz!nG+7BRZE>~FLI-?&W_rJUl-8FDIaXoNBL)@1hwKa^wOr1($*5h~T zF;%f^%<$p8Y_yu(JEg=c_O!aZ#)Gjh$n(hfJAp$C2he555W5zdrBqjFmo|VY+el;o z=*D_w|GXG|p0**hQ7~9-n|y5k%B}TAF0iarDM!q-jYbR^us(>&y;n^2l0C%@2B}KM zyeRT9)oMt97Agvc4sEKUEy%MpXr2vz*lb zh*L}}iG>-pqDRw7ud{=FvTD?}xjD)w{`KzjNom-$jS^;iw0+7nXSnt1R@G|VqoRhE%12nm+PH?9`(4rM0kfrZzIK9JU=^$YNyLvAIoxl#Q)xxDz!^0@zZ zSCs$nfcxK_vRYM34O<1}QHZ|hp4`ioX3x8(UV(FU$J@o%tw3t4k1QPmlEpZa2IujG&(roX_q*%e`Hq|);0;@k z0z=fZiFckp#JzW0p+2A+D$PC~IsakhJJkG(c;CqAgFfU0Z`u$PzG~-9I1oPHrCw&)@s^Dc~^)#HPW0Ra}J^=|h7Fs*<8|b13ZzG6MP*Q1dkoZ6&A^!}|hbjM{2HpqlSXv_UUg1U4gn z3Q)2VjU^ti1myodv+tjhSZp%D978m~p& z43uZUrraHs80Mq&vcetqfQpQP?m!CFj)44t8Z}k`E798wxg&~aCm+DBoI+nKq}&j^ zlPY3W$)K;KtEajks1`G?-@me7C>{PiiBu+41#yU_c(dITaqE?IQ(DBu+c^Ux!>pCj zLC|HJGU*v+!it1(;3e`6igkH(VA)-S+k(*yqxMgUah3$@C zz`7hEM47xr>j8^g`%*f=6S5n>z%Bt_Fg{Tvmr+MIsCx=0gsu_sF`q2hlkEmisz#Fy zj_0;zUWr;Gz}$BS%Y`meb(=$d%@Crs(OoJ|}m#<7=-A~PQbyN$x%2iXP2@e*nO0b7AwfH8cCUa*Wfu@b)D_>I*%uE4O3 z(lfnB`-Xf*LfC)E}e?%X2kK7DItK6Tf<+M^mX0Ijf_!IP>7c8IZX%8_#0060P{QMuV^B9i<^E`_Qf0pv9(P%_s8D`qvDE9LK9u-jB}J2S`(mCO&XHTS04Z5Ez*vl^T%!^$~EH8M-UdwhegL>3IQ*)(MtuH2Xt1p!fS4o~*rR?WLxlA!sjc2(O znjJn~wQ!Fp9s2e^IWP1C<4%sFF}T4omr}7+4asciyo3DntTgWIzhQpQirM$9{EbQd z3jz9vS@{aOqTQHI|l#aUV@2Q^Wko4T0T04Me4!2nsdrA8QY1%fnAYb~d2GDz@lAtfcHq(P7 zaMBAGo}+NcE-K*@9y;Vt3*(aCaMKXBB*BJcD_Qnxpt75r?GeAQ}*|>pYJE=uZb73 zC>sv)18)q#EGrTG6io*}JLuB_jP3AU1Uiu$D7r|2_zlIGb9 zjhst#ni)Y`$)!fc#reM*$~iaYoz~_Cy7J3ZTiPm)E?%`fbk`3Tu-F#`{i!l5pNEn5 zO-Tw-=TojYhzT{J=?SZj=Z8#|eoF>434b-DXiUsignxXNaR3 zm_}4iWU$gt2Mw5NvZ5(VpF`?X*f2UZDs1TEa1oZCif?Jdgr{>O~7}-$|BZ7I(IKW`{f;@|IZFX*R8&iT= zoWstN8&R;}@2Ka%d3vrLtR|O??ben;k8QbS-WB0VgiCz;<$pBmIZdN!aalyCSEm)crpS9dcD^Y@XT1a3+zpi-`D}e#HV<} z$Y(G&o~PvL-xSVD5D?JqF3?B9rxGWeb=oEGJ3vRp5xfBPlngh1O$yI95EL+T8{GC@ z98i1H9KhZGFl|;`)_=QpM6H?eDPpw~^(aFQWwyXZ8_EEE4#@QeT_URray*mEOGsGc z6|sdXtq!hVZo=d#+9^@lm&L5|q&-GDCyUx#YQiccq;spOBe3V+VKdjJA=IL=Zn%P} zNk=_8u}VhzFf{UYZV0`lUwcD&)9AFx0@Fc6LD9A6Rd1=ga>Mi0)_QxM2ddCVRmZ0d z+J=uXc(?5JLX3=)e)Jm$HS2yF`44IKhwRnm2*669_J=2LlwuF5$1tAo@ROSU@-y+;Foy2IEl2^V1N;fk~YR z?&EP8#t&m0B=?aJeuz~lHjAzRBX>&x=A;gIvb>MD{XEV zV%l-+9N-)i;YH%nKP?>f`=?#`>B(`*t`aiPLoQM(a6(qs4p5KFjDBN?8JGrf3z8>= zi7sD)c)Nm~x{e<^jy4nTx${P~cwz_*a>%0_;ULou3kHCAD7EYkw@l$8TN#LO9jC( z1BeFW`k+bu5e8Ns^a8dPcjEVHM;r6UX+cN=Uy7HU)j-myRU0wHd$A1fNI~`4;I~`zC)3ul#8#^rXVSO*m}Ag>c%_;nj=Nv$rCZ z*~L@C@OZg%Q^m)lc-kcX&a*a5`y&DaRxh6O*dfhLfF+fU5wKs(1v*!TkZidw*)YBP za@r`3+^IHRFeO%!ai%rxy;R;;V^Fr=OJlpBX;(b*3+SIw}7= zIq$*Thr(Zft-RlY)D3e8V;BmD&HOfX+E$H#Y@B3?UL5L~_fA-@*IB-!gItK7PIgG9 zgWuGZK_nuZjHVT_Fv(XxtU%)58;W39vzTI2n&)&4Dmq7&JX6G>XFaAR{7_3QB6zsT z?$L8c*WdN~nZGiscY%5KljQARN;`w$gho=p006z;n(qIQ*Zu<``TMO3n0{ARL@gYh zoRwS*|Niw~cR!?hE{m*y@F`1)vx-JRfqET=dJ5_(076st(=lFfjtKHoYg`k3oNmo_ zNbQEw8&sO5jAYmkD|Zaz_yUb0rC})U!rCHOl}JhbYIDLzLvrZVw0~JO`d*6f;X&?V=#T@ND*cv^I;`sFeq4 z##H5;gpZTb^0Hz@3C*~u0AqqNZ-r%rN3KD~%Gw`0XsIq$(^MEb<~H(2*5G^<2(*aI z%7}WB+TRlMIrEK#s0 z93xn*Ohb=kWFc)BNHG4I(~RPn-R8#0lqyBBz5OM6o5|>x9LK@%HaM}}Y5goCQRt2C z{j*2TtT4ne!Z}vh89mjwiSXG=%DURar~=kGNNaO_+Nkb+tRi~Rkf!7a$*QlavziD( z83s4GmQ^Wf*0Bd04f#0HX@ua_d8 z23~z*53ePD6@xwZ(vdl0DLc=>cPIOPOdca&MyR^jhhKrdQO?_jJh`xV3GKz&2lvP8 zEOwW6L*ufvK;TN{=S&R@pzV^U=QNk^Ec}5H z+2~JvEVA{`uMAr)?Kf|aW>33`)UL@bnfIUQc~L;TsTQ6>r-<^rB8uoNOJ>HWgqMI8 zSW}pZmp_;z_2O5_RD|fGyTxaxk53Hg_3Khc<8AUzV|ZeK{fp|Ne933=1&_^Dbv5^u zB9n=*)k*tjHDRJ@$bp9mrh}qFn*s}npMl5BMDC%Hs0M0g-hW~P*3CNG06G!MOPEQ_ zi}Qs-6M8aMt;sL$vlmVBR^+Ry<64jrm1EI1%#j?c?4b*7>)a{aDw#TfTYKq+SjEFA z(aJ&z_0?0JB83D-i3Vh+o|XV4UP+YJ$9Boid2^M2en@APw&wx7vU~t$r2V`F|7Qfo z>WKgI@eNBZ-+Og<{u2ZiG%>YvH2L3fNpV9J;WLJoBZda)01Rn;o@){01{7E#ke(7U zHK>S#qZ(N=aoae*4X!0A{)nu0R_sKpi1{)u>GVjC+b5Jyl6#AoQ-1_3UDovNSo`T> z?c-@7XX*2GMy?k?{g)7?Sv;SJkmxYPJPs!&QqB12ejq`Lee^-cDveVWL^CTUldb(G zjDGe(O4P=S{4fF=#~oAu>LG>wrU^z_?3yt24FOx>}{^lCGh8?vtvY$^hbZ)9I0E3r3NOlb9I?F-Yc=r$*~l`4N^xzlV~N zl~#oc>U)Yjl0BxV>O*Kr@lKT{Z09OXt2GlvE38nfs+DD7exl|&vT;)>VFXJVZp9Np zDK}aO;R3~ag$X*|hRVY3OPax|PG`@_ESc8E!mHRByJbZQRS38V2F__7MW~sgh!a>98Q2%lUNFO=^xU52|?D=IK#QjwBky-C>zOWlsiiM&1n z;!&1((Xn1$9K}xabq~222gYvx3hnZPg}VMF_GV~5ocE=-v>V=T&RsLBo&`)DOyIj* zLV{h)JU_y*7SdRtDajP_Y+rBkNN*1_TXiKwHH2&p51d(#zv~s#HwbNy?<+(=9WBvo zw2hkk2Dj%kTFhY+$T+W-b7@qD!bkfN#Z2ng@Pd=i3-i?xYfs5Z*1hO?kd7Sp^9`;Y zM2jeGg<-nJD1er@Pc_cSY7wo5dzQX44=%6rn}P_SRbpzsA{6B+!$3B0#;}qwO37G^ zL(V_5JK`XT?OHVk|{_$vQ|oNEpab*BO4F zUTNQ7RUhnRsU`TK#~`)$icsvKh~(pl=3p6m98@k3P#~upd=k*u20SNcb{l^1rUa)>qO997)pYRWMncC8A&&MHlbW?7i^7M`+B$hH~Y|J zd>FYOGQ;j>Zc2e7R{KK7)0>>nn_jYJy&o@sK!4G>-rLKM8Hv)f;hi1D2fAc$+six2 zyVZ@wZ6x|fJ!4KrpCJY=!Mq0;)X)OoS~{Lkh6u8J`eK%u0WtKh6B>GW_)PVc zl}-k`p09qwGtZ@VbYJC!>29V?Dr>>vk?)o(x?!z*9DJ||9qG-&G~#kXxbw{KKYy}J zQKa-dPt~M~E}V?PhW0R26xdA%1T*%ra6SguGu50YHngOTIv)@N|YttEXo#OZfgtP7;H?EeZZxo<}3YlYxtBq znJ!WFR^tmGf0Py}N?kZ(#=VtpC@%xJkDmfcCoBTxq zr_|5gP?u1@vJZbxPZ|G0AW4=tpb84gM2DpJU||(b8kMOV1S3|(yuwZJ&rIiFW(U;5 zUtAW`O6F6Zy+eZ1EDuP~AAHlSY-+A_eI5Gx)%*uro5tljy}kCZU*_d7)oJ>oQSZ3* zneTn`{gnNC&uJd)0aMBzAg021?YJ~b(fmkwZAd696a=0NzBAqBN54KuNDwa*no(^O z6p05bioXUR^uXjpTol*ppHp%1v9e)vkoUAUJyBx3lw0UO39b0?^{}yb!$yca(@DUn zCquRF?t=Zb9`Ed3AI6|L{eX~ijVH`VzSMheKoP7LSSf4g>md>`yi!TkoG5P>Ofp+n z(v~rW+(5L96L{vBb^g51B=(o)?%%xhvT*A5btOpw(TKh^g^4c zw>0%X!_0`{iN%RbVk+A^f{w-4-SSf*fu@FhruNL##F~sF24O~u zyYF<3el2b$$wZ_|uW#@Ak+VAGk#e|kS8nL1g>2B-SNMjMp^8;-FfeofY2fphFHO!{ z*!o4oTb{4e;S<|JEs<1_hPsmAlVNk?_5-Fp5KKU&d#FiNW~Y+pVFk@Cua1I{T+1|+ zHx6rFMor)7L)krbilqsWwy@T+g3DiH5MyVf8Wy}XbEaoFIDr~y;@r&I>FMW{ z?Q+(IgyebZ)-i4jNoXQhq4Muy9Fv+OxU;9_Jmn+<`mEC#%2Q_2bpcgzcinygNI!&^ z=V$)o2&Yz04~+&pPWWn`rrWxJ&}8khR)6B(--!9Q zubo}h+1T)>a@c)H^i``@<^j?|r4*{;tQf78(xn0g39IoZw0(CwY1f<%F>kEaJ zp9u|IeMY5mRdAlw*+gSN^5$Q)ShM<~E=(c8QM+T-Qk)FyKz#Sw0EJ*edYcuOtO#~Cx^(M7w5 z3)rl#L)rF|(Vun2LkFr!rg8Q@=r>9p>(t3Gf_auiJ2Xx9HmxYTa|=MH_SUlYL`mz9 zTTS$`%;D-|Jt}AP1&k7PcnfFNTH0A-*FmxstjBDiZX?}%u%Yq94$fUT&z6od+(Uk> zuqsld#G(b$G8tus=M!N#oPd|PVFX)?M?tCD0tS%2IGTfh}3YA3f&UM)W$_GNV8 zQo+a(ml2Km4o6O%gKTCSDNq+#zCTIQ1*`TIJh~k6Gp;htHBFnne))rlFdGqwC6dx2+La1&Mnko*352k0y z+tQcwndQlX`nc6nb$A9?<-o|r*%aWXV#=6PQic0Ok_D;q>wbv&j7cKc!w4~KF#-{6 z(S%6Za)WpGIWf7jZ3svNG5OLs0>vCL9{V7cgO%zevIVMH{WgP*^D9ws&OqA{yr|m| zKD4*07dGXshJHd#e%x%J+qmS^lS|0Bp?{drv;{@{l9ArPO&?Q5=?OO9=}h$oVe#3b z3Yofj&Cb}WC$PxmRRS)H%&$1-)z7jELS}!u!zQ?A^Y{Tv4QVt*vd@uj-^t2fYRzQj zfxGR>-q|o$3sGn^#VzZ!QQx?h9`njeJry}@x?|k0-GTTA4y3t2E`3DZ!A~D?GiJup z)8%PK2^9OVRlP(24P^4_<|D=H^7}WlWu#LgsdHzB%cPy|f8dD3|A^mh4WXxhLTVu_ z@abE{6Saz|Y{rXYPd4$tfPYo}ef(oQWZ=4Bct-=_9`#Qgp4ma$n$`tOwq#&E18$B; z@Bp)bn3&rEi0>fWWZ@7k5WazfoX`SCO4jQWwVuo+$PmSZn^Hz?O(-tW@*DGxuf)V1 zO_xm&;NVCaHD4dqt(-MlszI3F-p?0!-e$fbiCeuaw66h^TTDLWuaV<@C-`=Xe5WL) zwooG7h>4&*)p3pKMS3O!4>-4jQUN}iAMQ)2*70?hP~)TzzR?-f@?Aqy$$1Iy8VGG$ zMM?8;j!pUX7QQD$gRc_#+=raAS577ga-w?jd`vCiN5lu)dEUkkUPl9!?{$IJNxQys z*E4e$eF&n&+AMRQR2gcaFEjAy*r)G!s(P6D&TfoApMFC_*Ftx0|D0@E-=B7tezU@d zZ{hGiN;YLIoSeRS;9o%dEua4b%4R3;$SugDjP$x;Z!M!@QibuSBb)HY!3zJ7M;^jw zlx6AD50FD&p3JyP*>o+t9YWW8(7P2t!VQQ21pHJOcG_SXQD;(5aX#M6x##5H_Re>6lPyDCjxr*R(+HE%c&QN+b^tbT zXBJk?p)zhJj#I?&Y2n&~XiytG9!1ox;bw5Rbj~)7c(MFBb4>IiRATdhg zmiEFlj@S_hwYYI(ki{}&<;_7(Z0Qkfq>am z&LtL=2qc7rWguk3BtE4zL41@#S;NN*-jWw|7Kx7H7~_%7fPt;TIX}Ubo>;Rmj94V> zNB1=;-9AR7s`Pxn}t_6^3ahlq53e&!Lh85uG zec0vJY_6e`tg7LgfrJ3k!DjR)Bi#L@DHIrZ`sK=<5O0Ip!fxGf*OgGSpP@Hbbe&$9 z;ZI}8lEoC2_7;%L2=w?tb%1oL0V+=Z`7b=P&lNGY;yVBazXRYu;+cQDKvm*7NCxu&i;zub zAJh#11%?w>E2rf2e~C4+rAb-&$^vsdACs7 z@|Ra!OfVM(ke{vyiqh7puf&Yp6cd6{DptUteYfIRWG3pI+5< zBVBI_xkBAc<(pcb$!Y%dTW(b;B;2pOI-(QCsLv@U-D1XJ z(Gk8Q3l7Ws46Aktuj>|s{$6zA&xCPuXL-kB`CgYMs}4IeyG*P51IDwW?8UNQd+$i~ zlxOPtSi5L|gJcF@DwmJA5Ju8HEJ>o{{upwIpb!f{2(vLNBw`7xMbvcw<^{Fj@E~1( z?w`iIMieunS#>nXlmUcSMU+D3rX28f?s7z;X=se6bo8;5vM|O^(D6{A9*ChnGH!RG zP##3>LDC3jZPE4PH32AxrqPk|yIIrq~`aL-=}`okhNu9aT%q z1b)7iJ)CN=V#Ly84N_r7U^SH2FGdE5FpTO2 z630TF$P>GNMu8`rOytb(lB2};`;P4YNwW1<5d3Q~AX#P0aX}R2b2)`rgkp#zTxcGj zAV^cvFbhP|JgWrq_e`~exr~sIR$6p5V?o4Wym3kQ3HA+;Pr$bQ0(PmADVO%MKL!^q z?zAM8j1l4jrq|5X+V!8S*2Wl@=7*pPgciTVK6kS1Ge zMsd_u6DFK$jTnvVtE;qa+8(1sGBu~n&F%dh(&c(Zs4Fc#A=gG^^%^AyH}1^?|8quj zl@Z47h$){PlELJgYZCIHHL= z{U8O>Tw4x3<1{?$8>k-P<}1y9DmAZP_;(3Y*{Sk^H^A=_iSJ@+s5ktgwTXz_2$~W9>VVZsfwCm@s0sQ zeB50_yu@uS+e7QoPvdCwDz{prjo(AFwR%C?z`EL{1`|coJHQTk^nX=tvs1<0arUOJ z!^`*x&&BvTYmemyZ)2p~{%eYX=JVR?DYr(rNgqRMA5E1PR1Iw=prk=L2ldy3r3Vg@27IZx43+ywyzr-X*p*d@tZV+!U#~$-q=8c zgdSuh#r?b4GhEGNai)ayHQpk>5(%j5c@C1K3(W1pb~HeHpaqijJZa-e6vq_8t-^M^ zBJxq|MqZc?pjXPIH}70a5vt!IUh;l}<>VX<-Qcv^u@5(@@M2CHSe_hD$VG-eiV^V( zj7*9T0?di?P$FaD6oo?)<)QT>Npf6Og!GO^GmPV(Km0!=+dE&bk#SNI+C9RGQ|{~O*VC+tXK3!n`5 zHfl6>lwf_aEVV3`0T!aHNZLsj$paS$=LL(?b!Czaa5bbSuZ6#$_@LK<(7yrrl+80| z{tOFd=|ta2Z`^ssozD9BINn45NxUeCQis?-BKmU*Kt=FY-NJ+)8S1ecuFtN-M?&42 zl2$G>u!iNhAk*HoJ^4v^9#ORYp5t^wDj6|lx~5w45#E5wVqI1JQ~9l?nPp1YINf++ zMAdSif~_ETv@Er(EFBI^@L4BULFW>)NI+ejHFP*T}UhWNN`I)RRS8za? z*@`1>9ZB}An%aT5K=_2iQmfE;GcBVHLF!$`I99o5GO`O%O_zLr9AG18>&^HkG(;=V z%}c!OBQ~?MX(9h~tajX{=x)+!cbM7$YzTlmsPOdp2L-?GoW`@{lY9U3f;OUo*BwRB z8A+nv(br0-SH#VxGy#ZrgnGD(=@;HME;yd46EgWJ`EL%oXc&lFpc@Y}^>G(W>h_v_ zlN!`idhX+OjL+~T?19sroAFVGfa5tX-D49w$1g2g_-T|EpHL6}K_aX4$K=LTvwtlF zL*z}j{f+Uoe7{-px3_5iKPA<_7W=>Izkk)!l9ez2w%vi(?Y;i8AxRNLSOGDzNoqoI zP!1uAl}r=_871(G?y`i&)-7{u=%nxk7CZ_Qh#!|ITec zwQn`33GTUM`;D2POWnkqngqJhJRlM>CTONzTG}>^Q0wUunQyn|TAiHzyX2_%ATx%P z%7gW)%4rA9^)M<_%k@`Y?RbC<29sWU&5;@|9thf2#zf8z12$hRcZ!CSb>kUp=4N#y zl3hE#y6>kkA8VY2`W`g5Ip?2qC_BY$>R`iGQLhz2-S>x(RuWv)SPaGdl^)gGw7tjR zH@;jwk!jIaCgSg_*9iF|a);sRUTq30(8I(obh^|}S~}P4U^BIGYqcz;MPpC~Y@k_m zaw4WG1_vz2GdCAX!$_a%GHK**@IrHSkGoN>)e}>yzUTm52on`hYot7cB=oA-h1u|R ztH$11t?54Qg2L+i33FPFKKRm1aOjKST{l1*(nps`>sv%VqeVMWjl5+Gh+9);hIP8? zA@$?}Sc z3qIRpba+y5yf{R6G(u8Z^vkg0Fu&D-7?1s=QZU`Ub{-!Y`I?AGf1VNuc^L3v>)>i# z{DV9W$)>34wnzAXUiV^ZpYKw>UElrN_5Xj6{r_3| z$X5PK`e5$7>~9Dj7gK5ash(dvs`vwfk}&RD`>04;j62zoXESkFBklYaKm5seyiX(P zqQ-;XxlV*yg?Dhlx%xt!b0N3GHp@(p$A;8|%# zZ5m2KL|{on4nr>2_s9Yh=r5ScQ0;aMF)G$-9-Ca6%wA`Pa)i?NGFA|#Yi?{X-4ZO_ z^}%7%vkzvUHa$-^Y#aA+aiR5sa%S|Ebyn`EV<3Pc?ax_f>@sBZF1S;7y$CXd5t5=WGsTKBk8$OfH4v|0?0I=Yp}7c=WBSCg!{0n)XmiU;lfx)**zZaYqmDJelxk$)nZyx5`x$6R|fz(;u zEje5Dtm|a%zK!!tk3{i9$I2b{vXNFy%Bf{50X!x{98+BsDr_u9i>G5%*sqEX|06J0 z^IY{UcEbj6LDwuMh7cH`H@9sVt1l1#8kEQ(LyT@&+K}(ReE`ux8gb0r6L_#bDUo^P z3Ka2lRo52Hdtl_%+pwVs14=q`{d^L58PsU@AMf(hENumaxM{7iAT5sYmWh@hQCO^ zK&}ijo=`VqZ#a3vE?`7QW0ZREL17ZvDfdqKGD?0D4fg{7v%|Yj&_jcKJAB)>=*RS* zto8p6@k%;&^ZF>hvXm&$PCuEp{uqw3VPG$9VMdW5$w-fy2CNNT>E;>ejBgy-m_6`& z97L1p{%srn@O_JQgFpa_#f(_)eb#YS>o>q3(*uB;uZb605(iqM$=NK{nHY=+X2*G) zO3-_Xh%aG}fHWe*==58zBwp%&`mge<8uq8;xIxOd=P%9EK!34^E9sk|(Zq1QSz-JVeP12Fp)-`F|KY$LPwUE?rku zY@OJ)Z9A!ojfzfeyJ9;zv2EM7ZQB)AR5xGa-tMn^bl)FmoIiVyJ@!~@%{}qXXD&Ns zPnfe5U+&ohKefILu_1mPfLGuapX@btta5C#gPB2cjk5m4T}Nfi+Vfka!Yd(L?-c~5 z#ZK4VeQEXNPc4r$K00Fg>g#_W!YZ)cJ?JTS<&68_$#cZT-ME`}tcwqg3#``3M3UPvn+pi}(VNNx6y zFIMVb6OwYU(2`at$gHba*qrMVUl8xk5z-z~fb@Q3Y_+aXuEKH}L+>eW__!IAd@V}L zkw#s%H0v2k5-=vh$^vPCuAi22Luu3uKTf6fPo?*nvj$9(u)4$6tvF-%IM+3pt*cgs z_?wW}J7VAA{_~!?))?s6{M=KPpVhg4fNuU*|3THp@_(q!b*hdl{fjRVFWtu^1dV(f z6iOux9hi&+UK=|%M*~|aqFK{Urfl!TA}UWY#`w(0P!KMe1Si{8|o))Gy6d7;!JQYhgMYmXl?3FfOM2nQGN@~Ap6(G z3+d_5y@=nkpKAhRqf{qQ~k7Z$v&l&@m7Ppt#FSNzKPZM z8LhihcE6i=<(#87E|Wr~HKvVWhkll4iSK$^mUHaxgy8*K$_Zj;zJ`L$naPj+^3zTi z-3NTaaKnD5FPY-~?Tq6QHnmDDRxu0mh0D|zD~Y=vv_qig5r-cIbCpxlju&8Sya)@{ zsmv6XUSi)@(?PvItkiZEeN*)AE~I_?#+Ja-r8$(XiXei2d@Hi7Rx8+rZZb?ZLa{;@*EHeRQ-YDadz~M*YCM4&F-r;E#M+@CSJMJ0oU|PQ^ z=E!HBJDMQ2TN*Y(Ag(ynAL8%^v;=~q?s4plA_hig&5Z0x_^Oab!T)@6kRN$)qEJ6E zNuQjg|G7iwU(N8pI@_6==0CL;lRh1dQF#wePhmu@hADFd3B5KIH#dx(2A zp~K&;Xw}F_N6CU~0)QpQk7s$a+LcTOj1%=WXI(U=Dv!6 z{#<#-)2+gCyyv=Jw?Ab#PVkxPDeH|sAxyG`|Ys}A$PW4TdBv%zDz z^?lwrxWR<%Vzc8Sgt|?FL6ej_*e&rhqJZ3Y>k=X(^dytycR;XDU16}Pc9Vn0>_@H+ zQ;a`GSMEG64=JRAOg%~L)x*w{2re6DVprNp+FcNra4VdNjiaF0M^*>CdPkt(m150rCue?FVdL0nFL$V%5y6N z%eLr5%YN7D06k5ji5*p4v$UMM)G??Q%RB27IvH7vYr_^3>1D-M66#MN8tWGw>WED} z5AhlsanO=STFYFs)Il_0i)l)f<8qn|$DW7ZXhf5xI;m+7M5-%P63XFQrG9>DMqHc} zsgNU9nR`b}E^mL5=@7<1_R~j@q_2U^3h|+`7YH-?C=vme1C3m`Fe0HC>pjt6f_XMh zy~-i-8R46QNYneL4t@)<0VU7({aUO?aH`z4V2+kxgH5pYD5)wCh75JqQY)jIPN=U6 z+qi8cGiOtXG2tXm;_CfpH9ESCz#i5B(42}rBJJF$jh<1sbpj^8&L;gzGHb8M{of+} zzF^8VgML2O9nxBW7AvdEt90vp+#kZxWf@A)o9f9}vKJy9NDBjBW zSt=Hcs=YWCwnfY1UYx*+msp{g!w0HC<_SM!VL1(I2PE?CS}r(eh?{I)mQixmo5^p# zV?2R!R@3GV6hwTCrfHiK#3Orj>I!GS2kYhk1S;aFBD_}u2v;0HYFq}Iz1Z(I4oca4 zxquja8$+8JW_EagDHf$a1OTk5S97umGSDaj)gH=fLs9>_=XvVj^Xj9a#gLdk=&3tl zfmK9MNnIX9v{?%xdw7568 zNrZ|roYs(vC4pHB5RJ8>)^*OuyNC>x7ad)tB_}3SgQ96+-JT^Qi<`xi=)_=$Skwv~ zdqeT9Pa`LYvCAn&rMa2aCDV(TMI#PA5g#RtV|CWpgDYRA^|55LLN^uNh*gOU>Z=a06qJ;$C9z8;n-Pq=qZnc1zUwJ@t)L;&NN+E5m zRkQ(SeM8=l-aoAKGKD>!@?mWTW&~)uF2PYUJ;tB^my`r9n|Ly~0c%diYzqs9W#FTjy?h&X3TnH zXqA{QI82sdjPO->f=^K^f>N`+B`q9&rN0bOXO79S&a9XX8zund(kW7O76f4dcWhIu zER`XSMSFbSL>b;Rp#`CuGJ&p$s~G|76){d?xSA5wVg##_O0DrmyEYppyBr%fyWbbv zp`K84JwRNP$d-pJ!Qk|(RMr?*!wi1if-9G#0p>>1QXKXWFy)eB3ai)l3601q8!9JC zvU#ZWWDNKq9g6fYs?JQ)Q4C_cgTy3FhgKb8s&m)DdmL5zhNK#8wWg!J*7G7Qhe9VU zha?^AQTDpYcuN!B+#1dE*X{<#!M%zfUQbj=zLE{dW0XeQ7-oIsGY6RbkP2re@Q{}r_$iiH0xU%iN*ST`A)-EH6eaZB$GA#v)cLi z*MpA(3bYk$oBDKAzu^kJoSUsDd|856DApz={3u8sbQV@JnRkp2nC|)m;#T=DvIL-O zI4vh;g7824l}*`_p@MT4+d`JZ2%6NQh=N9bmgJ#q!hK@_<`HQq3}Z8Ij>3%~<*= zcv=!oT#5xmeGI92lqm9sGVE%#X$ls;St|F#u!?5Y7syhx6q#MVRa&lBmmn%$C0QzU z);*ldgwwCmzM3uglr}!Z2G+?& zf%Dpo&mD%2ZcNFiN-Z0f;c_Q;A%f@>26f?{d1kxIJD}LxsQkB47SAdwinfMILZdN3 zfj^HmTzS3Ku5BxY>ANutS8WPQ-G>v4^_Qndy==P3pDm+Xc?>rUHl-4+^%Sp5atOja z2oP}ftw-rqnb}+khR3CrRg^ibi6?QYk1*i^;kQGirQ=uB9Sd1NTfT-Rbv;hqnY4neE5H1YUrjS2m+2&@uXiAo- zrKUX|Ohg7(6F(AoP~tj;NZlV#xsfo-5reuQHB$&EIAhyZk;bL;k9ouDmJNBAun;H& zn;Of1z_Qj`x&M;5X;{s~iGzBQTY^kv-k{ksbE*Dl%Qf%N@hQCfY~iUw!=F-*$cpf2 z3wix|aLBV0b;W@z^%7S{>9Z^T^fLOI68_;l@+Qzaxo`nAI8emTV@rRhEKZ z?*z_{oGdI~R*#<2{bkz$G~^Qef}$*4OYTgtL$e9q!FY7EqxJ2`zk6SQc}M(k(_MaV zSLJnTXw&@djco1~a(vhBl^&w=$fa9{Sru>7g8SHahv$&Bl(D@(Zwxo_3r=;VH|uc5 zi1Ny)J!<(KN-EcQ(xlw%PNwK8U>4$9nVOhj(y0l9X^vP1TA>r_7WtSExIOsz`nDOP zs}d>Vxb2Vo2e5x8p(n~Y5ggAyvib>d)6?)|E@{FIz?G3PVGLf7-;BxaP;c?7ddH$z zA+{~k^V=bZuXafOv!RPsE1GrR3J2TH9uB=Z67gok+u`V#}BR86hB1xl}H4v`F+mRfr zYhortD%@IGfh!JB(NUNSDh+qDz?4ztEgCz&bIG-Wg7w-ua4ChgQR_c+z8dT3<1?uX z*G(DKy_LTl*Ea!%v!RhpCXW1WJO6F`bgS-SB;Xw9#! z<*K}=#wVu9$`Yo|e!z-CPYH!nj7s9dEPr-E`DXUBu0n!xX~&|%#G=BeM?X@shQQMf zMvr2!y7p_gD5-!Lnm|a@z8Of^EKboZsTMk%5VsJEm>VsJ4W7Kv{<|#4f-qDE$D-W>gWT%z-!qXnDHhOvLk=?^a1*|0j z{pW{M0{#1VcR5;F!!fIlLVNh_Gj zbnW(_j?0c2q$EHIi@fSMR{OUKBcLr{Y&$hrM8XhPByyZaXy|dd&{hYQRJ9@Fn%h3p7*VQolBIV@Eq`=y%5BU~3RPa^$a?ixp^cCg z+}Q*X+CW9~TL29@OOng(#OAOd!)e$d%sr}^KBJ-?-X&|4HTmtemxmp?cT3uA?md4% zT8yZ0U;6Rg6JHy3fJae{6TMGS?ZUX6+gGTT{Q{)SI85$5FD{g-eR%O0KMpWPY`4@O zx!hen1*8^E(*}{m^V_?}(b5k3hYo=T+$&M32+B`}81~KKZhY;2H{7O-M@vbCzuX0n zW-&HXeyr1%I3$@ns-V1~Lb@wIpkmx|8I~ob1Of7i6BTNysEwI}=!nU%q7(V_^+d*G z7G;07m(CRTJup!`cdYi93r^+LY+`M*>aMuHJm(A8_O8C#A*$!Xvddgpjx5)?_EB*q zgE8o5O>e~9IiSC@WtZpF{4Bj2J5eZ>uUzY%TgWF7wdDE!fSQIAWCP)V{;HsU3ap?4 znRsiiDbtN7i9hapO;(|Ew>Ip2TZSvK9Z^N21%J?OiA_&eP1{(Pu_=%JjKy|HOardq ze?zK^K zA%sjF64*Wufad%H<) z^|t>e*h+Z1#l=5wHexzt9HNDNXgM=-OPWKd^5p!~%SIl>Fo&7BvNpbf8{NXmH)o{r zO=aBJ;meX1^{O%q;kqdw*5k!Y7%t_30 zy{nGRVc&5qt?dBwLs+^Sfp;f`YVMSB#C>z^a9@fpZ!xb|b-JEz1LBX7ci)V@W+kvQ89KWA0T~Lj$aCcfW#nD5bt&Y_< z-q{4ZXDqVg?|0o)j1%l0^_it0WF*LCn-+)c!2y5yS7aZIN$>0LqNnkujV*YVes(v$ zY@_-!Q;!ZyJ}Bg|G-~w@or&u0RO?vlt5*9~yeoPV_UWrO2J54b4#{D(D>jF(R88u2 zo#B^@iF_%S>{iXSol8jpmsZuJ?+;epg>k=$d`?GSegAVp3n$`GVDvK${N*#L_1`44 z{w0fL{2%)0|E+qgZtjX}itZz^KJt4Y;*8uSK}Ft38+3>j|K(PxIXXR-t4VopXo#9# zt|F{LWr-?34y`$nLBVV_*UEgA6AUI65dYIbqpNq9cl&uLJ0~L}<=ESlOm?Y-S@L*d z<7vt}`)TW#f%Rp$Q}6@3=j$7Tze@_uZO@aMn<|si{?S}~maII`VTjs&?}jQ4_cut9$)PEqMukwoXobzaKx^MV z2fQwl+;LSZ$qy%Tys0oo^K=jOw$!YwCv^ei4NBVauL)tN%=wz9M{uf{IB(BxK|lT*pFkmNK_1tV`nb%jH=a0~VNq2RCKY(rG7jz!-D^k)Ec)yS%17pE#o6&eY+ z^qN(hQT$}5F(=4lgNQhlxj?nB4N6ntUY6(?+R#B?W3hY_a*)hnr4PA|vJ<6p`K3Z5Hy z{{8(|ux~NLUW=!?9Qe&WXMTAkQnLXg(g=I@(VG3{HE13OaUT|DljyWXPs2FE@?`iU z4GQlM&Q=T<4&v@Fe<+TuXiZQT3G~vZ&^POfmI1K2h6t4eD}Gk5XFGpbj1n_g*{qmD6Xy z`6Vv|lLZtLmrnv*{Q%xxtcWVj3K4M%$bdBk_a&ar{{GWyu#ljM;dII;*jP;QH z#+^o-A4np{@|Mz+LphTD0`FTyxYq#wY)*&Ls5o{0z9yg2K+K7ZN>j1>N&;r+Z`vI| zDzG1LJZ+sE?m?>x{5LJx^)g&pGEpY=fQ-4}{x=ru;}FL$inHemOg%|R*ZXPodU}Kh zFEd5#+8rGq$Y<_?k-}r5zgQ3jRV=ooHiF|@z_#D4pKVEmn5CGV(9VKCyG|sT9nc=U zEoT67R`C->KY8Wp-fEcjjFm^;Cg(ls|*ABVHq8clBE(;~K^b+S>6uj70g? z&{XQ5U&!Z$SO7zfP+y^8XBbiu*Cv-yJG|l-oe*!s5$@Lh_KpxYL2sx`B|V=dETN>5K+C+CU~a_3cI8{vbu$TNVdGf15*>D zz@f{zIlorkY>TRh7mKuAlN9A0>N>SV`X)+bEHms=mfYTMWt_AJtz_h+JMmrgH?mZt zm=lfdF`t^J*XLg7v+iS)XZROygK=CS@CvUaJo&w2W!Wb@aa?~Drtf`JV^cCMjngVZ zv&xaIBEo8EYWuML+vxCpjjY^s1-ahXJzAV6hTw%ZIy!FjI}aJ+{rE&u#>rs)vzuxz z+$5z=7W?zH2>Eb32dvgHYZtCAf!=OLY-pb4>Ae79rd68E2LkVPj-|jFeyqtBCCwiW zkB@kO_(3wFq)7qwV}bA=zD!*@UhT`geq}ITo%@O(Z5Y80nEX~;0-8kO{oB6|(4fQh z);73T!>3@{ZobPwRv*W?7m0Ml9GmJBCJd&6E?hdj9lV= z4flNfsc(J*DyPv?RCOx!MSvk(M952PJ-G|JeVxWVjN~SNS6n-_Ge3Q;TGE;EQvZg86%wZ`MB zSMQua(i*R8a75!6$QRO^(o7sGoomb+Y{OMy;m~Oa`;P9Yqo>?bJAhqXxLr7_3g_n>f#UVtxG!^F#1+y@os6x(sg z^28bsQ@8rw%Gxk-stAEPRbv^}5sLe=VMbkc@Jjimqjvmd!3E7+QnL>|(^3!R} zD-l1l7*Amu@j+PWLGHXXaFG0Ct2Q=}5YNUxEQHCAU7gA$sSC<5OGylNnQUa>>l%sM zyu}z6i&({U@x^hln**o6r2s-(C-L50tQvz|zHTqW!ir?w&V23tuYEDJVV#5pE|OJu z7^R!A$iM$YCe?8n67l*J-okwfZ+ZTkGvZ)tVPfR;|3gyFjF)8V zyXXN=!*bpyRg9#~Bg1+UDYCt0 ztp4&?t1X0q>uz;ann$OrZs{5*r`(oNvw=$7O#rD|Wuv*wIi)4b zGtq4%BX+kkagv3F9Id6~-c+1&?zny%w5j&nk9SQfo0k4LhdSU_kWGW7axkfpgR`8* z!?UTG*Zi_baA1^0eda8S|@&F z{)Rad0kiLjB|=}XFJhD(S3ssKlveFFmkN{Vl^_nb!o5M!RC=m)V&v2%e?ZoRC@h3> zJ(?pvToFd`*Zc@HFPL#=otWKwtuuQ_dT-Hr{S%pQX<6dqVJ8;f(o)4~VM_kEQkMR+ zs1SCVi~k>M`u1u2xc}>#D!V&6nOOh-E$O&SzYrjJdZpaDv1!R-QGA141WjQe2s0J~ zQ;AXG)F+K#K8_5HVqRoRM%^EduqOnS(j2)|ctA6Q^=|s_WJYU;Z%5bHp08HPL`YF2 zR)Ad1z{zh`=sDs^&V}J z%$Z$!jd7BY5AkT?j`eqMs%!Gm@T8)4w3GYEX~IwgE~`d|@T{WYHkudy(47brgHXx& zBL1yFG6!!!VOSmDxBpefy2{L_u5yTwja&HA!mYA#wg#bc-m%~8aRR|~AvMnind@zs zy>wkShe5&*un^zvSOdlVu%kHsEo>@puMQ`b1}(|)l~E{5)f7gC=E$fP(FC2=F<^|A zxeIm?{EE!3sO!Gr7e{w)Dx(uU#3WrFZ>ibmKSQ1tY?*-Nh1TDHLe+k*;{Rp!Bmd_m zb#^kh`Y*8l|9Cz2e{;RL%_lg{#^Ar+NH|3z*Zye>!alpt{z;4dFAw^^H!6ING*EFc z_yqhr8d!;%nHX9AKhFQZBGrSzfzYCi%C!(Q5*~hX>)0N`vbhZ@N|i;_972WSx*>LH z87?en(;2_`{_JHF`Sv6Wlps;dCcj+8IJ8ca6`DsOQCMb3n# z3)_w%FuJ3>fjeOOtWyq)ag|PmgQbC-s}KRHG~enBcIwqIiGW8R8jFeBNY9|YswRY5 zjGUxdGgUD26wOpwM#8a!Nuqg68*dG@VM~SbOroL_On0N6QdT9?)NeB3@0FCC?Z|E0 z6TPZj(AsPtwCw>*{eDEE}Gby>0q{*lI+g2e&(YQrsY&uGM{O~}(oM@YWmb*F zA0^rr5~UD^qmNljq$F#ARXRZ1igP`MQx4aS6*MS;Ot(1L5jF2NJ;de!NujUYg$dr# z=TEL_zTj2@>ZZN(NYCeVX2==~=aT)R30gETO{G&GM4XN<+!&W&(WcDP%oL8PyIVUC zs5AvMgh6qr-2?^unB@mXK*Dbil^y-GTC+>&N5HkzXtozVf93m~xOUHn8`HpX=$_v2 z61H;Z1qK9o;>->tb8y%#4H)765W4E>TQ1o0PFj)uTOPEvv&}%(_mG0ISmyhnQV33Z$#&yd{ zc{>8V8XK$3u8}04CmAQ#I@XvtmB*s4t8va?-IY4@CN>;)mLb_4!&P3XSw4pA_NzDb zORn!blT-aHk1%Jpi>T~oGLuh{DB)JIGZ9KOsciWs2N7mM1JWM+lna4vkDL?Q)z_Ct z`!mi0jtr+4*L&N7jk&LodVO#6?_qRGVaucqVB8*us6i3BTa^^EI0x%EREQSXV@f!lak6Wf1cNZ8>*artIJ(ADO*=<-an`3zB4d*oO*8D1K!f z*A@P1bZCNtU=p!742MrAj%&5v%Xp_dSX@4YCw%F|%Dk=u|1BOmo)HsVz)nD5USa zR~??e61sO(;PR)iaxK{M%QM_rIua9C^4ppVS$qCT9j2%?*em?`4Z;4@>I(c%M&#cH z>4}*;ej<4cKkbCAjjDsyKS8rIm90O)Jjgyxj5^venBx&7B!xLmzxW3jhj7sR(^3Fz z84EY|p1NauwXUr;FfZjdaAfh%ivyp+^!jBjJuAaKa!yCq=?T_)R!>16?{~p)FQ3LDoMyG%hL#pR!f@P%*;#90rs_y z@9}@r1BmM-SJ#DeuqCQk=J?ixDSwL*wh|G#us;dd{H}3*-Y7Tv5m=bQJMcH+_S`zVtf;!0kt*(zwJ zs+kedTm!A}cMiM!qv(c$o5K%}Yd0|nOd0iLjus&;s0Acvoi-PFrWm?+q9f^FslxGi z6ywB`QpL$rJzWDg(4)C4+!2cLE}UPCTBLa*_=c#*$b2PWrRN46$y~yST3a2$7hEH= zNjux+wna^AzQ=KEa_5#9Ph=G1{S0#hh1L3hQ`@HrVnCx{!fw_a0N5xV(iPdKZ-HOM za)LdgK}1ww*C_>V7hbQnTzjURJL`S%`6nTHcgS+dB6b_;PY1FsrdE8(2K6FN>37!62j_cBlui{jO^$dPkGHV>pXvW0EiOA zqW`YaSUBWg_v^Y5tPJfWLcLpsA8T zG)!x>pKMpt!lv3&KV!-um= zKCir6`bEL_LCFx4Z5bAFXW$g3Cq`?Q%)3q0r852XI*Der*JNuKUZ`C{cCuu8R8nkt z%pnF>R$uY8L+D!V{s^9>IC+bmt<05h**>49R*#vpM*4i0qRB2uPbg8{{s#9yC;Z18 zD7|4m<9qneQ84uX|J&f-g8a|nFKFt34@Bt{CU`v(SYbbn95Q67*)_Esl_;v291s=9 z+#2F2apZU4Tq=x+?V}CjwD(P=U~d<=mfEFuyPB`Ey82V9G#Sk8H_Ob_RnP3s?)S_3 zr%}Pb?;lt_)Nf>@zX~D~TBr;-LS<1I##8z`;0ZCvI_QbXNh8Iv)$LS=*gHr;}dgb=w5$3k2la1keIm|=7<-JD>)U%=Avl0Vj@+&vxn zt-)`vJxJr88D&!}2^{GPXc^nmRf#}nb$4MMkBA21GzB`-Or`-3lq^O^svO7Vs~FdM zv`NvzyG+0T!P8l_&8gH|pzE{N(gv_tgDU7SWeiI-iHC#0Ai%Ixn4&nt{5y3(GQs)i z&uA;~_0shP$0Wh0VooIeyC|lak__#KVJfxa7*mYmZ22@(<^W}FdKjd*U1CqSjNKW% z*z$5$=t^+;Ui=MoDW~A7;)Mj%ibX1_p4gu>RC}Z_pl`U*{_z@+HN?AF{_W z?M_X@o%w8fgFIJ$fIzBeK=v#*`mtY$HC3tqw7q^GCT!P$I%=2N4FY7j9nG8aIm$c9 zeKTxVKN!UJ{#W)zxW|Q^K!3s;(*7Gbn;e@pQBCDS(I|Y0euK#dSQ_W^)sv5pa%<^o zyu}3d?Lx`)3-n5Sy9r#`I{+t6x%I%G(iewGbvor&I^{lhu-!#}*Q3^itvY(^UWXgvthH52zLy&T+B)Pw;5>4D6>74 zO_EBS)>l!zLTVkX@NDqyN2cXTwsUVao7$HcqV2%t$YzdAC&T)dwzExa3*kt9d(}al zA~M}=%2NVNUjZiO7c>04YH)sRelXJYpWSn^aC$|Ji|E13a^-v2MB!Nc*b+=KY7MCm zqIteKfNkONq}uM;PB?vvgQvfKLPMB8u5+Am=d#>g+o&Ysb>dX9EC8q?D$pJH!MTAqa=DS5$cb+;hEvjwVfF{4;M{5U&^_+r zvZdu_rildI!*|*A$TzJ&apQWV@p{!W`=?t(o0{?9y&vM)V)ycGSlI3`;ps(vf2PUq zX745#`cmT*ra7XECC0gKkpu2eyhFEUb?;4@X7weEnLjXj_F~?OzL1U1L0|s6M+kIhmi%`n5vvDALMagi4`wMc=JV{XiO+^ z?s9i7;GgrRW{Mx)d7rj)?(;|b-`iBNPqdwtt%32se@?w4<^KU&585_kZ=`Wy^oLu9 z?DQAh5z%q;UkP48jgMFHTf#mj?#z|=w= z(q6~17Vn}P)J3M?O)x))%a5+>TFW3No~TgP;f}K$#icBh;rSS+R|}l鯊%1Et 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⁢ zv5o9#E7!G0XmdzfsS{efPNi`1b44~SZ4Z8fuX!I}#8g+(wxzQwUT#Xb2(tbY1+EUhGKoT@KEU9Ktl>_0 z%bjDJg;#*gtJZv!-Zs`?^}v5eKmnbjqlvnSzE@_SP|LG_PJ6CYU+6zY6>92%E+ z=j@TZf-iW4(%U{lnYxQA;7Q!b;^brF8n0D>)`q5>|WDDXLrqYU_tKN2>=#@~OE7grMnNh?UOz-O~6 z6%rHy{#h9K0AT+lDC7q4{hw^|q6*Ry;;L%Q@)Ga}$60_q%D)rv(CtS$CQbpq9|y1e zRSrN4;$Jyl{m5bZw`$8TGvb}(LpY{-cQ)fcyJv7l3S52TLXVDsphtv&aPuDk1OzCA z4A^QtC(!11`IsNx_HnSy?>EKpHJWT^wmS~hc^p^zIIh@9f6U@I2 zC=Mve{j2^)mS#U$e{@Q?SO6%LDsXz@SY+=cK_QMmXBIU)j!$ajc-zLx3V60EXJ!qC zi<%2x8Q24YN+&8U@CIlN zrZkcT9yh%LrlGS9`G)KdP(@9Eo-AQz@8GEFWcb7U=a0H^ZVbLmz{+&M7W(nXJ4sN8 zJLR7eeK(K8`2-}j(T7JsO`L!+CvbueT%izanm-^A1Dn{`1Nw`9P?cq;7no+XfC`K(GO9?O^5zNIt4M+M8LM0=7Gz8UA@Z0N+lg+cX)NfazRu z5D)~HA^(u%w^cz+@2@_#S|u>GpB+j4KzQ^&Wcl9f z&hG#bCA(Yk0D&t&aJE^xME^&E-&xGHhXn%}psEIj641H+Nl-}boj;)Zt*t(4wZ5DN z@GXF$bL=&pBq-#vkTkh>7hl%K5|3 z{`Vn9b$iR-SoGENp}bn4;fR3>9sA%X2@1L3aE9yTra;Wb#_`xWwLSLdfu+PAu+o3| zGVnpzPr=ch{uuoHjtw7+_!L_2;knQ!DuDl0R`|%jr+}jFzXtrHIKc323?JO{l&;VF z*L1+}JU7%QJOg|5|Tc|D8fN zJORAg=_vsy{ak|o);@)Yh8Lkcg@$FG3k@ep36BRa^>~UmnRPziS>Z=`Jb2x*Q#`%A zU*i3&Vg?TluO@X0O;r2Jl6LKLUOVhSqg1*qOt^|8*c7 zo(298@+r$k_wQNGHv{|$tW(T8L+4_`FQ{kEW5Jgg{yf7ey4ss_(SNKfz(N9lx&a;< je(UuV8hP?p&}TPdm1I$XmG#(RzlD&B2izSj9sl%y5~4qc diff --git a/core/gradle/wrapper/gradle-wrapper.properties b/core/gradle/wrapper/gradle-wrapper.properties index ac72c34e..9355b415 100644 --- a/core/gradle/wrapper/gradle-wrapper.properties +++ b/core/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/core/gradlew b/core/gradlew index 0adc8e1a..f5feea6d 100644 --- a/core/gradlew +++ b/core/gradlew @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # @@ -55,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -84,7 +86,8 @@ done # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -145,7 +148,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -153,7 +156,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -202,11 +205,11 @@ fi # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ diff --git a/core/gradlew.bat b/core/gradlew.bat index 93e3f59f..9d21a218 100644 --- a/core/gradlew.bat +++ b/core/gradlew.bat @@ -13,6 +13,8 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## @@ -43,11 +45,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -57,11 +59,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail diff --git a/fabric/1.18/gradle/wrapper/gradle-wrapper.jar b/fabric/1.18/gradle/wrapper/gradle-wrapper.jar index c1962a79e29d3e0ab67b14947c167a862655af9b..a4b76b9530d66f5e68d973ea569d8e19de379189 100644 GIT binary patch literal 43583 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 yu?e%!_ptzGB|8GrCfu%p?(_ zQccdaaVK$5bz;*rnyK{_SQYM>;aES6Qs^lj9lEs6_J+%nIiuQC*fN;z8md>r_~Mfl zU%p5Dt_YT>gQqfr@`cR!$NWr~+`CZb%dn;WtzrAOI>P_JtsB76PYe*<%H(y>qx-`Kq!X_; z<{RpAqYhE=L1r*M)gNF3B8r(<%8mo*SR2hu zccLRZwGARt)Hlo1euqTyM>^!HK*!Q2P;4UYrysje@;(<|$&%vQekbn|0Ruu_Io(w4#%p6ld2Yp7tlA`Y$cciThP zKzNGIMPXX%&Ud0uQh!uQZz|FB`4KGD?3!ND?wQt6!n*f4EmCoJUh&b?;B{|lxs#F- z31~HQ`SF4x$&v00@(P+j1pAaj5!s`)b2RDBp*PB=2IB>oBF!*6vwr7Dp%zpAx*dPr zb@Zjq^XjN?O4QcZ*O+8>)|HlrR>oD*?WQl5ri3R#2?*W6iJ>>kH%KnnME&TT@ZzrHS$Q%LC?n|e>V+D+8D zYc4)QddFz7I8#}y#Wj6>4P%34dZH~OUDb?uP%-E zwjXM(?Sg~1!|wI(RVuxbu)-rH+O=igSho_pDCw(c6b=P zKk4ATlB?bj9+HHlh<_!&z0rx13K3ZrAR8W)!@Y}o`?a*JJsD+twZIv`W)@Y?Amu_u zz``@-e2X}27$i(2=9rvIu5uTUOVhzwu%mNazS|lZb&PT;XE2|B&W1>=B58#*!~D&) zfVmJGg8UdP*fx(>Cj^?yS^zH#o-$Q-*$SnK(ZVFkw+er=>N^7!)FtP3y~Xxnu^nzY zikgB>Nj0%;WOltWIob|}%lo?_C7<``a5hEkx&1ku$|)i>Rh6@3h*`slY=9U}(Ql_< zaNG*J8vb&@zpdhAvv`?{=zDedJ23TD&Zg__snRAH4eh~^oawdYi6A3w8<Ozh@Kw)#bdktM^GVb zrG08?0bG?|NG+w^&JvD*7LAbjED{_Zkc`3H!My>0u5Q}m!+6VokMLXxl`Mkd=g&Xx z-a>m*#G3SLlhbKB!)tnzfWOBV;u;ftU}S!NdD5+YtOjLg?X}dl>7m^gOpihrf1;PY zvll&>dIuUGs{Qnd- zwIR3oIrct8Va^Tm0t#(bJD7c$Z7DO9*7NnRZorrSm`b`cxz>OIC;jSE3DO8`hX955ui`s%||YQtt2 z5DNA&pG-V+4oI2s*x^>-$6J?p=I>C|9wZF8z;VjR??Icg?1w2v5Me+FgAeGGa8(3S z4vg*$>zC-WIVZtJ7}o9{D-7d>zCe|z#<9>CFve-OPAYsneTb^JH!Enaza#j}^mXy1 z+ULn^10+rWLF6j2>Ya@@Kq?26>AqK{A_| zQKb*~F1>sE*=d?A?W7N2j?L09_7n+HGi{VY;MoTGr_)G9)ot$p!-UY5zZ2Xtbm=t z@dpPSGwgH=QtIcEulQNI>S-#ifbnO5EWkI;$A|pxJd885oM+ zGZ0_0gDvG8q2xebj+fbCHYfAXuZStH2j~|d^sBAzo46(K8n59+T6rzBwK)^rfPT+B zyIFw)9YC-V^rhtK`!3jrhmW-sTmM+tPH+;nwjL#-SjQPUZ53L@A>y*rt(#M(qsiB2 zx6B)dI}6Wlsw%bJ8h|(lhkJVogQZA&n{?Vgs6gNSXzuZpEyu*xySy8ro07QZ7Vk1!3tJphN_5V7qOiyK8p z#@jcDD8nmtYi1^l8ml;AF<#IPK?!pqf9D4moYk>d99Im}Jtwj6c#+A;f)CQ*f-hZ< z=p_T86jog%!p)D&5g9taSwYi&eP z#JuEK%+NULWus;0w32-SYFku#i}d~+{Pkho&^{;RxzP&0!RCm3-9K6`>KZpnzS6?L z^H^V*s!8<>x8bomvD%rh>Zp3>Db%kyin;qtl+jAv8Oo~1g~mqGAC&Qi_wy|xEt2iz zWAJEfTV%cl2Cs<1L&DLRVVH05EDq`pH7Oh7sR`NNkL%wi}8n>IXcO40hp+J+sC!W?!krJf!GJNE8uj zg-y~Ns-<~D?yqbzVRB}G>0A^f0!^N7l=$m0OdZuqAOQqLc zX?AEGr1Ht+inZ-Qiwnl@Z0qukd__a!C*CKuGdy5#nD7VUBM^6OCpxCa2A(X;e0&V4 zM&WR8+wErQ7UIc6LY~Q9x%Sn*Tn>>P`^t&idaOEnOd(Ufw#>NoR^1QdhJ8s`h^|R_ zXX`c5*O~Xdvh%q;7L!_!ohf$NfEBmCde|#uVZvEo>OfEq%+Ns7&_f$OR9xsihRpBb z+cjk8LyDm@U{YN>+r46?nn{7Gh(;WhFw6GAxtcKD+YWV?uge>;+q#Xx4!GpRkVZYu zzsF}1)7$?%s9g9CH=Zs+B%M_)+~*j3L0&Q9u7!|+T`^O{xE6qvAP?XWv9_MrZKdo& z%IyU)$Q95AB4!#hT!_dA>4e@zjOBD*Y=XjtMm)V|+IXzjuM;(l+8aA5#Kaz_$rR6! zj>#&^DidYD$nUY(D$mH`9eb|dtV0b{S>H6FBfq>t5`;OxA4Nn{J(+XihF(stSche7$es&~N$epi&PDM_N`As;*9D^L==2Q7Z2zD+CiU(|+-kL*VG+&9!Yb3LgPy?A zm7Z&^qRG_JIxK7-FBzZI3Q<;{`DIxtc48k> zc|0dmX;Z=W$+)qE)~`yn6MdoJ4co;%!`ddy+FV538Y)j(vg}5*k(WK)KWZ3WaOG!8 z!syGn=s{H$odtpqFrT#JGM*utN7B((abXnpDM6w56nhw}OY}0TiTG1#f*VFZr+^-g zbP10`$LPq_;PvrA1XXlyx2uM^mrjTzX}w{yuLo-cOClE8MMk47T25G8M!9Z5ypOSV zAJUBGEg5L2fY)ZGJb^E34R2zJ?}Vf>{~gB!8=5Z) z9y$>5c)=;o0HeHHSuE4U)#vG&KF|I%-cF6f$~pdYJWk_dD}iOA>iA$O$+4%@>JU08 zS`ep)$XLPJ+n0_i@PkF#ri6T8?ZeAot$6JIYHm&P6EB=BiaNY|aA$W0I+nz*zkz_z zkEru!tj!QUffq%)8y0y`T&`fuus-1p>=^hnBiBqD^hXrPs`PY9tU3m0np~rISY09> z`P3s=-kt_cYcxWd{de@}TwSqg*xVhp;E9zCsnXo6z z?f&Sv^U7n4`xr=mXle94HzOdN!2kB~4=%)u&N!+2;z6UYKUDqi-s6AZ!haB;@&B`? z_TRX0%@suz^TRdCb?!vNJYPY8L_}&07uySH9%W^Tc&1pia6y1q#?*Drf}GjGbPjBS zbOPcUY#*$3sL2x4v_i*Y=N7E$mR}J%|GUI(>WEr+28+V z%v5{#e!UF*6~G&%;l*q*$V?&r$Pp^sE^i-0$+RH3ERUUdQ0>rAq2(2QAbG}$y{de( z>{qD~GGuOk559Y@%$?N^1ApVL_a704>8OD%8Y%8B;FCt%AoPu8*D1 zLB5X>b}Syz81pn;xnB}%0FnwazlWfUV)Z-~rZg6~b z6!9J$EcE&sEbzcy?CI~=boWA&eeIa%z(7SE^qgVLz??1Vbc1*aRvc%Mri)AJaAG!p z$X!_9Ds;Zz)f+;%s&dRcJt2==P{^j3bf0M=nJd&xwUGlUFn?H=2W(*2I2Gdu zv!gYCwM10aeus)`RIZSrCK=&oKaO_Ry~D1B5!y0R=%!i2*KfXGYX&gNv_u+n9wiR5 z*e$Zjju&ODRW3phN925%S(jL+bCHv6rZtc?!*`1TyYXT6%Ju=|X;6D@lq$8T zW{Y|e39ioPez(pBH%k)HzFITXHvnD6hw^lIoUMA;qAJ^CU?top1fo@s7xT13Fvn1H z6JWa-6+FJF#x>~+A;D~;VDs26>^oH0EI`IYT2iagy23?nyJ==i{g4%HrAf1-*v zK1)~@&(KkwR7TL}L(A@C_S0G;-GMDy=MJn2$FP5s<%wC)4jC5PXoxrQBFZ_k0P{{s@sz+gX`-!=T8rcB(=7vW}^K6oLWMmp(rwDh}b zwaGGd>yEy6fHv%jM$yJXo5oMAQ>c9j`**}F?MCry;T@47@r?&sKHgVe$MCqk#Z_3S z1GZI~nOEN*P~+UaFGnj{{Jo@16`(qVNtbU>O0Hf57-P>x8Jikp=`s8xWs^dAJ9lCQ z)GFm+=OV%AMVqVATtN@|vp61VVAHRn87}%PC^RAzJ%JngmZTasWBAWsoAqBU+8L8u z4A&Pe?fmTm0?mK-BL9t+{y7o(7jm+RpOhL9KnY#E&qu^}B6=K_dB}*VlSEiC9fn)+V=J;OnN)Ta5v66ic1rG+dGAJ1 z1%Zb_+!$=tQ~lxQrzv3x#CPb?CekEkA}0MYSgx$Jdd}q8+R=ma$|&1a#)TQ=l$1tQ z=tL9&_^vJ)Pk}EDO-va`UCT1m#Uty1{v^A3P~83_#v^ozH}6*9mIjIr;t3Uv%@VeW zGL6(CwCUp)Jq%G0bIG%?{_*Y#5IHf*5M@wPo6A{$Um++Co$wLC=J1aoG93&T7Ho}P z=mGEPP7GbvoG!uD$k(H3A$Z))+i{Hy?QHdk>3xSBXR0j!11O^mEe9RHmw!pvzv?Ua~2_l2Yh~_!s1qS`|0~0)YsbHSz8!mG)WiJE| z2f($6TQtt6L_f~ApQYQKSb=`053LgrQq7G@98#igV>y#i==-nEjQ!XNu9 z~;mE+gtj4IDDNQJ~JVk5Ux6&LCSFL!y=>79kE9=V}J7tD==Ga+IW zX)r7>VZ9dY=V&}DR))xUoV!u(Z|%3ciQi_2jl}3=$Agc(`RPb z8kEBpvY>1FGQ9W$n>Cq=DIpski};nE)`p3IUw1Oz0|wxll^)4dq3;CCY@RyJgFgc# zKouFh!`?Xuo{IMz^xi-h=StCis_M7yq$u) z?XHvw*HP0VgR+KR6wI)jEMX|ssqYvSf*_3W8zVTQzD?3>H!#>InzpSO)@SC8q*ii- z%%h}_#0{4JG;Jm`4zg};BPTGkYamx$Xo#O~lBirRY)q=5M45n{GCfV7h9qwyu1NxOMoP4)jjZMxmT|IQQh0U7C$EbnMN<3)Kk?fFHYq$d|ICu>KbY_hO zTZM+uKHe(cIZfEqyzyYSUBZa8;Fcut-GN!HSA9ius`ltNebF46ZX_BbZNU}}ZOm{M2&nANL9@0qvih15(|`S~z}m&h!u4x~(%MAO$jHRWNfuxWF#B)E&g3ghSQ9|> z(MFaLQj)NE0lowyjvg8z0#m6FIuKE9lDO~Glg}nSb7`~^&#(Lw{}GVOS>U)m8bF}x zVjbXljBm34Cs-yM6TVusr+3kYFjr28STT3g056y3cH5Tmge~ASxBj z%|yb>$eF;WgrcOZf569sDZOVwoo%8>XO>XQOX1OyN9I-SQgrm;U;+#3OI(zrWyow3 zk==|{lt2xrQ%FIXOTejR>;wv(Pb8u8}BUpx?yd(Abh6? zsoO3VYWkeLnF43&@*#MQ9-i-d0t*xN-UEyNKeyNMHw|A(k(_6QKO=nKMCxD(W(Yop zsRQ)QeL4X3Lxp^L%wzi2-WVSsf61dqliPUM7srDB?Wm6Lzn0&{*}|IsKQW;02(Y&| zaTKv|`U(pSzuvR6Rduu$wzK_W-Y-7>7s?G$)U}&uK;<>vU}^^ns@Z!p+9?St1s)dG zK%y6xkPyyS1$~&6v{kl?Md6gwM|>mt6Upm>oa8RLD^8T{0?HC!Z>;(Bob7el(DV6x zi`I)$&E&ngwFS@bi4^xFLAn`=fzTC;aimE^!cMI2n@Vo%Ae-ne`RF((&5y6xsjjAZ zVguVoQ?Z9uk$2ON;ersE%PU*xGO@T*;j1BO5#TuZKEf(mB7|g7pcEA=nYJ{s3vlbg zd4-DUlD{*6o%Gc^N!Nptgay>j6E5;3psI+C3Q!1ZIbeCubW%w4pq9)MSDyB{HLm|k zxv-{$$A*pS@csolri$Ge<4VZ}e~78JOL-EVyrbxKra^d{?|NnPp86!q>t<&IP07?Z z^>~IK^k#OEKgRH+LjllZXk7iA>2cfH6+(e&9ku5poo~6y{GC5>(bRK7hwjiurqAiZ zg*DmtgY}v83IjE&AbiWgMyFbaRUPZ{lYiz$U^&Zt2YjG<%m((&_JUbZcfJ22(>bi5 z!J?<7AySj0JZ&<-qXX;mcV!f~>G=sB0KnjWca4}vrtunD^1TrpfeS^4dvFr!65knK zZh`d;*VOkPs4*-9kL>$GP0`(M!j~B;#x?Ba~&s6CopvO86oM?-? zOw#dIRc;6A6T?B`Qp%^<U5 z19x(ywSH$_N+Io!6;e?`tWaM$`=Db!gzx|lQ${DG!zb1Zl&|{kX0y6xvO1o z220r<-oaS^^R2pEyY;=Qllqpmue|5yI~D|iI!IGt@iod{Opz@*ml^w2bNs)p`M(Io z|E;;m*Xpjd9l)4G#KaWfV(t8YUn@A;nK^#xgv=LtnArX|vWQVuw3}B${h+frU2>9^ z!l6)!Uo4`5k`<<;E(ido7M6lKTgWezNLq>U*=uz&s=cc$1%>VrAeOoUtA|T6gO4>UNqsdK=NF*8|~*sl&wI=x9-EGiq*aqV!(VVXA57 zw9*o6Ir8Lj1npUXvlevtn(_+^X5rzdR>#(}4YcB9O50q97%rW2me5_L=%ffYPUSRc z!vv?Kv>dH994Qi>U(a<0KF6NH5b16enCp+mw^Hb3Xs1^tThFpz!3QuN#}KBbww`(h z7GO)1olDqy6?T$()R7y%NYx*B0k_2IBiZ14&8|JPFxeMF{vW>HF-Vi3+ZOI=+qP}n zw(+!WcTd~4ZJX1!ZM&y!+uyt=&i!+~d(V%GjH;-NsEEv6nS1TERt|RHh!0>W4+4pp z1-*EzAM~i`+1f(VEHI8So`S`akPfPTfq*`l{Fz`hS%k#JS0cjT2mS0#QLGf=J?1`he3W*;m4)ce8*WFq1sdP=~$5RlH1EdWm|~dCvKOi4*I_96{^95p#B<(n!d?B z=o`0{t+&OMwKcxiBECznJcfH!fL(z3OvmxP#oWd48|mMjpE||zdiTBdWelj8&Qosv zZFp@&UgXuvJw5y=q6*28AtxZzo-UUpkRW%ne+Ylf!V-0+uQXBW=5S1o#6LXNtY5!I z%Rkz#(S8Pjz*P7bqB6L|M#Er{|QLae-Y{KA>`^} z@lPjeX>90X|34S-7}ZVXe{wEei1<{*e8T-Nbj8JmD4iwcE+Hg_zhkPVm#=@b$;)h6 z<<6y`nPa`f3I6`!28d@kdM{uJOgM%`EvlQ5B2bL)Sl=|y@YB3KeOzz=9cUW3clPAU z^sYc}xf9{4Oj?L5MOlYxR{+>w=vJjvbyO5}ptT(o6dR|ygO$)nVCvNGnq(6;bHlBd zl?w-|plD8spjDF03g5ip;W3Z z><0{BCq!Dw;h5~#1BuQilq*TwEu)qy50@+BE4bX28+7erX{BD4H)N+7U`AVEuREE8 z;X?~fyhF-x_sRfHIj~6f(+^@H)D=ngP;mwJjxhQUbUdzk8f94Ab%59-eRIq?ZKrwD z(BFI=)xrUlgu(b|hAysqK<}8bslmNNeD=#JW*}^~Nrswn^xw*nL@Tx!49bfJecV&KC2G4q5a!NSv)06A_5N3Y?veAz;Gv+@U3R% z)~UA8-0LvVE{}8LVDOHzp~2twReqf}ODIyXMM6=W>kL|OHcx9P%+aJGYi_Om)b!xe zF40Vntn0+VP>o<$AtP&JANjXBn7$}C@{+@3I@cqlwR2MdwGhVPxlTIcRVu@Ho-wO` z_~Or~IMG)A_`6-p)KPS@cT9mu9RGA>dVh5wY$NM9-^c@N=hcNaw4ITjm;iWSP^ZX| z)_XpaI61<+La+U&&%2a z0za$)-wZP@mwSELo#3!PGTt$uy0C(nTT@9NX*r3Ctw6J~7A(m#8fE)0RBd`TdKfAT zCf@$MAxjP`O(u9s@c0Fd@|}UQ6qp)O5Q5DPCeE6mSIh|Rj{$cAVIWsA=xPKVKxdhg zLzPZ`3CS+KIO;T}0Ip!fAUaNU>++ZJZRk@I(h<)RsJUhZ&Ru9*!4Ptn;gX^~4E8W^TSR&~3BAZc#HquXn)OW|TJ`CTahk+{qe`5+ixON^zA9IFd8)kc%*!AiLu z>`SFoZ5bW-%7}xZ>gpJcx_hpF$2l+533{gW{a7ce^B9sIdmLrI0)4yivZ^(Vh@-1q zFT!NQK$Iz^xu%|EOK=n>ug;(7J4OnS$;yWmq>A;hsD_0oAbLYhW^1Vdt9>;(JIYjf zdb+&f&D4@4AS?!*XpH>8egQvSVX`36jMd>$+RgI|pEg))^djhGSo&#lhS~9%NuWfX zDDH;3T*GzRT@5=7ibO>N-6_XPBYxno@mD_3I#rDD?iADxX`! zh*v8^i*JEMzyN#bGEBz7;UYXki*Xr(9xXax(_1qVW=Ml)kSuvK$coq2A(5ZGhs_pF z$*w}FbN6+QDseuB9=fdp_MTs)nQf!2SlROQ!gBJBCXD&@-VurqHj0wm@LWX-TDmS= z71M__vAok|@!qgi#H&H%Vg-((ZfxPAL8AI{x|VV!9)ZE}_l>iWk8UPTGHs*?u7RfP z5MC&=c6X;XlUzrz5q?(!eO@~* zoh2I*%J7dF!!_!vXoSIn5o|wj1#_>K*&CIn{qSaRc&iFVxt*^20ngCL;QonIS>I5^ zMw8HXm>W0PGd*}Ko)f|~dDd%;Wu_RWI_d;&2g6R3S63Uzjd7dn%Svu-OKpx*o|N>F zZg=-~qLb~VRLpv`k zWSdfHh@?dp=s_X`{yxOlxE$4iuyS;Z-x!*E6eqmEm*j2bE@=ZI0YZ5%Yj29!5+J$4h{s($nakA`xgbO8w zi=*r}PWz#lTL_DSAu1?f%-2OjD}NHXp4pXOsCW;DS@BC3h-q4_l`<))8WgzkdXg3! zs1WMt32kS2E#L0p_|x+x**TFV=gn`m9BWlzF{b%6j-odf4{7a4y4Uaef@YaeuPhU8 zHBvRqN^;$Jizy+ z=zW{E5<>2gp$pH{M@S*!sJVQU)b*J5*bX4h>5VJve#Q6ga}cQ&iL#=(u+KroWrxa%8&~p{WEUF0il=db;-$=A;&9M{Rq`ouZ5m%BHT6%st%saGsD6)fQgLN}x@d3q>FC;=f%O3Cyg=Ke@Gh`XW za@RajqOE9UB6eE=zhG%|dYS)IW)&y&Id2n7r)6p_)vlRP7NJL(x4UbhlcFXWT8?K=%s7;z?Vjts?y2+r|uk8Wt(DM*73^W%pAkZa1Jd zNoE)8FvQA>Z`eR5Z@Ig6kS5?0h;`Y&OL2D&xnnAUzQz{YSdh0k zB3exx%A2TyI)M*EM6htrxSlep!Kk(P(VP`$p0G~f$smld6W1r_Z+o?=IB@^weq>5VYsYZZR@` z&XJFxd5{|KPZmVOSxc@^%71C@;z}}WhbF9p!%yLj3j%YOlPL5s>7I3vj25 z@xmf=*z%Wb4;Va6SDk9cv|r*lhZ`(y_*M@>q;wrn)oQx%B(2A$9(74>;$zmQ!4fN; z>XurIk-7@wZys<+7XL@0Fhe-f%*=(weaQEdR9Eh6>Kl-EcI({qoZqyzziGwpg-GM#251sK_ z=3|kitS!j%;fpc@oWn65SEL73^N&t>Ix37xgs= zYG%eQDJc|rqHFia0!_sm7`@lvcv)gfy(+KXA@E{3t1DaZ$DijWAcA)E0@X?2ziJ{v z&KOYZ|DdkM{}t+@{@*6ge}m%xfjIxi%qh`=^2Rwz@w0cCvZ&Tc#UmCDbVwABrON^x zEBK43FO@weA8s7zggCOWhMvGGE`baZ62cC)VHyy!5Zbt%ieH+XN|OLbAFPZWyC6)p z4P3%8sq9HdS3=ih^0OOlqTPbKuzQ?lBEI{w^ReUO{V?@`ARsL|S*%yOS=Z%sF)>-y z(LAQdhgAcuF6LQjRYfdbD1g4o%tV4EiK&ElLB&^VZHbrV1K>tHTO{#XTo>)2UMm`2 z^t4s;vnMQgf-njU-RVBRw0P0-m#d-u`(kq7NL&2T)TjI_@iKuPAK-@oH(J8?%(e!0Ir$yG32@CGUPn5w4)+9@8c&pGx z+K3GKESI4*`tYlmMHt@br;jBWTei&(a=iYslc^c#RU3Q&sYp zSG){)V<(g7+8W!Wxeb5zJb4XE{I|&Y4UrFWr%LHkdQ;~XU zgy^dH-Z3lmY+0G~?DrC_S4@=>0oM8Isw%g(id10gWkoz2Q%7W$bFk@mIzTCcIB(K8 zc<5h&ZzCdT=9n-D>&a8vl+=ZF*`uTvQviG_bLde*k>{^)&0o*b05x$MO3gVLUx`xZ z43j+>!u?XV)Yp@MmG%Y`+COH2?nQcMrQ%k~6#O%PeD_WvFO~Kct za4XoCM_X!c5vhRkIdV=xUB3xI2NNStK*8_Zl!cFjOvp-AY=D;5{uXj}GV{LK1~IE2 z|KffUiBaStRr;10R~K2VVtf{TzM7FaPm;Y(zQjILn+tIPSrJh&EMf6evaBKIvi42-WYU9Vhj~3< zZSM-B;E`g_o8_XTM9IzEL=9Lb^SPhe(f(-`Yh=X6O7+6ALXnTcUFpI>ekl6v)ZQeNCg2 z^H|{SKXHU*%nBQ@I3It0m^h+6tvI@FS=MYS$ZpBaG7j#V@P2ZuYySbp@hA# ze(kc;P4i_-_UDP?%<6>%tTRih6VBgScKU^BV6Aoeg6Uh(W^#J^V$Xo^4#Ekp ztqQVK^g9gKMTHvV7nb64UU7p~!B?>Y0oFH5T7#BSW#YfSB@5PtE~#SCCg3p^o=NkMk$<8- z6PT*yIKGrvne7+y3}_!AC8NNeI?iTY(&nakN>>U-zT0wzZf-RuyZk^X9H-DT_*wk= z;&0}6LsGtfVa1q)CEUPlx#(ED@-?H<1_FrHU#z5^P3lEB|qsxEyn%FOpjx z3S?~gvoXy~L(Q{Jh6*i~=f%9kM1>RGjBzQh_SaIDfSU_9!<>*Pm>l)cJD@wlyxpBV z4Fmhc2q=R_wHCEK69<*wG%}mgD1=FHi4h!98B-*vMu4ZGW~%IrYSLGU{^TuseqVgV zLP<%wirIL`VLyJv9XG_p8w@Q4HzNt-o;U@Au{7%Ji;53!7V8Rv0^Lu^Vf*sL>R(;c zQG_ZuFl)Mh-xEIkGu}?_(HwkB2jS;HdPLSxVU&Jxy9*XRG~^HY(f0g8Q}iqnVmgjI zfd=``2&8GsycjR?M%(zMjn;tn9agcq;&rR!Hp z$B*gzHsQ~aXw8c|a(L^LW(|`yGc!qOnV(ZjU_Q-4z1&0;jG&vAKuNG=F|H?@m5^N@ zq{E!1n;)kNTJ>|Hb2ODt-7U~-MOIFo%9I)_@7fnX+eMMNh>)V$IXesJpBn|uo8f~#aOFytCT zf9&%MCLf8mp4kwHTcojWmM3LU=#|{3L>E}SKwOd?%{HogCZ_Z1BSA}P#O(%H$;z7XyJ^sjGX;j5 zrzp>|Ud;*&VAU3x#f{CKwY7Vc{%TKKqmB@oTHA9;>?!nvMA;8+Jh=cambHz#J18x~ zs!dF>$*AnsQ{{82r5Aw&^7eRCdvcgyxH?*DV5(I$qXh^zS>us*I66_MbL8y4d3ULj z{S(ipo+T3Ag!+5`NU2sc+@*m{_X|&p#O-SAqF&g_n7ObB82~$p%fXA5GLHMC+#qqL zdt`sJC&6C2)=juQ_!NeD>U8lDVpAOkW*khf7MCcs$A(wiIl#B9HM%~GtQ^}yBPjT@ z+E=|A!Z?A(rwzZ;T}o6pOVqHzTr*i;Wrc%&36kc@jXq~+w8kVrs;%=IFdACoLAcCAmhFNpbP8;s`zG|HC2Gv?I~w4ITy=g$`0qMQdkijLSOtX6xW%Z9Nw<;M- zMN`c7=$QxN00DiSjbVt9Mi6-pjv*j(_8PyV-il8Q-&TwBwH1gz1uoxs6~uU}PrgWB zIAE_I-a1EqlIaGQNbcp@iI8W1sm9fBBNOk(k&iLBe%MCo#?xI$%ZmGA?=)M9D=0t7 zc)Q0LnI)kCy{`jCGy9lYX%mUsDWwsY`;jE(;Us@gmWPqjmXL+Hu#^;k%eT>{nMtzj zsV`Iy6leTA8-PndszF;N^X@CJrTw5IIm!GPeu)H2#FQitR{1p;MasQVAG3*+=9FYK zw*k!HT(YQorfQj+1*mCV458(T5=fH`um$gS38hw(OqVMyunQ;rW5aPbF##A3fGH6h z@W)i9Uff?qz`YbK4c}JzQpuxuE3pcQO)%xBRZp{zJ^-*|oryTxJ-rR+MXJ)!f=+pp z10H|DdGd2exhi+hftcYbM0_}C0ZI-2vh+$fU1acsB-YXid7O|=9L!3e@$H*6?G*Zp z%qFB(sgl=FcC=E4CYGp4CN>=M8#5r!RU!u+FJVlH6=gI5xHVD&k;Ta*M28BsxfMV~ zLz+@6TxnfLhF@5=yQo^1&S}cmTN@m!7*c6z;}~*!hNBjuE>NLVl2EwN!F+)0$R1S! zR|lF%n!9fkZ@gPW|x|B={V6x3`=jS*$Pu0+5OWf?wnIy>Y1MbbGSncpKO0qE(qO=ts z!~@&!N`10S593pVQu4FzpOh!tvg}p%zCU(aV5=~K#bKi zHdJ1>tQSrhW%KOky;iW+O_n;`l9~omqM%sdxdLtI`TrJzN6BQz+7xOl*rM>xVI2~# z)7FJ^Dc{DC<%~VS?@WXzuOG$YPLC;>#vUJ^MmtbSL`_yXtNKa$Hk+l-c!aC7gn(Cg ze?YPYZ(2Jw{SF6MiO5(%_pTo7j@&DHNW`|lD`~{iH+_eSTS&OC*2WTT*a`?|9w1dh zh1nh@$a}T#WE5$7Od~NvSEU)T(W$p$s5fe^GpG+7fdJ9=enRT9$wEk+ZaB>G3$KQO zgq?-rZZnIv!p#>Ty~}c*Lb_jxJg$eGM*XwHUwuQ|o^}b3^T6Bxx{!?va8aC@-xK*H ztJBFvFfsSWu89%@b^l3-B~O!CXs)I6Y}y#0C0U0R0WG zybjroj$io0j}3%P7zADXOwHwafT#uu*zfM!oD$6aJx7+WL%t-@6^rD_a_M?S^>c;z zMK580bZXo1f*L$CuMeM4Mp!;P@}b~$cd(s5*q~FP+NHSq;nw3fbWyH)i2)-;gQl{S zZO!T}A}fC}vUdskGSq&{`oxt~0i?0xhr6I47_tBc`fqaSrMOzR4>0H^;A zF)hX1nfHs)%Zb-(YGX;=#2R6C{BG;k=?FfP?9{_uFLri~-~AJ;jw({4MU7e*d)?P@ zXX*GkNY9ItFjhwgAIWq7Y!ksbMzfqpG)IrqKx9q{zu%Mdl+{Dis#p9q`02pr1LG8R z@As?eG!>IoROgS!@J*to<27coFc1zpkh?w=)h9CbYe%^Q!Ui46Y*HO0mr% zEff-*$ndMNw}H2a5@BsGj5oFfd!T(F&0$<{GO!Qdd?McKkorh=5{EIjDTHU`So>8V zBA-fqVLb2;u7UhDV1xMI?y>fe3~4urv3%PX)lDw+HYa;HFkaLqi4c~VtCm&Ca+9C~ zge+67hp#R9`+Euq59WhHX&7~RlXn=--m8$iZ~~1C8cv^2(qO#X0?vl91gzUKBeR1J z^p4!!&7)3#@@X&2aF2-)1Ffcc^F8r|RtdL2X%HgN&XU-KH2SLCbpw?J5xJ*!F-ypZ zMG%AJ!Pr&}`LW?E!K~=(NJxuSVTRCGJ$2a*Ao=uUDSys!OFYu!Vs2IT;xQ6EubLIl z+?+nMGeQQhh~??0!s4iQ#gm3!BpMpnY?04kK375e((Uc7B3RMj;wE?BCoQGu=UlZt!EZ1Q*auI)dj3Jj{Ujgt zW5hd~-HWBLI_3HuO) zNrb^XzPsTIb=*a69wAAA3J6AAZZ1VsYbIG}a`=d6?PjM)3EPaDpW2YP$|GrBX{q*! z$KBHNif)OKMBCFP5>!1d=DK>8u+Upm-{hj5o|Wn$vh1&K!lVfDB&47lw$tJ?d5|=B z^(_9=(1T3Fte)z^>|3**n}mIX;mMN5v2F#l(q*CvU{Ga`@VMp#%rQkDBy7kYbmb-q z<5!4iuB#Q_lLZ8}h|hPODI^U6`gzLJre9u3k3c#%86IKI*^H-@I48Bi*@avYm4v!n0+v zWu{M{&F8#p9cx+gF0yTB_<2QUrjMPo9*7^-uP#~gGW~y3nfPAoV%amgr>PSyVAd@l)}8#X zR5zV6t*uKJZL}?NYvPVK6J0v4iVpwiN|>+t3aYiZSp;m0!(1`bHO}TEtWR1tY%BPB z(W!0DmXbZAsT$iC13p4f>u*ZAy@JoLAkJhzFf1#4;#1deO8#8d&89}en&z!W&A3++^1(;>0SB1*54d@y&9Pn;^IAf3GiXbfT`_>{R+Xv; zQvgL>+0#8-laO!j#-WB~(I>l0NCMt_;@Gp_f0#^c)t?&#Xh1-7RR0@zPyBz!U#0Av zT?}n({(p?p7!4S2ZBw)#KdCG)uPnZe+U|0{BW!m)9 zi_9$F?m<`2!`JNFv+w8MK_K)qJ^aO@7-Ig>cM4-r0bi=>?B_2mFNJ}aE3<+QCzRr*NA!QjHw# z`1OsvcoD0?%jq{*7b!l|L1+Tw0TTAM4XMq7*ntc-Ived>Sj_ZtS|uVdpfg1_I9knY z2{GM_j5sDC7(W&}#s{jqbybqJWyn?{PW*&cQIU|*v8YGOKKlGl@?c#TCnmnAkAzV- zmK={|1G90zz=YUvC}+fMqts0d4vgA%t6Jhjv?d;(Z}(Ep8fTZfHA9``fdUHkA+z3+ zhh{ohP%Bj?T~{i0sYCQ}uC#5BwN`skI7`|c%kqkyWIQ;!ysvA8H`b-t()n6>GJj6xlYDu~8qX{AFo$Cm3d|XFL=4uvc?Keb zzb0ZmMoXca6Mob>JqkNuoP>B2Z>D`Q(TvrG6m`j}-1rGP!g|qoL=$FVQYxJQjFn33lODt3Wb1j8VR zlR++vIT6^DtYxAv_hxupbLLN3e0%A%a+hWTKDV3!Fjr^cWJ{scsAdfhpI)`Bms^M6 zQG$waKgFr=c|p9Piug=fcJvZ1ThMnNhQvBAg-8~b1?6wL*WyqXhtj^g(Ke}mEfZVM zJuLNTUVh#WsE*a6uqiz`b#9ZYg3+2%=C(6AvZGc=u&<6??!slB1a9K)=VL zY9EL^mfyKnD zSJyYBc_>G;5RRnrNgzJz#Rkn3S1`mZgO`(r5;Hw6MveN(URf_XS-r58Cn80K)ArH4 z#Rrd~LG1W&@ttw85cjp8xV&>$b%nSXH_*W}7Ch2pg$$c0BdEo-HWRTZcxngIBJad> z;C>b{jIXjb_9Jis?NZJsdm^EG}e*pR&DAy0EaSGi3XWTa(>C%tz1n$u?5Fb z1qtl?;_yjYo)(gB^iQq?=jusF%kywm?CJP~zEHi0NbZ);$(H$w(Hy@{i>$wcVRD_X|w-~(0Z9BJyh zhNh;+eQ9BEIs;tPz%jSVnfCP!3L&9YtEP;svoj_bNzeGSQIAjd zBss@A;)R^WAu-37RQrM%{DfBNRx>v!G31Z}8-El9IOJlb_MSoMu2}GDYycNaf>uny z+8xykD-7ONCM!APry_Lw6-yT>5!tR}W;W`C)1>pxSs5o1z#j7%m=&=7O4hz+Lsqm` z*>{+xsabZPr&X=}G@obTb{nPTkccJX8w3CG7X+1+t{JcMabv~UNv+G?txRqXib~c^Mo}`q{$`;EBNJ;#F*{gvS12kV?AZ%O0SFB$^ zn+}!HbmEj}w{Vq(G)OGAzH}R~kS^;(-s&=ectz8vN!_)Yl$$U@HNTI-pV`LSj7Opu zTZ5zZ)-S_{GcEQPIQXLQ#oMS`HPu{`SQiAZ)m1at*Hy%3xma|>o`h%E%8BEbi9p0r zVjcsh<{NBKQ4eKlXU|}@XJ#@uQw*$4BxKn6#W~I4T<^f99~(=}a`&3(ur8R9t+|AQ zWkQx7l}wa48-jO@ft2h+7qn%SJtL%~890FG0s5g*kNbL3I&@brh&f6)TlM`K^(bhr zJWM6N6x3flOw$@|C@kPi7yP&SP?bzP-E|HSXQXG>7gk|R9BTj`e=4de9C6+H7H7n# z#GJeVs1mtHhLDmVO?LkYRQc`DVOJ_vdl8VUihO-j#t=0T3%Fc1f9F73ufJz*adn*p zc%&vi(4NqHu^R>sAT_0EDjVR8bc%wTz#$;%NU-kbDyL_dg0%TFafZwZ?5KZpcuaO54Z9hX zD$u>q!-9`U6-D`E#`W~fIfiIF5_m6{fvM)b1NG3xf4Auw;Go~Fu7cth#DlUn{@~yu z=B;RT*dp?bO}o%4x7k9v{r=Y@^YQ^UUm(Qmliw8brO^=NP+UOohLYiaEB3^DB56&V zK?4jV61B|1Uj_5fBKW;8LdwOFZKWp)g{B%7g1~DgO&N& z#lisxf?R~Z@?3E$Mms$$JK8oe@X`5m98V*aV6Ua}8Xs2#A!{x?IP|N(%nxsH?^c{& z@vY&R1QmQs83BW28qAmJfS7MYi=h(YK??@EhjL-t*5W!p z^gYX!Q6-vBqcv~ruw@oMaU&qp0Fb(dbVzm5xJN%0o_^@fWq$oa3X?9s%+b)x4w-q5Koe(@j6Ez7V@~NRFvd zfBH~)U5!ix3isg`6be__wBJp=1@yfsCMw1C@y+9WYD9_C%{Q~7^0AF2KFryfLlUP# zwrtJEcH)jm48!6tUcxiurAMaiD04C&tPe6DI0#aoqz#Bt0_7_*X*TsF7u*zv(iEfA z;$@?XVu~oX#1YXtceQL{dSneL&*nDug^OW$DSLF0M1Im|sSX8R26&)<0Fbh^*l6!5wfSu8MpMoh=2l z^^0Sr$UpZp*9oqa23fcCfm7`ya2<4wzJ`Axt7e4jJrRFVf?nY~2&tRL* zd;6_njcz01c>$IvN=?K}9ie%Z(BO@JG2J}fT#BJQ+f5LFSgup7i!xWRKw6)iITjZU z%l6hPZia>R!`aZjwCp}I zg)%20;}f+&@t;(%5;RHL>K_&7MH^S+7<|(SZH!u zznW|jz$uA`P9@ZWtJgv$EFp>)K&Gt+4C6#*khZQXS*S~6N%JDT$r`aJDs9|uXWdbg zBwho$phWx}x!qy8&}6y5Vr$G{yGSE*r$^r{}pw zVTZKvikRZ`J_IJrjc=X1uw?estdwm&bEahku&D04HD+0Bm~q#YGS6gp!KLf$A{%Qd z&&yX@Hp>~(wU{|(#U&Bf92+1i&Q*-S+=y=3pSZy$#8Uc$#7oiJUuO{cE6=tsPhwPe| zxQpK>`Dbka`V)$}e6_OXKLB%i76~4N*zA?X+PrhH<&)}prET;kel24kW%+9))G^JI zsq7L{P}^#QsZViX%KgxBvEugr>ZmFqe^oAg?{EI=&_O#e)F3V#rc z8$4}0Zr19qd3tE4#$3_f=Bbx9oV6VO!d3(R===i-7p=Vj`520w0D3W6lQfY48}!D* z&)lZMG;~er2qBoI2gsX+Ts-hnpS~NYRDtPd^FPzn!^&yxRy#CSz(b&E*tL|jIkq|l zf%>)7Dtu>jCf`-7R#*GhGn4FkYf;B$+9IxmqH|lf6$4irg{0ept__%)V*R_OK=T06 zyT_m-o@Kp6U{l5h>W1hGq*X#8*y@<;vsOFqEjTQXFEotR+{3}ODDnj;o0@!bB5x=N z394FojuGOtVKBlVRLtHp%EJv_G5q=AgF)SKyRN5=cGBjDWv4LDn$IL`*=~J7u&Dy5 zrMc83y+w^F&{?X(KOOAl-sWZDb{9X9#jrQtmrEXD?;h-}SYT7yM(X_6qksM=K_a;Z z3u0qT0TtaNvDER_8x*rxXw&C^|h{P1qxK|@pS7vdlZ#P z7PdB7MmC2}%sdzAxt>;WM1s0??`1983O4nFK|hVAbHcZ3x{PzytQLkCVk7hA!Lo` zEJH?4qw|}WH{dc4z%aB=0XqsFW?^p=X}4xnCJXK%c#ItOSjdSO`UXJyuc8bh^Cf}8 z@Ht|vXd^6{Fgai8*tmyRGmD_s_nv~r^Fy7j`Bu`6=G)5H$i7Q7lvQnmea&TGvJp9a|qOrUymZ$6G|Ly z#zOCg++$3iB$!6!>215A4!iryregKuUT344X)jQb3|9qY>c0LO{6Vby05n~VFzd?q zgGZv&FGlkiH*`fTurp>B8v&nSxNz)=5IF$=@rgND4d`!AaaX;_lK~)-U8la_Wa8i?NJC@BURO*sUW)E9oyv3RG^YGfN%BmxzjlT)bp*$<| zX3tt?EAy<&K+bhIuMs-g#=d1}N_?isY)6Ay$mDOKRh z4v1asEGWoAp=srraLW^h&_Uw|6O+r;wns=uwYm=JN4Q!quD8SQRSeEcGh|Eb5Jg8m zOT}u;N|x@aq)=&;wufCc^#)5U^VcZw;d_wwaoh9$p@Xrc{DD6GZUqZ ziC6OT^zSq@-lhbgR8B+e;7_Giv;DK5gn^$bs<6~SUadiosfewWDJu`XsBfOd1|p=q zE>m=zF}!lObA%ePey~gqU8S6h-^J2Y?>7)L2+%8kV}Gp=h`Xm_}rlm)SyUS=`=S7msKu zC|T!gPiI1rWGb1z$Md?0YJQ;%>uPLOXf1Z>N~`~JHJ!^@D5kSXQ4ugnFZ>^`zH8CAiZmp z6Ms|#2gcGsQ{{u7+Nb9sA?U>(0e$5V1|WVwY`Kn)rsnnZ4=1u=7u!4WexZD^IQ1Jk zfF#NLe>W$3m&C^ULjdw+5|)-BSHwpegdyt9NYC{3@QtMfd8GrIWDu`gd0nv-3LpGCh@wgBaG z176tikL!_NXM+Bv#7q^cyn9$XSeZR6#!B4JE@GVH zoobHZN_*RF#@_SVYKkQ_igme-Y5U}cV(hkR#k1c{bQNMji zU7aE`?dHyx=1`kOYZo_8U7?3-7vHOp`Qe%Z*i+FX!s?6huNp0iCEW-Z7E&jRWmUW_ z67j>)Ew!yq)hhG4o?^z}HWH-e=es#xJUhDRc4B51M4~E-l5VZ!&zQq`gWe`?}#b~7w1LH4Xa-UCT5LXkXQWheBa2YJYbyQ zl1pXR%b(KCXMO0OsXgl0P0Og<{(@&z1aokU-Pq`eQq*JYgt8xdFQ6S z6Z3IFSua8W&M#`~*L#r>Jfd6*BzJ?JFdBR#bDv$_0N!_5vnmo@!>vULcDm`MFU823 zpG9pqjqz^FE5zMDoGqhs5OMmC{Y3iVcl>F}5Rs24Y5B^mYQ;1T&ks@pIApHOdrzXF z-SdX}Hf{X;TaSxG_T$0~#RhqKISGKNK47}0*x&nRIPtmdwxc&QT3$8&!3fWu1eZ_P zJveQj^hJL#Sn!*4k`3}(d(aasl&7G0j0-*_2xtAnoX1@9+h zO#c>YQg60Z;o{Bi=3i7S`Ic+ZE>K{(u|#)9y}q*j8uKQ1^>+(BI}m%1v3$=4ojGBc zm+o1*!T&b}-lVvZqIUBc8V}QyFEgm#oyIuC{8WqUNV{Toz`oxhYpP!_p2oHHh5P@iB*NVo~2=GQm+8Yrkm2Xjc_VyHg1c0>+o~@>*Qzo zHVBJS>$$}$_4EniTI;b1WShX<5-p#TPB&!;lP!lBVBbLOOxh6FuYloD%m;n{r|;MU3!q4AVkua~fieeWu2 zQAQ$ue(IklX6+V;F1vCu-&V?I3d42FgWgsb_e^29ol}HYft?{SLf>DrmOp9o!t>I^ zY7fBCk+E8n_|apgM|-;^=#B?6RnFKlN`oR)`e$+;D=yO-(U^jV;rft^G_zl`n7qnM zL z*-Y4Phq+ZI1$j$F-f;`CD#|`-T~OM5Q>x}a>B~Gb3-+9i>Lfr|Ca6S^8g*{*?_5!x zH_N!SoRP=gX1?)q%>QTY!r77e2j9W(I!uAz{T`NdNmPBBUzi2{`XMB^zJGGwFWeA9 z{fk33#*9SO0)DjROug+(M)I-pKA!CX;IY(#gE!UxXVsa)X!UftIN98{pt#4MJHOhY zM$_l}-TJlxY?LS6Nuz1T<44m<4i^8k@D$zuCPrkmz@sdv+{ciyFJG2Zwy&%c7;atIeTdh!a(R^QXnu1Oq1b42*OQFWnyQ zWeQrdvP|w_idy53Wa<{QH^lFmEd+VlJkyiC>6B#s)F;w-{c;aKIm;Kp50HnA-o3lY z9B~F$gJ@yYE#g#X&3ADx&tO+P_@mnQTz9gv30_sTsaGXkfNYXY{$(>*PEN3QL>I!k zp)KibPhrfX3%Z$H6SY`rXGYS~143wZrG2;=FLj50+VM6soI~up_>fU(2Wl@{BRsMi zO%sL3x?2l1cXTF)k&moNsHfQrQ+wu(gBt{sk#CU=UhrvJIncy@tJX5klLjgMn>~h= zg|FR&;@eh|C7`>s_9c~0-{IAPV){l|Ts`i=)AW;d9&KPc3fMeoTS%8@V~D8*h;&(^>yjT84MM}=%#LS7shLAuuj(0VAYoozhWjq z4LEr?wUe2^WGwdTIgWBkDUJa>YP@5d9^Rs$kCXmMRxuF*YMVrn?0NFyPl}>`&dqZb z<5eqR=ZG3>n2{6v6BvJ`YBZeeTtB88TAY(x0a58EWyuf>+^|x8Qa6wA|1Nb_p|nA zWWa}|z8a)--Wj`LqyFk_a3gN2>5{Rl_wbW?#by7&i*^hRknK%jwIH6=dQ8*-_{*x0j^DUfMX0`|K@6C<|1cgZ~D(e5vBFFm;HTZF(!vT8=T$K+|F)x3kqzBV4-=p1V(lzi(s7jdu0>LD#N=$Lk#3HkG!a zIF<7>%B7sRNzJ66KrFV76J<2bdYhxll0y2^_rdG=I%AgW4~)1Nvz=$1UkE^J%BxLo z+lUci`UcU062os*=`-j4IfSQA{w@y|3}Vk?i;&SSdh8n+$iHA#%ERL{;EpXl6u&8@ zzg}?hkEOUOJt?ZL=pWZFJ19mI1@P=$U5*Im1e_8Z${JsM>Ov?nh8Z zP5QvI!{Jy@&BP48%P2{Jr_VgzW;P@7)M9n|lDT|Ep#}7C$&ud&6>C^5ZiwKIg2McPU(4jhM!BD@@L(Gd*Nu$ji(ljZ<{FIeW_1Mmf;76{LU z-ywN~=uNN)Xi6$<12A9y)K%X|(W0p|&>>4OXB?IiYr||WKDOJPxiSe01NSV-h24^L z_>m$;|C+q!Mj**-qQ$L-*++en(g|hw;M!^%_h-iDjFHLo-n3JpB;p?+o2;`*jpvJU zLY^lt)Un4joij^^)O(CKs@7E%*!w>!HA4Q?0}oBJ7Nr8NQ7QmY^4~jvf0-`%waOLn zdNjAPaC0_7c|RVhw)+71NWjRi!y>C+Bl;Z`NiL^zn2*0kmj5gyhCLCxts*cWCdRI| zjsd=sT5BVJc^$GxP~YF$-U{-?kW6r@^vHXB%{CqYzU@1>dzf#3SYedJG-Rm6^RB7s zGM5PR(yKPKR)>?~vpUIeTP7A1sc8-knnJk*9)3t^e%izbdm>Y=W{$wm(cy1RB-19i za#828DMBY+ps#7Y8^6t)=Ea@%Nkt)O6JCx|ybC;Ap}Z@Zw~*}3P>MZLPb4Enxz9Wf zssobT^(R@KuShj8>@!1M7tm|2%-pYYDxz-5`rCbaTCG5{;Uxm z*g=+H1X8{NUvFGzz~wXa%Eo};I;~`37*WrRU&K0dPSB$yk(Z*@K&+mFal^?c zurbqB-+|Kb5|sznT;?Pj!+kgFY1#Dr;_%A(GIQC{3ct|{*Bji%FNa6c-thbpBkA;U zURV!Dr&X{0J}iht#-Qp2=xzuh(fM>zRoiGrYl5ttw2#r34gC41CCOC31m~^UPTK@s z6;A@)7O7_%C)>bnAXerYuAHdE93>j2N}H${zEc6&SbZ|-fiG*-qtGuy-qDelH(|u$ zorf8_T6Zqe#Ub!+e3oSyrskt_HyW_^5lrWt#30l)tHk|j$@YyEkXUOV;6B51L;M@=NIWZXU;GrAa(LGxO%|im%7F<-6N;en0Cr zLH>l*y?pMwt`1*cH~LdBPFY_l;~`N!Clyfr;7w<^X;&(ZiVdF1S5e(+Q%60zgh)s4 zn2yj$+mE=miVERP(g8}G4<85^-5f@qxh2ec?n+$A_`?qN=iyT1?U@t?V6DM~BIlBB z>u~eXm-aE>R0sQy!-I4xtCNi!!qh?R1!kKf6BoH2GG{L4%PAz0{Sh6xpuyI%*~u)s z%rLuFl)uQUCBQAtMyN;%)zFMx4loh7uTfKeB2Xif`lN?2gq6NhWhfz0u5WP9J>=V2 zo{mLtSy&BA!mSzs&CrKWq^y40JF5a&GSXIi2= z{EYb59J4}VwikL4P=>+mc6{($FNE@e=VUwG+KV21;<@lrN`mnz5jYGASyvz7BOG_6(p^eTxD-4O#lROgon;R35=|nj#eHIfJBYPWG>H>`dHKCDZ3`R{-?HO0mE~(5_WYcFmp8sU?wr*UkAQiNDGc6T zA%}GOLXlOWqL?WwfHO8MB#8M8*~Y*gz;1rWWoVSXP&IbKxbQ8+s%4Jnt?kDsq7btI zCDr0PZ)b;B%!lu&CT#RJzm{l{2fq|BcY85`w~3LSK<><@(2EdzFLt9Y_`;WXL6x`0 zDoQ?=?I@Hbr;*VVll1Gmd8*%tiXggMK81a+T(5Gx6;eNb8=uYn z5BG-0g>pP21NPn>$ntBh>`*})Fl|38oC^9Qz>~MAazH%3Q~Qb!ALMf$srexgPZ2@&c~+hxRi1;}+)-06)!#Mq<6GhP z-Q?qmgo${aFBApb5p}$1OJKTClfi8%PpnczyVKkoHw7Ml9e7ikrF0d~UB}i3vizos zXW4DN$SiEV9{faLt5bHy2a>33K%7Td-n5C*N;f&ZqAg#2hIqEb(y<&f4u5BWJ>2^4 z414GosL=Aom#m&=x_v<0-fp1r%oVJ{T-(xnomNJ(Dryv zh?vj+%=II_nV+@NR+(!fZZVM&(W6{6%9cm+o+Z6}KqzLw{(>E86uA1`_K$HqINlb1 zKelh3-jr2I9V?ych`{hta9wQ2c9=MM`2cC{m6^MhlL2{DLv7C^j z$xXBCnDl_;l|bPGMX@*tV)B!c|4oZyftUlP*?$YU9C_eAsuVHJ58?)zpbr30P*C`T z7y#ao`uE-SOG(Pi+`$=e^mle~)pRrdwL5)N;o{gpW21of(QE#U6w%*C~`v-z0QqBML!!5EeYA5IQB0 z^l01c;L6E(iytN!LhL}wfwP7W9PNAkb+)Cst?qg#$n;z41O4&v+8-zPs+XNb-q zIeeBCh#ivnFLUCwfS;p{LC0O7tm+Sf9Jn)~b%uwP{%69;QC)Ok0t%*a5M+=;y8j=v z#!*pp$9@!x;UMIs4~hP#pnfVc!%-D<+wsG@R2+J&%73lK|2G!EQC)O05TCV=&3g)C!lT=czLpZ@Sa%TYuoE?v8T8`V;e$#Zf2_Nj6nvBgh1)2 GZ~q4|mN%#X literal 62076 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 diff --git a/fabric/1.18/gradle/wrapper/gradle-wrapper.properties b/fabric/1.18/gradle/wrapper/gradle-wrapper.properties index 37aef8d3..9355b415 100644 --- a/fabric/1.18/gradle/wrapper/gradle-wrapper.properties +++ b/fabric/1.18/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/fabric/1.18/gradlew b/fabric/1.18/gradlew index aeb74cbb..f5feea6d 100644 --- a/fabric/1.18/gradlew +++ b/fabric/1.18/gradlew @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # @@ -55,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -83,7 +85,9 @@ done # This is normally unused # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -130,10 +134,13 @@ location of your Java installation." fi else JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. @@ -141,7 +148,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -149,7 +156,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -198,11 +205,11 @@ fi # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ diff --git a/fabric/1.18/gradlew.bat b/fabric/1.18/gradlew.bat index 93e3f59f..9d21a218 100644 --- a/fabric/1.18/gradlew.bat +++ b/fabric/1.18/gradlew.bat @@ -13,6 +13,8 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## @@ -43,11 +45,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -57,11 +59,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail diff --git a/fabric/1.19.2/gradle/wrapper/gradle-wrapper.jar b/fabric/1.19.2/gradle/wrapper/gradle-wrapper.jar index c1962a79e29d3e0ab67b14947c167a862655af9b..a4b76b9530d66f5e68d973ea569d8e19de379189 100644 GIT binary patch literal 43583 zcma&N1CXTcmMvW9vTb(Rwr$&4wr$(C?dmSu>@vG-+vuvg^_??!{yS%8zW-#zn-LkA z5&1^$^{lnmUON?}LBF8_K|(?T0Ra(xUH{($5eN!MR#ZihR#HxkUPe+_R8Cn`RRs(P z_^*#_XlXmGv7!4;*Y%p4nw?{bNp@UZHv1?Um8r6)Fei3p@ClJn0ECfg1hkeuUU@Or zDaPa;U3fE=3L}DooL;8f;P0ipPt0Z~9P0)lbStMS)ag54=uL9ia-Lm3nh|@(Y?B`; zx_#arJIpXH!U{fbCbI^17}6Ri*H<>OLR%c|^mh8+)*h~K8Z!9)DPf zR2h?lbDZQ`p9P;&DQ4F0sur@TMa!Y}S8irn(%d-gi0*WxxCSk*A?3lGh=gcYN?FGl z7D=Js!i~0=u3rox^eO3i@$0=n{K1lPNU zwmfjRVmLOCRfe=seV&P*1Iq=^i`502keY8Uy-WNPwVNNtJFx?IwAyRPZo2Wo1+S(xF37LJZ~%i)kpFQ3Fw=mXfd@>%+)RpYQLnr}B~~zoof(JVm^^&f zxKV^+3D3$A1G;qh4gPVjhrC8e(VYUHv#dy^)(RoUFM?o%W-EHxufuWf(l*@-l+7vt z=l`qmR56K~F|v<^Pd*p~1_y^P0P^aPC##d8+HqX4IR1gu+7w#~TBFphJxF)T$2WEa zxa?H&6=Qe7d(#tha?_1uQys2KtHQ{)Qco)qwGjrdNL7thd^G5i8Os)CHqc>iOidS} z%nFEDdm=GXBw=yXe1W-ShHHFb?Cc70+$W~z_+}nAoHFYI1MV1wZegw*0y^tC*s%3h zhD3tN8b=Gv&rj}!SUM6|ajSPp*58KR7MPpI{oAJCtY~JECm)*m_x>AZEu>DFgUcby z1Qaw8lU4jZpQ_$;*7RME+gq1KySGG#Wql>aL~k9tLrSO()LWn*q&YxHEuzmwd1?aAtI zBJ>P=&$=l1efe1CDU;`Fd+_;&wI07?V0aAIgc(!{a z0Jg6Y=inXc3^n!U0Atk`iCFIQooHqcWhO(qrieUOW8X(x?(RD}iYDLMjSwffH2~tB z)oDgNBLB^AJBM1M^c5HdRx6fBfka`(LD-qrlh5jqH~);#nw|iyp)()xVYak3;Ybik z0j`(+69aK*B>)e_p%=wu8XC&9e{AO4c~O1U`5X9}?0mrd*m$_EUek{R?DNSh(=br# z#Q61gBzEpmy`$pA*6!87 zSDD+=@fTY7<4A?GLqpA?Pb2z$pbCc4B4zL{BeZ?F-8`s$?>*lXXtn*NC61>|*w7J* z$?!iB{6R-0=KFmyp1nnEmLsA-H0a6l+1uaH^g%c(p{iT&YFrbQ$&PRb8Up#X3@Zsk zD^^&LK~111%cqlP%!_gFNa^dTYT?rhkGl}5=fL{a`UViaXWI$k-UcHJwmaH1s=S$4 z%4)PdWJX;hh5UoK?6aWoyLxX&NhNRqKam7tcOkLh{%j3K^4Mgx1@i|Pi&}<^5>hs5 zm8?uOS>%)NzT(%PjVPGa?X%`N2TQCKbeH2l;cTnHiHppPSJ<7y-yEIiC!P*ikl&!B z%+?>VttCOQM@ShFguHVjxX^?mHX^hSaO_;pnyh^v9EumqSZTi+#f&_Vaija0Q-e*| z7ulQj6Fs*bbmsWp{`auM04gGwsYYdNNZcg|ph0OgD>7O}Asn7^Z=eI>`$2*v78;sj-}oMoEj&@)9+ycEOo92xSyY344^ z11Hb8^kdOvbf^GNAK++bYioknrpdN>+u8R?JxG=!2Kd9r=YWCOJYXYuM0cOq^FhEd zBg2puKy__7VT3-r*dG4c62Wgxi52EMCQ`bKgf*#*ou(D4-ZN$+mg&7$u!! z-^+Z%;-3IDwqZ|K=ah85OLwkO zKxNBh+4QHh)u9D?MFtpbl)us}9+V!D%w9jfAMYEb>%$A;u)rrI zuBudh;5PN}_6J_}l55P3l_)&RMlH{m!)ai-i$g)&*M`eN$XQMw{v^r@-125^RRCF0 z^2>|DxhQw(mtNEI2Kj(;KblC7x=JlK$@78`O~>V!`|1Lm-^JR$-5pUANAnb(5}B}JGjBsliK4& zk6y(;$e&h)lh2)L=bvZKbvh@>vLlreBdH8No2>$#%_Wp1U0N7Ank!6$dFSi#xzh|( zRi{Uw%-4W!{IXZ)fWx@XX6;&(m_F%c6~X8hx=BN1&q}*( zoaNjWabE{oUPb!Bt$eyd#$5j9rItB-h*5JiNi(v^e|XKAj*8(k<5-2$&ZBR5fF|JA z9&m4fbzNQnAU}r8ab>fFV%J0z5awe#UZ|bz?Ur)U9bCIKWEzi2%A+5CLqh?}K4JHi z4vtM;+uPsVz{Lfr;78W78gC;z*yTch~4YkLr&m-7%-xc ztw6Mh2d>_iO*$Rd8(-Cr1_V8EO1f*^@wRoSozS) zy1UoC@pruAaC8Z_7~_w4Q6n*&B0AjOmMWa;sIav&gu z|J5&|{=a@vR!~k-OjKEgPFCzcJ>#A1uL&7xTDn;{XBdeM}V=l3B8fE1--DHjSaxoSjNKEM9|U9#m2<3>n{Iuo`r3UZp;>GkT2YBNAh|b z^jTq-hJp(ebZh#Lk8hVBP%qXwv-@vbvoREX$TqRGTgEi$%_F9tZES@z8Bx}$#5eeG zk^UsLBH{bc2VBW)*EdS({yw=?qmevwi?BL6*=12k9zM5gJv1>y#ML4!)iiPzVaH9% zgSImetD@dam~e>{LvVh!phhzpW+iFvWpGT#CVE5TQ40n%F|p(sP5mXxna+Ev7PDwA zamaV4m*^~*xV+&p;W749xhb_X=$|LD;FHuB&JL5?*Y2-oIT(wYY2;73<^#46S~Gx| z^cez%V7x$81}UWqS13Gz80379Rj;6~WdiXWOSsdmzY39L;Hg3MH43o*y8ibNBBH`(av4|u;YPq%{R;IuYow<+GEsf@R?=@tT@!}?#>zIIn0CoyV!hq3mw zHj>OOjfJM3F{RG#6ujzo?y32m^tgSXf@v=J$ELdJ+=5j|=F-~hP$G&}tDZsZE?5rX ztGj`!S>)CFmdkccxM9eGIcGnS2AfK#gXwj%esuIBNJQP1WV~b~+D7PJTmWGTSDrR` zEAu4B8l>NPuhsk5a`rReSya2nfV1EK01+G!x8aBdTs3Io$u5!6n6KX%uv@DxAp3F@{4UYg4SWJtQ-W~0MDb|j-$lwVn znAm*Pl!?Ps&3wO=R115RWKb*JKoexo*)uhhHBncEDMSVa_PyA>k{Zm2(wMQ(5NM3# z)jkza|GoWEQo4^s*wE(gHz?Xsg4`}HUAcs42cM1-qq_=+=!Gk^y710j=66(cSWqUe zklbm8+zB_syQv5A2rj!Vbw8;|$@C!vfNmNV!yJIWDQ>{+2x zKjuFX`~~HKG~^6h5FntRpnnHt=D&rq0>IJ9#F0eM)Y-)GpRjiN7gkA8wvnG#K=q{q z9dBn8_~wm4J<3J_vl|9H{7q6u2A!cW{bp#r*-f{gOV^e=8S{nc1DxMHFwuM$;aVI^ zz6A*}m8N-&x8;aunp1w7_vtB*pa+OYBw=TMc6QK=mbA-|Cf* zvyh8D4LRJImooUaSb7t*fVfih<97Gf@VE0|z>NcBwBQze);Rh!k3K_sfunToZY;f2 z^HmC4KjHRVg+eKYj;PRN^|E0>Gj_zagfRbrki68I^#~6-HaHg3BUW%+clM1xQEdPYt_g<2K+z!$>*$9nQ>; zf9Bei{?zY^-e{q_*|W#2rJG`2fy@{%6u0i_VEWTq$*(ZN37|8lFFFt)nCG({r!q#9 z5VK_kkSJ3?zOH)OezMT{!YkCuSSn!K#-Rhl$uUM(bq*jY? zi1xbMVthJ`E>d>(f3)~fozjg^@eheMF6<)I`oeJYx4*+M&%c9VArn(OM-wp%M<-`x z7sLP1&3^%Nld9Dhm@$3f2}87!quhI@nwd@3~fZl_3LYW-B?Ia>ui`ELg z&Qfe!7m6ze=mZ`Ia9$z|ARSw|IdMpooY4YiPN8K z4B(ts3p%2i(Td=tgEHX z0UQ_>URBtG+-?0E;E7Ld^dyZ;jjw0}XZ(}-QzC6+NN=40oDb2^v!L1g9xRvE#@IBR zO!b-2N7wVfLV;mhEaXQ9XAU+>=XVA6f&T4Z-@AX!leJ8obP^P^wP0aICND?~w&NykJ#54x3_@r7IDMdRNy4Hh;h*!u(Ol(#0bJdwEo$5437-UBjQ+j=Ic>Q2z` zJNDf0yO6@mr6y1#n3)s(W|$iE_i8r@Gd@!DWDqZ7J&~gAm1#~maIGJ1sls^gxL9LLG_NhU!pTGty!TbhzQnu)I*S^54U6Yu%ZeCg`R>Q zhBv$n5j0v%O_j{QYWG!R9W?5_b&67KB$t}&e2LdMvd(PxN6Ir!H4>PNlerpBL>Zvyy!yw z-SOo8caEpDt(}|gKPBd$qND5#a5nju^O>V&;f890?yEOfkSG^HQVmEbM3Ugzu+UtH zC(INPDdraBN?P%kE;*Ae%Wto&sgw(crfZ#Qy(<4nk;S|hD3j{IQRI6Yq|f^basLY; z-HB&Je%Gg}Jt@={_C{L$!RM;$$|iD6vu#3w?v?*;&()uB|I-XqEKqZPS!reW9JkLewLb!70T7n`i!gNtb1%vN- zySZj{8-1>6E%H&=V}LM#xmt`J3XQoaD|@XygXjdZ1+P77-=;=eYpoEQ01B@L*a(uW zrZeZz?HJsw_4g0vhUgkg@VF8<-X$B8pOqCuWAl28uB|@r`19DTUQQsb^pfqB6QtiT z*`_UZ`fT}vtUY#%sq2{rchyfu*pCg;uec2$-$N_xgjZcoumE5vSI{+s@iLWoz^Mf; zuI8kDP{!XY6OP~q5}%1&L}CtfH^N<3o4L@J@zg1-mt{9L`s^z$Vgb|mr{@WiwAqKg zp#t-lhrU>F8o0s1q_9y`gQNf~Vb!F%70f}$>i7o4ho$`uciNf=xgJ>&!gSt0g;M>*x4-`U)ysFW&Vs^Vk6m%?iuWU+o&m(2Jm26Y(3%TL; zA7T)BP{WS!&xmxNw%J=$MPfn(9*^*TV;$JwRy8Zl*yUZi8jWYF>==j~&S|Xinsb%c z2?B+kpet*muEW7@AzjBA^wAJBY8i|#C{WtO_or&Nj2{=6JTTX05}|H>N2B|Wf!*3_ z7hW*j6p3TvpghEc6-wufFiY!%-GvOx*bZrhZu+7?iSrZL5q9}igiF^*R3%DE4aCHZ zqu>xS8LkW+Auv%z-<1Xs92u23R$nk@Pk}MU5!gT|c7vGlEA%G^2th&Q*zfg%-D^=f z&J_}jskj|Q;73NP4<4k*Y%pXPU2Thoqr+5uH1yEYM|VtBPW6lXaetokD0u z9qVek6Q&wk)tFbQ8(^HGf3Wp16gKmr>G;#G(HRBx?F`9AIRboK+;OfHaLJ(P>IP0w zyTbTkx_THEOs%Q&aPrxbZrJlio+hCC_HK<4%f3ZoSAyG7Dn`=X=&h@m*|UYO-4Hq0 z-Bq&+Ie!S##4A6OGoC~>ZW`Y5J)*ouaFl_e9GA*VSL!O_@xGiBw!AF}1{tB)z(w%c zS1Hmrb9OC8>0a_$BzeiN?rkPLc9%&;1CZW*4}CDDNr2gcl_3z+WC15&H1Zc2{o~i) z)LLW=WQ{?ricmC`G1GfJ0Yp4Dy~Ba;j6ZV4r{8xRs`13{dD!xXmr^Aga|C=iSmor% z8hi|pTXH)5Yf&v~exp3o+sY4B^^b*eYkkCYl*T{*=-0HniSA_1F53eCb{x~1k3*`W zr~};p1A`k{1DV9=UPnLDgz{aJH=-LQo<5%+Em!DNN252xwIf*wF_zS^!(XSm(9eoj z=*dXG&n0>)_)N5oc6v!>-bd(2ragD8O=M|wGW z!xJQS<)u70m&6OmrF0WSsr@I%T*c#Qo#Ha4d3COcX+9}hM5!7JIGF>7<~C(Ear^Sn zm^ZFkV6~Ula6+8S?oOROOA6$C&q&dp`>oR-2Ym3(HT@O7Sd5c~+kjrmM)YmgPH*tL zX+znN>`tv;5eOfX?h{AuX^LK~V#gPCu=)Tigtq9&?7Xh$qN|%A$?V*v=&-2F$zTUv z`C#WyIrChS5|Kgm_GeudCFf;)!WH7FI60j^0o#65o6`w*S7R@)88n$1nrgU(oU0M9 zx+EuMkC>(4j1;m6NoGqEkpJYJ?vc|B zOlwT3t&UgL!pX_P*6g36`ZXQ; z9~Cv}ANFnJGp(;ZhS(@FT;3e)0)Kp;h^x;$*xZn*k0U6-&FwI=uOGaODdrsp-!K$Ac32^c{+FhI-HkYd5v=`PGsg%6I`4d9Jy)uW0y%) zm&j^9WBAp*P8#kGJUhB!L?a%h$hJgQrx!6KCB_TRo%9{t0J7KW8!o1B!NC)VGLM5! zpZy5Jc{`r{1e(jd%jsG7k%I+m#CGS*BPA65ZVW~fLYw0dA-H_}O zrkGFL&P1PG9p2(%QiEWm6x;U-U&I#;Em$nx-_I^wtgw3xUPVVu zqSuKnx&dIT-XT+T10p;yjo1Y)z(x1fb8Dzfn8e yu?e%!_ptzGB|8GrCfu%p?(_ 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 GZ~q4|mN%#X literal 62076 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 diff --git a/fabric/1.19.2/gradle/wrapper/gradle-wrapper.properties b/fabric/1.19.2/gradle/wrapper/gradle-wrapper.properties index 37aef8d3..9355b415 100644 --- a/fabric/1.19.2/gradle/wrapper/gradle-wrapper.properties +++ b/fabric/1.19.2/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/fabric/1.19.2/gradlew b/fabric/1.19.2/gradlew index aeb74cbb..f5feea6d 100644 --- a/fabric/1.19.2/gradlew +++ b/fabric/1.19.2/gradlew @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # @@ -55,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -83,7 +85,9 @@ done # This is normally unused # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -130,10 +134,13 @@ location of your Java installation." fi else JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. @@ -141,7 +148,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -149,7 +156,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -198,11 +205,11 @@ fi # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ diff --git a/fabric/1.19.2/gradlew.bat b/fabric/1.19.2/gradlew.bat index 93e3f59f..9d21a218 100644 --- a/fabric/1.19.2/gradlew.bat +++ b/fabric/1.19.2/gradlew.bat @@ -13,6 +13,8 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## @@ -43,11 +45,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -57,11 +59,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail diff --git a/fabric/1.19.3/gradle/wrapper/gradle-wrapper.jar b/fabric/1.19.3/gradle/wrapper/gradle-wrapper.jar index c1962a79e29d3e0ab67b14947c167a862655af9b..a4b76b9530d66f5e68d973ea569d8e19de379189 100644 GIT binary patch literal 43583 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 yu?e%!_ptzGB|8GrCfu%p?(_ zQccdaaVK$5bz;*rnyK{_SQYM>;aES6Qs^lj9lEs6_J+%nIiuQC*fN;z8md>r_~Mfl zU%p5Dt_YT>gQqfr@`cR!$NWr~+`CZb%dn;WtzrAOI>P_JtsB76PYe*<%H(y>qx-`Kq!X_; z<{RpAqYhE=L1r*M)gNF3B8r(<%8mo*SR2hu zccLRZwGARt)Hlo1euqTyM>^!HK*!Q2P;4UYrysje@;(<|$&%vQekbn|0Ruu_Io(w4#%p6ld2Yp7tlA`Y$cciThP zKzNGIMPXX%&Ud0uQh!uQZz|FB`4KGD?3!ND?wQt6!n*f4EmCoJUh&b?;B{|lxs#F- z31~HQ`SF4x$&v00@(P+j1pAaj5!s`)b2RDBp*PB=2IB>oBF!*6vwr7Dp%zpAx*dPr zb@Zjq^XjN?O4QcZ*O+8>)|HlrR>oD*?WQl5ri3R#2?*W6iJ>>kH%KnnME&TT@ZzrHS$Q%LC?n|e>V+D+8D zYc4)QddFz7I8#}y#Wj6>4P%34dZH~OUDb?uP%-E zwjXM(?Sg~1!|wI(RVuxbu)-rH+O=igSho_pDCw(c6b=P zKk4ATlB?bj9+HHlh<_!&z0rx13K3ZrAR8W)!@Y}o`?a*JJsD+twZIv`W)@Y?Amu_u zz``@-e2X}27$i(2=9rvIu5uTUOVhzwu%mNazS|lZb&PT;XE2|B&W1>=B58#*!~D&) zfVmJGg8UdP*fx(>Cj^?yS^zH#o-$Q-*$SnK(ZVFkw+er=>N^7!)FtP3y~Xxnu^nzY zikgB>Nj0%;WOltWIob|}%lo?_C7<``a5hEkx&1ku$|)i>Rh6@3h*`slY=9U}(Ql_< zaNG*J8vb&@zpdhAvv`?{=zDedJ23TD&Zg__snRAH4eh~^oawdYi6A3w8<Ozh@Kw)#bdktM^GVb zrG08?0bG?|NG+w^&JvD*7LAbjED{_Zkc`3H!My>0u5Q}m!+6VokMLXxl`Mkd=g&Xx z-a>m*#G3SLlhbKB!)tnzfWOBV;u;ftU}S!NdD5+YtOjLg?X}dl>7m^gOpihrf1;PY zvll&>dIuUGs{Qnd- zwIR3oIrct8Va^Tm0t#(bJD7c$Z7DO9*7NnRZorrSm`b`cxz>OIC;jSE3DO8`hX955ui`s%||YQtt2 z5DNA&pG-V+4oI2s*x^>-$6J?p=I>C|9wZF8z;VjR??Icg?1w2v5Me+FgAeGGa8(3S z4vg*$>zC-WIVZtJ7}o9{D-7d>zCe|z#<9>CFve-OPAYsneTb^JH!Enaza#j}^mXy1 z+ULn^10+rWLF6j2>Ya@@Kq?26>AqK{A_| zQKb*~F1>sE*=d?A?W7N2j?L09_7n+HGi{VY;MoTGr_)G9)ot$p!-UY5zZ2Xtbm=t z@dpPSGwgH=QtIcEulQNI>S-#ifbnO5EWkI;$A|pxJd885oM+ zGZ0_0gDvG8q2xebj+fbCHYfAXuZStH2j~|d^sBAzo46(K8n59+T6rzBwK)^rfPT+B zyIFw)9YC-V^rhtK`!3jrhmW-sTmM+tPH+;nwjL#-SjQPUZ53L@A>y*rt(#M(qsiB2 zx6B)dI}6Wlsw%bJ8h|(lhkJVogQZA&n{?Vgs6gNSXzuZpEyu*xySy8ro07QZ7Vk1!3tJphN_5V7qOiyK8p z#@jcDD8nmtYi1^l8ml;AF<#IPK?!pqf9D4moYk>d99Im}Jtwj6c#+A;f)CQ*f-hZ< z=p_T86jog%!p)D&5g9taSwYi&eP z#JuEK%+NULWus;0w32-SYFku#i}d~+{Pkho&^{;RxzP&0!RCm3-9K6`>KZpnzS6?L z^H^V*s!8<>x8bomvD%rh>Zp3>Db%kyin;qtl+jAv8Oo~1g~mqGAC&Qi_wy|xEt2iz zWAJEfTV%cl2Cs<1L&DLRVVH05EDq`pH7Oh7sR`NNkL%wi}8n>IXcO40hp+J+sC!W?!krJf!GJNE8uj zg-y~Ns-<~D?yqbzVRB}G>0A^f0!^N7l=$m0OdZuqAOQqLc zX?AEGr1Ht+inZ-Qiwnl@Z0qukd__a!C*CKuGdy5#nD7VUBM^6OCpxCa2A(X;e0&V4 zM&WR8+wErQ7UIc6LY~Q9x%Sn*Tn>>P`^t&idaOEnOd(Ufw#>NoR^1QdhJ8s`h^|R_ zXX`c5*O~Xdvh%q;7L!_!ohf$NfEBmCde|#uVZvEo>OfEq%+Ns7&_f$OR9xsihRpBb z+cjk8LyDm@U{YN>+r46?nn{7Gh(;WhFw6GAxtcKD+YWV?uge>;+q#Xx4!GpRkVZYu zzsF}1)7$?%s9g9CH=Zs+B%M_)+~*j3L0&Q9u7!|+T`^O{xE6qvAP?XWv9_MrZKdo& z%IyU)$Q95AB4!#hT!_dA>4e@zjOBD*Y=XjtMm)V|+IXzjuM;(l+8aA5#Kaz_$rR6! zj>#&^DidYD$nUY(D$mH`9eb|dtV0b{S>H6FBfq>t5`;OxA4Nn{J(+XihF(stSche7$es&~N$epi&PDM_N`As;*9D^L==2Q7Z2zD+CiU(|+-kL*VG+&9!Yb3LgPy?A zm7Z&^qRG_JIxK7-FBzZI3Q<;{`DIxtc48k> zc|0dmX;Z=W$+)qE)~`yn6MdoJ4co;%!`ddy+FV538Y)j(vg}5*k(WK)KWZ3WaOG!8 z!syGn=s{H$odtpqFrT#JGM*utN7B((abXnpDM6w56nhw}OY}0TiTG1#f*VFZr+^-g zbP10`$LPq_;PvrA1XXlyx2uM^mrjTzX}w{yuLo-cOClE8MMk47T25G8M!9Z5ypOSV zAJUBGEg5L2fY)ZGJb^E34R2zJ?}Vf>{~gB!8=5Z) z9y$>5c)=;o0HeHHSuE4U)#vG&KF|I%-cF6f$~pdYJWk_dD}iOA>iA$O$+4%@>JU08 zS`ep)$XLPJ+n0_i@PkF#ri6T8?ZeAot$6JIYHm&P6EB=BiaNY|aA$W0I+nz*zkz_z zkEru!tj!QUffq%)8y0y`T&`fuus-1p>=^hnBiBqD^hXrPs`PY9tU3m0np~rISY09> z`P3s=-kt_cYcxWd{de@}TwSqg*xVhp;E9zCsnXo6z z?f&Sv^U7n4`xr=mXle94HzOdN!2kB~4=%)u&N!+2;z6UYKUDqi-s6AZ!haB;@&B`? z_TRX0%@suz^TRdCb?!vNJYPY8L_}&07uySH9%W^Tc&1pia6y1q#?*Drf}GjGbPjBS zbOPcUY#*$3sL2x4v_i*Y=N7E$mR}J%|GUI(>WEr+28+V z%v5{#e!UF*6~G&%;l*q*$V?&r$Pp^sE^i-0$+RH3ERUUdQ0>rAq2(2QAbG}$y{de( z>{qD~GGuOk559Y@%$?N^1ApVL_a704>8OD%8Y%8B;FCt%AoPu8*D1 zLB5X>b}Syz81pn;xnB}%0FnwazlWfUV)Z-~rZg6~b z6!9J$EcE&sEbzcy?CI~=boWA&eeIa%z(7SE^qgVLz??1Vbc1*aRvc%Mri)AJaAG!p z$X!_9Ds;Zz)f+;%s&dRcJt2==P{^j3bf0M=nJd&xwUGlUFn?H=2W(*2I2Gdu zv!gYCwM10aeus)`RIZSrCK=&oKaO_Ry~D1B5!y0R=%!i2*KfXGYX&gNv_u+n9wiR5 z*e$Zjju&ODRW3phN925%S(jL+bCHv6rZtc?!*`1TyYXT6%Ju=|X;6D@lq$8T zW{Y|e39ioPez(pBH%k)HzFITXHvnD6hw^lIoUMA;qAJ^CU?top1fo@s7xT13Fvn1H z6JWa-6+FJF#x>~+A;D~;VDs26>^oH0EI`IYT2iagy23?nyJ==i{g4%HrAf1-*v zK1)~@&(KkwR7TL}L(A@C_S0G;-GMDy=MJn2$FP5s<%wC)4jC5PXoxrQBFZ_k0P{{s@sz+gX`-!=T8rcB(=7vW}^K6oLWMmp(rwDh}b zwaGGd>yEy6fHv%jM$yJXo5oMAQ>c9j`**}F?MCry;T@47@r?&sKHgVe$MCqk#Z_3S z1GZI~nOEN*P~+UaFGnj{{Jo@16`(qVNtbU>O0Hf57-P>x8Jikp=`s8xWs^dAJ9lCQ z)GFm+=OV%AMVqVATtN@|vp61VVAHRn87}%PC^RAzJ%JngmZTasWBAWsoAqBU+8L8u z4A&Pe?fmTm0?mK-BL9t+{y7o(7jm+RpOhL9KnY#E&qu^}B6=K_dB}*VlSEiC9fn)+V=J;OnN)Ta5v66ic1rG+dGAJ1 z1%Zb_+!$=tQ~lxQrzv3x#CPb?CekEkA}0MYSgx$Jdd}q8+R=ma$|&1a#)TQ=l$1tQ z=tL9&_^vJ)Pk}EDO-va`UCT1m#Uty1{v^A3P~83_#v^ozH}6*9mIjIr;t3Uv%@VeW zGL6(CwCUp)Jq%G0bIG%?{_*Y#5IHf*5M@wPo6A{$Um++Co$wLC=J1aoG93&T7Ho}P z=mGEPP7GbvoG!uD$k(H3A$Z))+i{Hy?QHdk>3xSBXR0j!11O^mEe9RHmw!pvzv?Ua~2_l2Yh~_!s1qS`|0~0)YsbHSz8!mG)WiJE| z2f($6TQtt6L_f~ApQYQKSb=`053LgrQq7G@98#igV>y#i==-nEjQ!XNu9 z~;mE+gtj4IDDNQJ~JVk5Ux6&LCSFL!y=>79kE9=V}J7tD==Ga+IW zX)r7>VZ9dY=V&}DR))xUoV!u(Z|%3ciQi_2jl}3=$Agc(`RPb z8kEBpvY>1FGQ9W$n>Cq=DIpski};nE)`p3IUw1Oz0|wxll^)4dq3;CCY@RyJgFgc# zKouFh!`?Xuo{IMz^xi-h=StCis_M7yq$u) z?XHvw*HP0VgR+KR6wI)jEMX|ssqYvSf*_3W8zVTQzD?3>H!#>InzpSO)@SC8q*ii- z%%h}_#0{4JG;Jm`4zg};BPTGkYamx$Xo#O~lBirRY)q=5M45n{GCfV7h9qwyu1NxOMoP4)jjZMxmT|IQQh0U7C$EbnMN<3)Kk?fFHYq$d|ICu>KbY_hO zTZM+uKHe(cIZfEqyzyYSUBZa8;Fcut-GN!HSA9ius`ltNebF46ZX_BbZNU}}ZOm{M2&nANL9@0qvih15(|`S~z}m&h!u4x~(%MAO$jHRWNfuxWF#B)E&g3ghSQ9|> z(MFaLQj)NE0lowyjvg8z0#m6FIuKE9lDO~Glg}nSb7`~^&#(Lw{}GVOS>U)m8bF}x zVjbXljBm34Cs-yM6TVusr+3kYFjr28STT3g056y3cH5Tmge~ASxBj z%|yb>$eF;WgrcOZf569sDZOVwoo%8>XO>XQOX1OyN9I-SQgrm;U;+#3OI(zrWyow3 zk==|{lt2xrQ%FIXOTejR>;wv(Pb8u8}BUpx?yd(Abh6? zsoO3VYWkeLnF43&@*#MQ9-i-d0t*xN-UEyNKeyNMHw|A(k(_6QKO=nKMCxD(W(Yop zsRQ)QeL4X3Lxp^L%wzi2-WVSsf61dqliPUM7srDB?Wm6Lzn0&{*}|IsKQW;02(Y&| zaTKv|`U(pSzuvR6Rduu$wzK_W-Y-7>7s?G$)U}&uK;<>vU}^^ns@Z!p+9?St1s)dG zK%y6xkPyyS1$~&6v{kl?Md6gwM|>mt6Upm>oa8RLD^8T{0?HC!Z>;(Bob7el(DV6x zi`I)$&E&ngwFS@bi4^xFLAn`=fzTC;aimE^!cMI2n@Vo%Ae-ne`RF((&5y6xsjjAZ zVguVoQ?Z9uk$2ON;ersE%PU*xGO@T*;j1BO5#TuZKEf(mB7|g7pcEA=nYJ{s3vlbg zd4-DUlD{*6o%Gc^N!Nptgay>j6E5;3psI+C3Q!1ZIbeCubW%w4pq9)MSDyB{HLm|k zxv-{$$A*pS@csolri$Ge<4VZ}e~78JOL-EVyrbxKra^d{?|NnPp86!q>t<&IP07?Z z^>~IK^k#OEKgRH+LjllZXk7iA>2cfH6+(e&9ku5poo~6y{GC5>(bRK7hwjiurqAiZ zg*DmtgY}v83IjE&AbiWgMyFbaRUPZ{lYiz$U^&Zt2YjG<%m((&_JUbZcfJ22(>bi5 z!J?<7AySj0JZ&<-qXX;mcV!f~>G=sB0KnjWca4}vrtunD^1TrpfeS^4dvFr!65knK zZh`d;*VOkPs4*-9kL>$GP0`(M!j~B;#x?Ba~&s6CopvO86oM?-? zOw#dIRc;6A6T?B`Qp%^<U5 z19x(ywSH$_N+Io!6;e?`tWaM$`=Db!gzx|lQ${DG!zb1Zl&|{kX0y6xvO1o z220r<-oaS^^R2pEyY;=Qllqpmue|5yI~D|iI!IGt@iod{Opz@*ml^w2bNs)p`M(Io z|E;;m*Xpjd9l)4G#KaWfV(t8YUn@A;nK^#xgv=LtnArX|vWQVuw3}B${h+frU2>9^ z!l6)!Uo4`5k`<<;E(ido7M6lKTgWezNLq>U*=uz&s=cc$1%>VrAeOoUtA|T6gO4>UNqsdK=NF*8|~*sl&wI=x9-EGiq*aqV!(VVXA57 zw9*o6Ir8Lj1npUXvlevtn(_+^X5rzdR>#(}4YcB9O50q97%rW2me5_L=%ffYPUSRc z!vv?Kv>dH994Qi>U(a<0KF6NH5b16enCp+mw^Hb3Xs1^tThFpz!3QuN#}KBbww`(h z7GO)1olDqy6?T$()R7y%NYx*B0k_2IBiZ14&8|JPFxeMF{vW>HF-Vi3+ZOI=+qP}n zw(+!WcTd~4ZJX1!ZM&y!+uyt=&i!+~d(V%GjH;-NsEEv6nS1TERt|RHh!0>W4+4pp z1-*EzAM~i`+1f(VEHI8So`S`akPfPTfq*`l{Fz`hS%k#JS0cjT2mS0#QLGf=J?1`he3W*;m4)ce8*WFq1sdP=~$5RlH1EdWm|~dCvKOi4*I_96{^95p#B<(n!d?B z=o`0{t+&OMwKcxiBECznJcfH!fL(z3OvmxP#oWd48|mMjpE||zdiTBdWelj8&Qosv zZFp@&UgXuvJw5y=q6*28AtxZzo-UUpkRW%ne+Ylf!V-0+uQXBW=5S1o#6LXNtY5!I z%Rkz#(S8Pjz*P7bqB6L|M#Er{|QLae-Y{KA>`^} z@lPjeX>90X|34S-7}ZVXe{wEei1<{*e8T-Nbj8JmD4iwcE+Hg_zhkPVm#=@b$;)h6 z<<6y`nPa`f3I6`!28d@kdM{uJOgM%`EvlQ5B2bL)Sl=|y@YB3KeOzz=9cUW3clPAU z^sYc}xf9{4Oj?L5MOlYxR{+>w=vJjvbyO5}ptT(o6dR|ygO$)nVCvNGnq(6;bHlBd zl?w-|plD8spjDF03g5ip;W3Z z><0{BCq!Dw;h5~#1BuQilq*TwEu)qy50@+BE4bX28+7erX{BD4H)N+7U`AVEuREE8 z;X?~fyhF-x_sRfHIj~6f(+^@H)D=ngP;mwJjxhQUbUdzk8f94Ab%59-eRIq?ZKrwD z(BFI=)xrUlgu(b|hAysqK<}8bslmNNeD=#JW*}^~Nrswn^xw*nL@Tx!49bfJecV&KC2G4q5a!NSv)06A_5N3Y?veAz;Gv+@U3R% z)~UA8-0LvVE{}8LVDOHzp~2twReqf}ODIyXMM6=W>kL|OHcx9P%+aJGYi_Om)b!xe zF40Vntn0+VP>o<$AtP&JANjXBn7$}C@{+@3I@cqlwR2MdwGhVPxlTIcRVu@Ho-wO` z_~Or~IMG)A_`6-p)KPS@cT9mu9RGA>dVh5wY$NM9-^c@N=hcNaw4ITjm;iWSP^ZX| z)_XpaI61<+La+U&&%2a z0za$)-wZP@mwSELo#3!PGTt$uy0C(nTT@9NX*r3Ctw6J~7A(m#8fE)0RBd`TdKfAT zCf@$MAxjP`O(u9s@c0Fd@|}UQ6qp)O5Q5DPCeE6mSIh|Rj{$cAVIWsA=xPKVKxdhg zLzPZ`3CS+KIO;T}0Ip!fAUaNU>++ZJZRk@I(h<)RsJUhZ&Ru9*!4Ptn;gX^~4E8W^TSR&~3BAZc#HquXn)OW|TJ`CTahk+{qe`5+ixON^zA9IFd8)kc%*!AiLu z>`SFoZ5bW-%7}xZ>gpJcx_hpF$2l+533{gW{a7ce^B9sIdmLrI0)4yivZ^(Vh@-1q zFT!NQK$Iz^xu%|EOK=n>ug;(7J4OnS$;yWmq>A;hsD_0oAbLYhW^1Vdt9>;(JIYjf zdb+&f&D4@4AS?!*XpH>8egQvSVX`36jMd>$+RgI|pEg))^djhGSo&#lhS~9%NuWfX zDDH;3T*GzRT@5=7ibO>N-6_XPBYxno@mD_3I#rDD?iADxX`! zh*v8^i*JEMzyN#bGEBz7;UYXki*Xr(9xXax(_1qVW=Ml)kSuvK$coq2A(5ZGhs_pF z$*w}FbN6+QDseuB9=fdp_MTs)nQf!2SlROQ!gBJBCXD&@-VurqHj0wm@LWX-TDmS= z71M__vAok|@!qgi#H&H%Vg-((ZfxPAL8AI{x|VV!9)ZE}_l>iWk8UPTGHs*?u7RfP z5MC&=c6X;XlUzrz5q?(!eO@~* zoh2I*%J7dF!!_!vXoSIn5o|wj1#_>K*&CIn{qSaRc&iFVxt*^20ngCL;QonIS>I5^ zMw8HXm>W0PGd*}Ko)f|~dDd%;Wu_RWI_d;&2g6R3S63Uzjd7dn%Svu-OKpx*o|N>F zZg=-~qLb~VRLpv`k zWSdfHh@?dp=s_X`{yxOlxE$4iuyS;Z-x!*E6eqmEm*j2bE@=ZI0YZ5%Yj29!5+J$4h{s($nakA`xgbO8w zi=*r}PWz#lTL_DSAu1?f%-2OjD}NHXp4pXOsCW;DS@BC3h-q4_l`<))8WgzkdXg3! zs1WMt32kS2E#L0p_|x+x**TFV=gn`m9BWlzF{b%6j-odf4{7a4y4Uaef@YaeuPhU8 zHBvRqN^;$Jizy+ z=zW{E5<>2gp$pH{M@S*!sJVQU)b*J5*bX4h>5VJve#Q6ga}cQ&iL#=(u+KroWrxa%8&~p{WEUF0il=db;-$=A;&9M{Rq`ouZ5m%BHT6%st%saGsD6)fQgLN}x@d3q>FC;=f%O3Cyg=Ke@Gh`XW za@RajqOE9UB6eE=zhG%|dYS)IW)&y&Id2n7r)6p_)vlRP7NJL(x4UbhlcFXWT8?K=%s7;z?Vjts?y2+r|uk8Wt(DM*73^W%pAkZa1Jd zNoE)8FvQA>Z`eR5Z@Ig6kS5?0h;`Y&OL2D&xnnAUzQz{YSdh0k zB3exx%A2TyI)M*EM6htrxSlep!Kk(P(VP`$p0G~f$smld6W1r_Z+o?=IB@^weq>5VYsYZZR@` z&XJFxd5{|KPZmVOSxc@^%71C@;z}}WhbF9p!%yLj3j%YOlPL5s>7I3vj25 z@xmf=*z%Wb4;Va6SDk9cv|r*lhZ`(y_*M@>q;wrn)oQx%B(2A$9(74>;$zmQ!4fN; z>XurIk-7@wZys<+7XL@0Fhe-f%*=(weaQEdR9Eh6>Kl-EcI({qoZqyzziGwpg-GM#251sK_ z=3|kitS!j%;fpc@oWn65SEL73^N&t>Ix37xgs= zYG%eQDJc|rqHFia0!_sm7`@lvcv)gfy(+KXA@E{3t1DaZ$DijWAcA)E0@X?2ziJ{v z&KOYZ|DdkM{}t+@{@*6ge}m%xfjIxi%qh`=^2Rwz@w0cCvZ&Tc#UmCDbVwABrON^x zEBK43FO@weA8s7zggCOWhMvGGE`baZ62cC)VHyy!5Zbt%ieH+XN|OLbAFPZWyC6)p z4P3%8sq9HdS3=ih^0OOlqTPbKuzQ?lBEI{w^ReUO{V?@`ARsL|S*%yOS=Z%sF)>-y z(LAQdhgAcuF6LQjRYfdbD1g4o%tV4EiK&ElLB&^VZHbrV1K>tHTO{#XTo>)2UMm`2 z^t4s;vnMQgf-njU-RVBRw0P0-m#d-u`(kq7NL&2T)TjI_@iKuPAK-@oH(J8?%(e!0Ir$yG32@CGUPn5w4)+9@8c&pGx z+K3GKESI4*`tYlmMHt@br;jBWTei&(a=iYslc^c#RU3Q&sYp zSG){)V<(g7+8W!Wxeb5zJb4XE{I|&Y4UrFWr%LHkdQ;~XU zgy^dH-Z3lmY+0G~?DrC_S4@=>0oM8Isw%g(id10gWkoz2Q%7W$bFk@mIzTCcIB(K8 zc<5h&ZzCdT=9n-D>&a8vl+=ZF*`uTvQviG_bLde*k>{^)&0o*b05x$MO3gVLUx`xZ z43j+>!u?XV)Yp@MmG%Y`+COH2?nQcMrQ%k~6#O%PeD_WvFO~Kct za4XoCM_X!c5vhRkIdV=xUB3xI2NNStK*8_Zl!cFjOvp-AY=D;5{uXj}GV{LK1~IE2 z|KffUiBaStRr;10R~K2VVtf{TzM7FaPm;Y(zQjILn+tIPSrJh&EMf6evaBKIvi42-WYU9Vhj~3< zZSM-B;E`g_o8_XTM9IzEL=9Lb^SPhe(f(-`Yh=X6O7+6ALXnTcUFpI>ekl6v)ZQeNCg2 z^H|{SKXHU*%nBQ@I3It0m^h+6tvI@FS=MYS$ZpBaG7j#V@P2ZuYySbp@hA# ze(kc;P4i_-_UDP?%<6>%tTRih6VBgScKU^BV6Aoeg6Uh(W^#J^V$Xo^4#Ekp ztqQVK^g9gKMTHvV7nb64UU7p~!B?>Y0oFH5T7#BSW#YfSB@5PtE~#SCCg3p^o=NkMk$<8- z6PT*yIKGrvne7+y3}_!AC8NNeI?iTY(&nakN>>U-zT0wzZf-RuyZk^X9H-DT_*wk= z;&0}6LsGtfVa1q)CEUPlx#(ED@-?H<1_FrHU#z5^P3lEB|qsxEyn%FOpjx z3S?~gvoXy~L(Q{Jh6*i~=f%9kM1>RGjBzQh_SaIDfSU_9!<>*Pm>l)cJD@wlyxpBV z4Fmhc2q=R_wHCEK69<*wG%}mgD1=FHi4h!98B-*vMu4ZGW~%IrYSLGU{^TuseqVgV zLP<%wirIL`VLyJv9XG_p8w@Q4HzNt-o;U@Au{7%Ji;53!7V8Rv0^Lu^Vf*sL>R(;c zQG_ZuFl)Mh-xEIkGu}?_(HwkB2jS;HdPLSxVU&Jxy9*XRG~^HY(f0g8Q}iqnVmgjI zfd=``2&8GsycjR?M%(zMjn;tn9agcq;&rR!Hp z$B*gzHsQ~aXw8c|a(L^LW(|`yGc!qOnV(ZjU_Q-4z1&0;jG&vAKuNG=F|H?@m5^N@ zq{E!1n;)kNTJ>|Hb2ODt-7U~-MOIFo%9I)_@7fnX+eMMNh>)V$IXesJpBn|uo8f~#aOFytCT zf9&%MCLf8mp4kwHTcojWmM3LU=#|{3L>E}SKwOd?%{HogCZ_Z1BSA}P#O(%H$;z7XyJ^sjGX;j5 zrzp>|Ud;*&VAU3x#f{CKwY7Vc{%TKKqmB@oTHA9;>?!nvMA;8+Jh=cambHz#J18x~ zs!dF>$*AnsQ{{82r5Aw&^7eRCdvcgyxH?*DV5(I$qXh^zS>us*I66_MbL8y4d3ULj z{S(ipo+T3Ag!+5`NU2sc+@*m{_X|&p#O-SAqF&g_n7ObB82~$p%fXA5GLHMC+#qqL zdt`sJC&6C2)=juQ_!NeD>U8lDVpAOkW*khf7MCcs$A(wiIl#B9HM%~GtQ^}yBPjT@ z+E=|A!Z?A(rwzZ;T}o6pOVqHzTr*i;Wrc%&36kc@jXq~+w8kVrs;%=IFdACoLAcCAmhFNpbP8;s`zG|HC2Gv?I~w4ITy=g$`0qMQdkijLSOtX6xW%Z9Nw<;M- zMN`c7=$QxN00DiSjbVt9Mi6-pjv*j(_8PyV-il8Q-&TwBwH1gz1uoxs6~uU}PrgWB zIAE_I-a1EqlIaGQNbcp@iI8W1sm9fBBNOk(k&iLBe%MCo#?xI$%ZmGA?=)M9D=0t7 zc)Q0LnI)kCy{`jCGy9lYX%mUsDWwsY`;jE(;Us@gmWPqjmXL+Hu#^;k%eT>{nMtzj zsV`Iy6leTA8-PndszF;N^X@CJrTw5IIm!GPeu)H2#FQitR{1p;MasQVAG3*+=9FYK zw*k!HT(YQorfQj+1*mCV458(T5=fH`um$gS38hw(OqVMyunQ;rW5aPbF##A3fGH6h z@W)i9Uff?qz`YbK4c}JzQpuxuE3pcQO)%xBRZp{zJ^-*|oryTxJ-rR+MXJ)!f=+pp z10H|DdGd2exhi+hftcYbM0_}C0ZI-2vh+$fU1acsB-YXid7O|=9L!3e@$H*6?G*Zp z%qFB(sgl=FcC=E4CYGp4CN>=M8#5r!RU!u+FJVlH6=gI5xHVD&k;Ta*M28BsxfMV~ zLz+@6TxnfLhF@5=yQo^1&S}cmTN@m!7*c6z;}~*!hNBjuE>NLVl2EwN!F+)0$R1S! zR|lF%n!9fkZ@gPW|x|B={V6x3`=jS*$Pu0+5OWf?wnIy>Y1MbbGSncpKO0qE(qO=ts z!~@&!N`10S593pVQu4FzpOh!tvg}p%zCU(aV5=~K#bKi zHdJ1>tQSrhW%KOky;iW+O_n;`l9~omqM%sdxdLtI`TrJzN6BQz+7xOl*rM>xVI2~# z)7FJ^Dc{DC<%~VS?@WXzuOG$YPLC;>#vUJ^MmtbSL`_yXtNKa$Hk+l-c!aC7gn(Cg ze?YPYZ(2Jw{SF6MiO5(%_pTo7j@&DHNW`|lD`~{iH+_eSTS&OC*2WTT*a`?|9w1dh zh1nh@$a}T#WE5$7Od~NvSEU)T(W$p$s5fe^GpG+7fdJ9=enRT9$wEk+ZaB>G3$KQO zgq?-rZZnIv!p#>Ty~}c*Lb_jxJg$eGM*XwHUwuQ|o^}b3^T6Bxx{!?va8aC@-xK*H ztJBFvFfsSWu89%@b^l3-B~O!CXs)I6Y}y#0C0U0R0WG zybjroj$io0j}3%P7zADXOwHwafT#uu*zfM!oD$6aJx7+WL%t-@6^rD_a_M?S^>c;z zMK580bZXo1f*L$CuMeM4Mp!;P@}b~$cd(s5*q~FP+NHSq;nw3fbWyH)i2)-;gQl{S zZO!T}A}fC}vUdskGSq&{`oxt~0i?0xhr6I47_tBc`fqaSrMOzR4>0H^;A zF)hX1nfHs)%Zb-(YGX;=#2R6C{BG;k=?FfP?9{_uFLri~-~AJ;jw({4MU7e*d)?P@ zXX*GkNY9ItFjhwgAIWq7Y!ksbMzfqpG)IrqKx9q{zu%Mdl+{Dis#p9q`02pr1LG8R z@As?eG!>IoROgS!@J*to<27coFc1zpkh?w=)h9CbYe%^Q!Ui46Y*HO0mr% zEff-*$ndMNw}H2a5@BsGj5oFfd!T(F&0$<{GO!Qdd?McKkorh=5{EIjDTHU`So>8V zBA-fqVLb2;u7UhDV1xMI?y>fe3~4urv3%PX)lDw+HYa;HFkaLqi4c~VtCm&Ca+9C~ zge+67hp#R9`+Euq59WhHX&7~RlXn=--m8$iZ~~1C8cv^2(qO#X0?vl91gzUKBeR1J z^p4!!&7)3#@@X&2aF2-)1Ffcc^F8r|RtdL2X%HgN&XU-KH2SLCbpw?J5xJ*!F-ypZ zMG%AJ!Pr&}`LW?E!K~=(NJxuSVTRCGJ$2a*Ao=uUDSys!OFYu!Vs2IT;xQ6EubLIl z+?+nMGeQQhh~??0!s4iQ#gm3!BpMpnY?04kK375e((Uc7B3RMj;wE?BCoQGu=UlZt!EZ1Q*auI)dj3Jj{Ujgt zW5hd~-HWBLI_3HuO) zNrb^XzPsTIb=*a69wAAA3J6AAZZ1VsYbIG}a`=d6?PjM)3EPaDpW2YP$|GrBX{q*! z$KBHNif)OKMBCFP5>!1d=DK>8u+Upm-{hj5o|Wn$vh1&K!lVfDB&47lw$tJ?d5|=B z^(_9=(1T3Fte)z^>|3**n}mIX;mMN5v2F#l(q*CvU{Ga`@VMp#%rQkDBy7kYbmb-q z<5!4iuB#Q_lLZ8}h|hPODI^U6`gzLJre9u3k3c#%86IKI*^H-@I48Bi*@avYm4v!n0+v zWu{M{&F8#p9cx+gF0yTB_<2QUrjMPo9*7^-uP#~gGW~y3nfPAoV%amgr>PSyVAd@l)}8#X zR5zV6t*uKJZL}?NYvPVK6J0v4iVpwiN|>+t3aYiZSp;m0!(1`bHO}TEtWR1tY%BPB z(W!0DmXbZAsT$iC13p4f>u*ZAy@JoLAkJhzFf1#4;#1deO8#8d&89}en&z!W&A3++^1(;>0SB1*54d@y&9Pn;^IAf3GiXbfT`_>{R+Xv; zQvgL>+0#8-laO!j#-WB~(I>l0NCMt_;@Gp_f0#^c)t?&#Xh1-7RR0@zPyBz!U#0Av zT?}n({(p?p7!4S2ZBw)#KdCG)uPnZe+U|0{BW!m)9 zi_9$F?m<`2!`JNFv+w8MK_K)qJ^aO@7-Ig>cM4-r0bi=>?B_2mFNJ}aE3<+QCzRr*NA!QjHw# z`1OsvcoD0?%jq{*7b!l|L1+Tw0TTAM4XMq7*ntc-Ived>Sj_ZtS|uVdpfg1_I9knY z2{GM_j5sDC7(W&}#s{jqbybqJWyn?{PW*&cQIU|*v8YGOKKlGl@?c#TCnmnAkAzV- zmK={|1G90zz=YUvC}+fMqts0d4vgA%t6Jhjv?d;(Z}(Ep8fTZfHA9``fdUHkA+z3+ zhh{ohP%Bj?T~{i0sYCQ}uC#5BwN`skI7`|c%kqkyWIQ;!ysvA8H`b-t()n6>GJj6xlYDu~8qX{AFo$Cm3d|XFL=4uvc?Keb zzb0ZmMoXca6Mob>JqkNuoP>B2Z>D`Q(TvrG6m`j}-1rGP!g|qoL=$FVQYxJQjFn33lODt3Wb1j8VR zlR++vIT6^DtYxAv_hxupbLLN3e0%A%a+hWTKDV3!Fjr^cWJ{scsAdfhpI)`Bms^M6 zQG$waKgFr=c|p9Piug=fcJvZ1ThMnNhQvBAg-8~b1?6wL*WyqXhtj^g(Ke}mEfZVM zJuLNTUVh#WsE*a6uqiz`b#9ZYg3+2%=C(6AvZGc=u&<6??!slB1a9K)=VL zY9EL^mfyKnD zSJyYBc_>G;5RRnrNgzJz#Rkn3S1`mZgO`(r5;Hw6MveN(URf_XS-r58Cn80K)ArH4 z#Rrd~LG1W&@ttw85cjp8xV&>$b%nSXH_*W}7Ch2pg$$c0BdEo-HWRTZcxngIBJad> z;C>b{jIXjb_9Jis?NZJsdm^EG}e*pR&DAy0EaSGi3XWTa(>C%tz1n$u?5Fb z1qtl?;_yjYo)(gB^iQq?=jusF%kywm?CJP~zEHi0NbZ);$(H$w(Hy@{i>$wcVRD_X|w-~(0Z9BJyh zhNh;+eQ9BEIs;tPz%jSVnfCP!3L&9YtEP;svoj_bNzeGSQIAjd zBss@A;)R^WAu-37RQrM%{DfBNRx>v!G31Z}8-El9IOJlb_MSoMu2}GDYycNaf>uny z+8xykD-7ONCM!APry_Lw6-yT>5!tR}W;W`C)1>pxSs5o1z#j7%m=&=7O4hz+Lsqm` z*>{+xsabZPr&X=}G@obTb{nPTkccJX8w3CG7X+1+t{JcMabv~UNv+G?txRqXib~c^Mo}`q{$`;EBNJ;#F*{gvS12kV?AZ%O0SFB$^ zn+}!HbmEj}w{Vq(G)OGAzH}R~kS^;(-s&=ectz8vN!_)Yl$$U@HNTI-pV`LSj7Opu zTZ5zZ)-S_{GcEQPIQXLQ#oMS`HPu{`SQiAZ)m1at*Hy%3xma|>o`h%E%8BEbi9p0r zVjcsh<{NBKQ4eKlXU|}@XJ#@uQw*$4BxKn6#W~I4T<^f99~(=}a`&3(ur8R9t+|AQ zWkQx7l}wa48-jO@ft2h+7qn%SJtL%~890FG0s5g*kNbL3I&@brh&f6)TlM`K^(bhr zJWM6N6x3flOw$@|C@kPi7yP&SP?bzP-E|HSXQXG>7gk|R9BTj`e=4de9C6+H7H7n# z#GJeVs1mtHhLDmVO?LkYRQc`DVOJ_vdl8VUihO-j#t=0T3%Fc1f9F73ufJz*adn*p zc%&vi(4NqHu^R>sAT_0EDjVR8bc%wTz#$;%NU-kbDyL_dg0%TFafZwZ?5KZpcuaO54Z9hX zD$u>q!-9`U6-D`E#`W~fIfiIF5_m6{fvM)b1NG3xf4Auw;Go~Fu7cth#DlUn{@~yu z=B;RT*dp?bO}o%4x7k9v{r=Y@^YQ^UUm(Qmliw8brO^=NP+UOohLYiaEB3^DB56&V zK?4jV61B|1Uj_5fBKW;8LdwOFZKWp)g{B%7g1~DgO&N& z#lisxf?R~Z@?3E$Mms$$JK8oe@X`5m98V*aV6Ua}8Xs2#A!{x?IP|N(%nxsH?^c{& z@vY&R1QmQs83BW28qAmJfS7MYi=h(YK??@EhjL-t*5W!p z^gYX!Q6-vBqcv~ruw@oMaU&qp0Fb(dbVzm5xJN%0o_^@fWq$oa3X?9s%+b)x4w-q5Koe(@j6Ez7V@~NRFvd zfBH~)U5!ix3isg`6be__wBJp=1@yfsCMw1C@y+9WYD9_C%{Q~7^0AF2KFryfLlUP# zwrtJEcH)jm48!6tUcxiurAMaiD04C&tPe6DI0#aoqz#Bt0_7_*X*TsF7u*zv(iEfA z;$@?XVu~oX#1YXtceQL{dSneL&*nDug^OW$DSLF0M1Im|sSX8R26&)<0Fbh^*l6!5wfSu8MpMoh=2l z^^0Sr$UpZp*9oqa23fcCfm7`ya2<4wzJ`Axt7e4jJrRFVf?nY~2&tRL* zd;6_njcz01c>$IvN=?K}9ie%Z(BO@JG2J}fT#BJQ+f5LFSgup7i!xWRKw6)iITjZU z%l6hPZia>R!`aZjwCp}I zg)%20;}f+&@t;(%5;RHL>K_&7MH^S+7<|(SZH!u zznW|jz$uA`P9@ZWtJgv$EFp>)K&Gt+4C6#*khZQXS*S~6N%JDT$r`aJDs9|uXWdbg zBwho$phWx}x!qy8&}6y5Vr$G{yGSE*r$^r{}pw zVTZKvikRZ`J_IJrjc=X1uw?estdwm&bEahku&D04HD+0Bm~q#YGS6gp!KLf$A{%Qd z&&yX@Hp>~(wU{|(#U&Bf92+1i&Q*-S+=y=3pSZy$#8Uc$#7oiJUuO{cE6=tsPhwPe| zxQpK>`Dbka`V)$}e6_OXKLB%i76~4N*zA?X+PrhH<&)}prET;kel24kW%+9))G^JI zsq7L{P}^#QsZViX%KgxBvEugr>ZmFqe^oAg?{EI=&_O#e)F3V#rc z8$4}0Zr19qd3tE4#$3_f=Bbx9oV6VO!d3(R===i-7p=Vj`520w0D3W6lQfY48}!D* z&)lZMG;~er2qBoI2gsX+Ts-hnpS~NYRDtPd^FPzn!^&yxRy#CSz(b&E*tL|jIkq|l zf%>)7Dtu>jCf`-7R#*GhGn4FkYf;B$+9IxmqH|lf6$4irg{0ept__%)V*R_OK=T06 zyT_m-o@Kp6U{l5h>W1hGq*X#8*y@<;vsOFqEjTQXFEotR+{3}ODDnj;o0@!bB5x=N z394FojuGOtVKBlVRLtHp%EJv_G5q=AgF)SKyRN5=cGBjDWv4LDn$IL`*=~J7u&Dy5 zrMc83y+w^F&{?X(KOOAl-sWZDb{9X9#jrQtmrEXD?;h-}SYT7yM(X_6qksM=K_a;Z z3u0qT0TtaNvDER_8x*rxXw&C^|h{P1qxK|@pS7vdlZ#P z7PdB7MmC2}%sdzAxt>;WM1s0??`1983O4nFK|hVAbHcZ3x{PzytQLkCVk7hA!Lo` zEJH?4qw|}WH{dc4z%aB=0XqsFW?^p=X}4xnCJXK%c#ItOSjdSO`UXJyuc8bh^Cf}8 z@Ht|vXd^6{Fgai8*tmyRGmD_s_nv~r^Fy7j`Bu`6=G)5H$i7Q7lvQnmea&TGvJp9a|qOrUymZ$6G|Ly z#zOCg++$3iB$!6!>215A4!iryregKuUT344X)jQb3|9qY>c0LO{6Vby05n~VFzd?q zgGZv&FGlkiH*`fTurp>B8v&nSxNz)=5IF$=@rgND4d`!AaaX;_lK~)-U8la_Wa8i?NJC@BURO*sUW)E9oyv3RG^YGfN%BmxzjlT)bp*$<| zX3tt?EAy<&K+bhIuMs-g#=d1}N_?isY)6Ay$mDOKRh z4v1asEGWoAp=srraLW^h&_Uw|6O+r;wns=uwYm=JN4Q!quD8SQRSeEcGh|Eb5Jg8m zOT}u;N|x@aq)=&;wufCc^#)5U^VcZw;d_wwaoh9$p@Xrc{DD6GZUqZ ziC6OT^zSq@-lhbgR8B+e;7_Giv;DK5gn^$bs<6~SUadiosfewWDJu`XsBfOd1|p=q zE>m=zF}!lObA%ePey~gqU8S6h-^J2Y?>7)L2+%8kV}Gp=h`Xm_}rlm)SyUS=`=S7msKu zC|T!gPiI1rWGb1z$Md?0YJQ;%>uPLOXf1Z>N~`~JHJ!^@D5kSXQ4ugnFZ>^`zH8CAiZmp z6Ms|#2gcGsQ{{u7+Nb9sA?U>(0e$5V1|WVwY`Kn)rsnnZ4=1u=7u!4WexZD^IQ1Jk zfF#NLe>W$3m&C^ULjdw+5|)-BSHwpegdyt9NYC{3@QtMfd8GrIWDu`gd0nv-3LpGCh@wgBaG z176tikL!_NXM+Bv#7q^cyn9$XSeZR6#!B4JE@GVH zoobHZN_*RF#@_SVYKkQ_igme-Y5U}cV(hkR#k1c{bQNMji zU7aE`?dHyx=1`kOYZo_8U7?3-7vHOp`Qe%Z*i+FX!s?6huNp0iCEW-Z7E&jRWmUW_ z67j>)Ew!yq)hhG4o?^z}HWH-e=es#xJUhDRc4B51M4~E-l5VZ!&zQq`gWe`?}#b~7w1LH4Xa-UCT5LXkXQWheBa2YJYbyQ zl1pXR%b(KCXMO0OsXgl0P0Og<{(@&z1aokU-Pq`eQq*JYgt8xdFQ6S z6Z3IFSua8W&M#`~*L#r>Jfd6*BzJ?JFdBR#bDv$_0N!_5vnmo@!>vULcDm`MFU823 zpG9pqjqz^FE5zMDoGqhs5OMmC{Y3iVcl>F}5Rs24Y5B^mYQ;1T&ks@pIApHOdrzXF z-SdX}Hf{X;TaSxG_T$0~#RhqKISGKNK47}0*x&nRIPtmdwxc&QT3$8&!3fWu1eZ_P zJveQj^hJL#Sn!*4k`3}(d(aasl&7G0j0-*_2xtAnoX1@9+h zO#c>YQg60Z;o{Bi=3i7S`Ic+ZE>K{(u|#)9y}q*j8uKQ1^>+(BI}m%1v3$=4ojGBc zm+o1*!T&b}-lVvZqIUBc8V}QyFEgm#oyIuC{8WqUNV{Toz`oxhYpP!_p2oHHh5P@iB*NVo~2=GQm+8Yrkm2Xjc_VyHg1c0>+o~@>*Qzo zHVBJS>$$}$_4EniTI;b1WShX<5-p#TPB&!;lP!lBVBbLOOxh6FuYloD%m;n{r|;MU3!q4AVkua~fieeWu2 zQAQ$ue(IklX6+V;F1vCu-&V?I3d42FgWgsb_e^29ol}HYft?{SLf>DrmOp9o!t>I^ zY7fBCk+E8n_|apgM|-;^=#B?6RnFKlN`oR)`e$+;D=yO-(U^jV;rft^G_zl`n7qnM zL z*-Y4Phq+ZI1$j$F-f;`CD#|`-T~OM5Q>x}a>B~Gb3-+9i>Lfr|Ca6S^8g*{*?_5!x zH_N!SoRP=gX1?)q%>QTY!r77e2j9W(I!uAz{T`NdNmPBBUzi2{`XMB^zJGGwFWeA9 z{fk33#*9SO0)DjROug+(M)I-pKA!CX;IY(#gE!UxXVsa)X!UftIN98{pt#4MJHOhY zM$_l}-TJlxY?LS6Nuz1T<44m<4i^8k@D$zuCPrkmz@sdv+{ciyFJG2Zwy&%c7;atIeTdh!a(R^QXnu1Oq1b42*OQFWnyQ zWeQrdvP|w_idy53Wa<{QH^lFmEd+VlJkyiC>6B#s)F;w-{c;aKIm;Kp50HnA-o3lY z9B~F$gJ@yYE#g#X&3ADx&tO+P_@mnQTz9gv30_sTsaGXkfNYXY{$(>*PEN3QL>I!k zp)KibPhrfX3%Z$H6SY`rXGYS~143wZrG2;=FLj50+VM6soI~up_>fU(2Wl@{BRsMi zO%sL3x?2l1cXTF)k&moNsHfQrQ+wu(gBt{sk#CU=UhrvJIncy@tJX5klLjgMn>~h= zg|FR&;@eh|C7`>s_9c~0-{IAPV){l|Ts`i=)AW;d9&KPc3fMeoTS%8@V~D8*h;&(^>yjT84MM}=%#LS7shLAuuj(0VAYoozhWjq z4LEr?wUe2^WGwdTIgWBkDUJa>YP@5d9^Rs$kCXmMRxuF*YMVrn?0NFyPl}>`&dqZb z<5eqR=ZG3>n2{6v6BvJ`YBZeeTtB88TAY(x0a58EWyuf>+^|x8Qa6wA|1Nb_p|nA zWWa}|z8a)--Wj`LqyFk_a3gN2>5{Rl_wbW?#by7&i*^hRknK%jwIH6=dQ8*-_{*x0j^DUfMX0`|K@6C<|1cgZ~D(e5vBFFm;HTZF(!vT8=T$K+|F)x3kqzBV4-=p1V(lzi(s7jdu0>LD#N=$Lk#3HkG!a zIF<7>%B7sRNzJ66KrFV76J<2bdYhxll0y2^_rdG=I%AgW4~)1Nvz=$1UkE^J%BxLo z+lUci`UcU062os*=`-j4IfSQA{w@y|3}Vk?i;&SSdh8n+$iHA#%ERL{;EpXl6u&8@ zzg}?hkEOUOJt?ZL=pWZFJ19mI1@P=$U5*Im1e_8Z${JsM>Ov?nh8Z zP5QvI!{Jy@&BP48%P2{Jr_VgzW;P@7)M9n|lDT|Ep#}7C$&ud&6>C^5ZiwKIg2McPU(4jhM!BD@@L(Gd*Nu$ji(ljZ<{FIeW_1Mmf;76{LU z-ywN~=uNN)Xi6$<12A9y)K%X|(W0p|&>>4OXB?IiYr||WKDOJPxiSe01NSV-h24^L z_>m$;|C+q!Mj**-qQ$L-*++en(g|hw;M!^%_h-iDjFHLo-n3JpB;p?+o2;`*jpvJU zLY^lt)Un4joij^^)O(CKs@7E%*!w>!HA4Q?0}oBJ7Nr8NQ7QmY^4~jvf0-`%waOLn zdNjAPaC0_7c|RVhw)+71NWjRi!y>C+Bl;Z`NiL^zn2*0kmj5gyhCLCxts*cWCdRI| zjsd=sT5BVJc^$GxP~YF$-U{-?kW6r@^vHXB%{CqYzU@1>dzf#3SYedJG-Rm6^RB7s zGM5PR(yKPKR)>?~vpUIeTP7A1sc8-knnJk*9)3t^e%izbdm>Y=W{$wm(cy1RB-19i za#828DMBY+ps#7Y8^6t)=Ea@%Nkt)O6JCx|ybC;Ap}Z@Zw~*}3P>MZLPb4Enxz9Wf zssobT^(R@KuShj8>@!1M7tm|2%-pYYDxz-5`rCbaTCG5{;Uxm z*g=+H1X8{NUvFGzz~wXa%Eo};I;~`37*WrRU&K0dPSB$yk(Z*@K&+mFal^?c zurbqB-+|Kb5|sznT;?Pj!+kgFY1#Dr;_%A(GIQC{3ct|{*Bji%FNa6c-thbpBkA;U zURV!Dr&X{0J}iht#-Qp2=xzuh(fM>zRoiGrYl5ttw2#r34gC41CCOC31m~^UPTK@s z6;A@)7O7_%C)>bnAXerYuAHdE93>j2N}H${zEc6&SbZ|-fiG*-qtGuy-qDelH(|u$ zorf8_T6Zqe#Ub!+e3oSyrskt_HyW_^5lrWt#30l)tHk|j$@YyEkXUOV;6B51L;M@=NIWZXU;GrAa(LGxO%|im%7F<-6N;en0Cr zLH>l*y?pMwt`1*cH~LdBPFY_l;~`N!Clyfr;7w<^X;&(ZiVdF1S5e(+Q%60zgh)s4 zn2yj$+mE=miVERP(g8}G4<85^-5f@qxh2ec?n+$A_`?qN=iyT1?U@t?V6DM~BIlBB z>u~eXm-aE>R0sQy!-I4xtCNi!!qh?R1!kKf6BoH2GG{L4%PAz0{Sh6xpuyI%*~u)s z%rLuFl)uQUCBQAtMyN;%)zFMx4loh7uTfKeB2Xif`lN?2gq6NhWhfz0u5WP9J>=V2 zo{mLtSy&BA!mSzs&CrKWq^y40JF5a&GSXIi2= z{EYb59J4}VwikL4P=>+mc6{($FNE@e=VUwG+KV21;<@lrN`mnz5jYGASyvz7BOG_6(p^eTxD-4O#lROgon;R35=|nj#eHIfJBYPWG>H>`dHKCDZ3`R{-?HO0mE~(5_WYcFmp8sU?wr*UkAQiNDGc6T zA%}GOLXlOWqL?WwfHO8MB#8M8*~Y*gz;1rWWoVSXP&IbKxbQ8+s%4Jnt?kDsq7btI zCDr0PZ)b;B%!lu&CT#RJzm{l{2fq|BcY85`w~3LSK<><@(2EdzFLt9Y_`;WXL6x`0 zDoQ?=?I@Hbr;*VVll1Gmd8*%tiXggMK81a+T(5Gx6;eNb8=uYn z5BG-0g>pP21NPn>$ntBh>`*})Fl|38oC^9Qz>~MAazH%3Q~Qb!ALMf$srexgPZ2@&c~+hxRi1;}+)-06)!#Mq<6GhP z-Q?qmgo${aFBApb5p}$1OJKTClfi8%PpnczyVKkoHw7Ml9e7ikrF0d~UB}i3vizos zXW4DN$SiEV9{faLt5bHy2a>33K%7Td-n5C*N;f&ZqAg#2hIqEb(y<&f4u5BWJ>2^4 z414GosL=Aom#m&=x_v<0-fp1r%oVJ{T-(xnomNJ(Dryv zh?vj+%=II_nV+@NR+(!fZZVM&(W6{6%9cm+o+Z6}KqzLw{(>E86uA1`_K$HqINlb1 zKelh3-jr2I9V?ych`{hta9wQ2c9=MM`2cC{m6^MhlL2{DLv7C^j z$xXBCnDl_;l|bPGMX@*tV)B!c|4oZyftUlP*?$YU9C_eAsuVHJ58?)zpbr30P*C`T z7y#ao`uE-SOG(Pi+`$=e^mle~)pRrdwL5)N;o{gpW21of(QE#U6w%*C~`v-z0QqBML!!5EeYA5IQB0 z^l01c;L6E(iytN!LhL}wfwP7W9PNAkb+)Cst?qg#$n;z41O4&v+8-zPs+XNb-q zIeeBCh#ivnFLUCwfS;p{LC0O7tm+Sf9Jn)~b%uwP{%69;QC)Ok0t%*a5M+=;y8j=v z#!*pp$9@!x;UMIs4~hP#pnfVc!%-D<+wsG@R2+J&%73lK|2G!EQC)O05TCV=&3g)C!lT=czLpZ@Sa%TYuoE?v8T8`V;e$#Zf2_Nj6nvBgh1)2 GZ~q4|mN%#X literal 62076 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 diff --git a/fabric/1.19.3/gradle/wrapper/gradle-wrapper.properties b/fabric/1.19.3/gradle/wrapper/gradle-wrapper.properties index 37aef8d3..9355b415 100644 --- a/fabric/1.19.3/gradle/wrapper/gradle-wrapper.properties +++ b/fabric/1.19.3/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/fabric/1.19.3/gradlew b/fabric/1.19.3/gradlew index aeb74cbb..f5feea6d 100644 --- a/fabric/1.19.3/gradlew +++ b/fabric/1.19.3/gradlew @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # @@ -55,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -83,7 +85,9 @@ done # This is normally unused # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -130,10 +134,13 @@ location of your Java installation." fi else JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. @@ -141,7 +148,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -149,7 +156,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -198,11 +205,11 @@ fi # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ diff --git a/fabric/1.19.3/gradlew.bat b/fabric/1.19.3/gradlew.bat index 93e3f59f..9d21a218 100644 --- a/fabric/1.19.3/gradlew.bat +++ b/fabric/1.19.3/gradlew.bat @@ -13,6 +13,8 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## @@ -43,11 +45,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -57,11 +59,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail diff --git a/fabric/1.20.2/gradle/wrapper/gradle-wrapper.jar b/fabric/1.20.2/gradle/wrapper/gradle-wrapper.jar index 7f93135c49b765f8051ef9d0a6055ff8e46073d8..a4b76b9530d66f5e68d973ea569d8e19de379189 100644 GIT binary patch literal 43583 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 yu?e%!_ptzGB|8GrCfu%p?(_ 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 GZ~q4|mN%#X literal 63721 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鯊%1Et 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⁢ zv5o9#E7!G0XmdzfsS{efPNi`1b44~SZ4Z8fuX!I}#8g+(wxzQwUT#Xb2(tbY1+EUhGKoT@KEU9Ktl>_0 z%bjDJg;#*gtJZv!-Zs`?^}v5eKmnbjqlvnSzE@_SP|LG_PJ6CYU+6zY6>92%E+ z=j@TZf-iW4(%U{lnYxQA;7Q!b;^brF8n0D>)`q5>|WDDXLrqYU_tKN2>=#@~OE7grMnNh?UOz-O~6 z6%rHy{#h9K0AT+lDC7q4{hw^|q6*Ry;;L%Q@)Ga}$60_q%D)rv(CtS$CQbpq9|y1e zRSrN4;$Jyl{m5bZw`$8TGvb}(LpY{-cQ)fcyJv7l3S52TLXVDsphtv&aPuDk1OzCA z4A^QtC(!11`IsNx_HnSy?>EKpHJWT^wmS~hc^p^zIIh@9f6U@I2 zC=Mve{j2^)mS#U$e{@Q?SO6%LDsXz@SY+=cK_QMmXBIU)j!$ajc-zLx3V60EXJ!qC zi<%2x8Q24YN+&8U@CIlN zrZkcT9yh%LrlGS9`G)KdP(@9Eo-AQz@8GEFWcb7U=a0H^ZVbLmz{+&M7W(nXJ4sN8 zJLR7eeK(K8`2-}j(T7JsO`L!+CvbueT%izanm-^A1Dn{`1Nw`9P?cq;7no+XfC`K(GO9?O^5zNIt4M+M8LM0=7Gz8UA@Z0N+lg+cX)NfazRu z5D)~HA^(u%w^cz+@2@_#S|u>GpB+j4KzQ^&Wcl9f z&hG#bCA(Yk0D&t&aJE^xME^&E-&xGHhXn%}psEIj641H+Nl-}boj;)Zt*t(4wZ5DN z@GXF$bL=&pBq-#vkTkh>7hl%K5|3 z{`Vn9b$iR-SoGENp}bn4;fR3>9sA%X2@1L3aE9yTra;Wb#_`xWwLSLdfu+PAu+o3| zGVnpzPr=ch{uuoHjtw7+_!L_2;knQ!DuDl0R`|%jr+}jFzXtrHIKc323?JO{l&;VF z*L1+}JU7%QJOg|5|Tc|D8fN zJORAg=_vsy{ak|o);@)Yh8Lkcg@$FG3k@ep36BRa^>~UmnRPziS>Z=`Jb2x*Q#`%A zU*i3&Vg?TluO@X0O;r2Jl6LKLUOVhSqg1*qOt^|8*c7 zo(298@+r$k_wQNGHv{|$tW(T8L+4_`FQ{kEW5Jgg{yf7ey4ss_(SNKfz(N9lx&a;< je(UuV8hP?p&}TPdm1I$XmG#(RzlD&B2izSj9sl%y5~4qc diff --git a/fabric/1.20.2/gradle/wrapper/gradle-wrapper.properties b/fabric/1.20.2/gradle/wrapper/gradle-wrapper.properties index ac72c34e..9355b415 100644 --- a/fabric/1.20.2/gradle/wrapper/gradle-wrapper.properties +++ b/fabric/1.20.2/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/fabric/1.20.2/gradlew b/fabric/1.20.2/gradlew index 0adc8e1a..f5feea6d 100644 --- a/fabric/1.20.2/gradlew +++ b/fabric/1.20.2/gradlew @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # @@ -55,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -84,7 +86,8 @@ done # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -145,7 +148,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -153,7 +156,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -202,11 +205,11 @@ fi # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ diff --git a/fabric/1.20.2/gradlew.bat b/fabric/1.20.2/gradlew.bat index 93e3f59f..9d21a218 100644 --- a/fabric/1.20.2/gradlew.bat +++ b/fabric/1.20.2/gradlew.bat @@ -13,6 +13,8 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## @@ -43,11 +45,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -57,11 +59,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail diff --git a/fabric/1.20.6/gradle/wrapper/gradle-wrapper.jar b/fabric/1.20.6/gradle/wrapper/gradle-wrapper.jar index e6441136f3d4ba8a0da8d277868979cfbc8ad796..a4b76b9530d66f5e68d973ea569d8e19de379189 100644 GIT binary patch delta 12612 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 HJ4oML2Lo<@i8BwbL^1~GkG`E7C$SEa_ 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 diff --git a/fabric/1.20.6/gradle/wrapper/gradle-wrapper.properties b/fabric/1.20.6/gradle/wrapper/gradle-wrapper.properties index b82aa23a..9355b415 100644 --- a/fabric/1.20.6/gradle/wrapper/gradle-wrapper.properties +++ b/fabric/1.20.6/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/fabric/1.20.6/gradlew b/fabric/1.20.6/gradlew index 1aa94a42..f5feea6d 100644 --- a/fabric/1.20.6/gradlew +++ b/fabric/1.20.6/gradlew @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # @@ -55,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -84,7 +86,8 @@ done # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum diff --git a/fabric/1.20.6/gradlew.bat b/fabric/1.20.6/gradlew.bat index 25da30db..9d21a218 100644 --- a/fabric/1.20.6/gradlew.bat +++ b/fabric/1.20.6/gradlew.bat @@ -13,6 +13,8 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## diff --git a/fabric/1.20/gradle/wrapper/gradle-wrapper.jar b/fabric/1.20/gradle/wrapper/gradle-wrapper.jar index c1962a79e29d3e0ab67b14947c167a862655af9b..a4b76b9530d66f5e68d973ea569d8e19de379189 100644 GIT binary patch literal 43583 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 yu?e%!_ptzGB|8GrCfu%p?(_ zQccdaaVK$5bz;*rnyK{_SQYM>;aES6Qs^lj9lEs6_J+%nIiuQC*fN;z8md>r_~Mfl zU%p5Dt_YT>gQqfr@`cR!$NWr~+`CZb%dn;WtzrAOI>P_JtsB76PYe*<%H(y>qx-`Kq!X_; z<{RpAqYhE=L1r*M)gNF3B8r(<%8mo*SR2hu zccLRZwGARt)Hlo1euqTyM>^!HK*!Q2P;4UYrysje@;(<|$&%vQekbn|0Ruu_Io(w4#%p6ld2Yp7tlA`Y$cciThP zKzNGIMPXX%&Ud0uQh!uQZz|FB`4KGD?3!ND?wQt6!n*f4EmCoJUh&b?;B{|lxs#F- z31~HQ`SF4x$&v00@(P+j1pAaj5!s`)b2RDBp*PB=2IB>oBF!*6vwr7Dp%zpAx*dPr zb@Zjq^XjN?O4QcZ*O+8>)|HlrR>oD*?WQl5ri3R#2?*W6iJ>>kH%KnnME&TT@ZzrHS$Q%LC?n|e>V+D+8D zYc4)QddFz7I8#}y#Wj6>4P%34dZH~OUDb?uP%-E zwjXM(?Sg~1!|wI(RVuxbu)-rH+O=igSho_pDCw(c6b=P zKk4ATlB?bj9+HHlh<_!&z0rx13K3ZrAR8W)!@Y}o`?a*JJsD+twZIv`W)@Y?Amu_u zz``@-e2X}27$i(2=9rvIu5uTUOVhzwu%mNazS|lZb&PT;XE2|B&W1>=B58#*!~D&) zfVmJGg8UdP*fx(>Cj^?yS^zH#o-$Q-*$SnK(ZVFkw+er=>N^7!)FtP3y~Xxnu^nzY zikgB>Nj0%;WOltWIob|}%lo?_C7<``a5hEkx&1ku$|)i>Rh6@3h*`slY=9U}(Ql_< zaNG*J8vb&@zpdhAvv`?{=zDedJ23TD&Zg__snRAH4eh~^oawdYi6A3w8<Ozh@Kw)#bdktM^GVb zrG08?0bG?|NG+w^&JvD*7LAbjED{_Zkc`3H!My>0u5Q}m!+6VokMLXxl`Mkd=g&Xx z-a>m*#G3SLlhbKB!)tnzfWOBV;u;ftU}S!NdD5+YtOjLg?X}dl>7m^gOpihrf1;PY zvll&>dIuUGs{Qnd- zwIR3oIrct8Va^Tm0t#(bJD7c$Z7DO9*7NnRZorrSm`b`cxz>OIC;jSE3DO8`hX955ui`s%||YQtt2 z5DNA&pG-V+4oI2s*x^>-$6J?p=I>C|9wZF8z;VjR??Icg?1w2v5Me+FgAeGGa8(3S z4vg*$>zC-WIVZtJ7}o9{D-7d>zCe|z#<9>CFve-OPAYsneTb^JH!Enaza#j}^mXy1 z+ULn^10+rWLF6j2>Ya@@Kq?26>AqK{A_| zQKb*~F1>sE*=d?A?W7N2j?L09_7n+HGi{VY;MoTGr_)G9)ot$p!-UY5zZ2Xtbm=t z@dpPSGwgH=QtIcEulQNI>S-#ifbnO5EWkI;$A|pxJd885oM+ zGZ0_0gDvG8q2xebj+fbCHYfAXuZStH2j~|d^sBAzo46(K8n59+T6rzBwK)^rfPT+B zyIFw)9YC-V^rhtK`!3jrhmW-sTmM+tPH+;nwjL#-SjQPUZ53L@A>y*rt(#M(qsiB2 zx6B)dI}6Wlsw%bJ8h|(lhkJVogQZA&n{?Vgs6gNSXzuZpEyu*xySy8ro07QZ7Vk1!3tJphN_5V7qOiyK8p z#@jcDD8nmtYi1^l8ml;AF<#IPK?!pqf9D4moYk>d99Im}Jtwj6c#+A;f)CQ*f-hZ< z=p_T86jog%!p)D&5g9taSwYi&eP z#JuEK%+NULWus;0w32-SYFku#i}d~+{Pkho&^{;RxzP&0!RCm3-9K6`>KZpnzS6?L z^H^V*s!8<>x8bomvD%rh>Zp3>Db%kyin;qtl+jAv8Oo~1g~mqGAC&Qi_wy|xEt2iz zWAJEfTV%cl2Cs<1L&DLRVVH05EDq`pH7Oh7sR`NNkL%wi}8n>IXcO40hp+J+sC!W?!krJf!GJNE8uj zg-y~Ns-<~D?yqbzVRB}G>0A^f0!^N7l=$m0OdZuqAOQqLc zX?AEGr1Ht+inZ-Qiwnl@Z0qukd__a!C*CKuGdy5#nD7VUBM^6OCpxCa2A(X;e0&V4 zM&WR8+wErQ7UIc6LY~Q9x%Sn*Tn>>P`^t&idaOEnOd(Ufw#>NoR^1QdhJ8s`h^|R_ zXX`c5*O~Xdvh%q;7L!_!ohf$NfEBmCde|#uVZvEo>OfEq%+Ns7&_f$OR9xsihRpBb z+cjk8LyDm@U{YN>+r46?nn{7Gh(;WhFw6GAxtcKD+YWV?uge>;+q#Xx4!GpRkVZYu zzsF}1)7$?%s9g9CH=Zs+B%M_)+~*j3L0&Q9u7!|+T`^O{xE6qvAP?XWv9_MrZKdo& z%IyU)$Q95AB4!#hT!_dA>4e@zjOBD*Y=XjtMm)V|+IXzjuM;(l+8aA5#Kaz_$rR6! zj>#&^DidYD$nUY(D$mH`9eb|dtV0b{S>H6FBfq>t5`;OxA4Nn{J(+XihF(stSche7$es&~N$epi&PDM_N`As;*9D^L==2Q7Z2zD+CiU(|+-kL*VG+&9!Yb3LgPy?A zm7Z&^qRG_JIxK7-FBzZI3Q<;{`DIxtc48k> zc|0dmX;Z=W$+)qE)~`yn6MdoJ4co;%!`ddy+FV538Y)j(vg}5*k(WK)KWZ3WaOG!8 z!syGn=s{H$odtpqFrT#JGM*utN7B((abXnpDM6w56nhw}OY}0TiTG1#f*VFZr+^-g zbP10`$LPq_;PvrA1XXlyx2uM^mrjTzX}w{yuLo-cOClE8MMk47T25G8M!9Z5ypOSV zAJUBGEg5L2fY)ZGJb^E34R2zJ?}Vf>{~gB!8=5Z) z9y$>5c)=;o0HeHHSuE4U)#vG&KF|I%-cF6f$~pdYJWk_dD}iOA>iA$O$+4%@>JU08 zS`ep)$XLPJ+n0_i@PkF#ri6T8?ZeAot$6JIYHm&P6EB=BiaNY|aA$W0I+nz*zkz_z zkEru!tj!QUffq%)8y0y`T&`fuus-1p>=^hnBiBqD^hXrPs`PY9tU3m0np~rISY09> z`P3s=-kt_cYcxWd{de@}TwSqg*xVhp;E9zCsnXo6z z?f&Sv^U7n4`xr=mXle94HzOdN!2kB~4=%)u&N!+2;z6UYKUDqi-s6AZ!haB;@&B`? z_TRX0%@suz^TRdCb?!vNJYPY8L_}&07uySH9%W^Tc&1pia6y1q#?*Drf}GjGbPjBS zbOPcUY#*$3sL2x4v_i*Y=N7E$mR}J%|GUI(>WEr+28+V z%v5{#e!UF*6~G&%;l*q*$V?&r$Pp^sE^i-0$+RH3ERUUdQ0>rAq2(2QAbG}$y{de( z>{qD~GGuOk559Y@%$?N^1ApVL_a704>8OD%8Y%8B;FCt%AoPu8*D1 zLB5X>b}Syz81pn;xnB}%0FnwazlWfUV)Z-~rZg6~b z6!9J$EcE&sEbzcy?CI~=boWA&eeIa%z(7SE^qgVLz??1Vbc1*aRvc%Mri)AJaAG!p z$X!_9Ds;Zz)f+;%s&dRcJt2==P{^j3bf0M=nJd&xwUGlUFn?H=2W(*2I2Gdu zv!gYCwM10aeus)`RIZSrCK=&oKaO_Ry~D1B5!y0R=%!i2*KfXGYX&gNv_u+n9wiR5 z*e$Zjju&ODRW3phN925%S(jL+bCHv6rZtc?!*`1TyYXT6%Ju=|X;6D@lq$8T zW{Y|e39ioPez(pBH%k)HzFITXHvnD6hw^lIoUMA;qAJ^CU?top1fo@s7xT13Fvn1H z6JWa-6+FJF#x>~+A;D~;VDs26>^oH0EI`IYT2iagy23?nyJ==i{g4%HrAf1-*v zK1)~@&(KkwR7TL}L(A@C_S0G;-GMDy=MJn2$FP5s<%wC)4jC5PXoxrQBFZ_k0P{{s@sz+gX`-!=T8rcB(=7vW}^K6oLWMmp(rwDh}b zwaGGd>yEy6fHv%jM$yJXo5oMAQ>c9j`**}F?MCry;T@47@r?&sKHgVe$MCqk#Z_3S z1GZI~nOEN*P~+UaFGnj{{Jo@16`(qVNtbU>O0Hf57-P>x8Jikp=`s8xWs^dAJ9lCQ z)GFm+=OV%AMVqVATtN@|vp61VVAHRn87}%PC^RAzJ%JngmZTasWBAWsoAqBU+8L8u z4A&Pe?fmTm0?mK-BL9t+{y7o(7jm+RpOhL9KnY#E&qu^}B6=K_dB}*VlSEiC9fn)+V=J;OnN)Ta5v66ic1rG+dGAJ1 z1%Zb_+!$=tQ~lxQrzv3x#CPb?CekEkA}0MYSgx$Jdd}q8+R=ma$|&1a#)TQ=l$1tQ z=tL9&_^vJ)Pk}EDO-va`UCT1m#Uty1{v^A3P~83_#v^ozH}6*9mIjIr;t3Uv%@VeW zGL6(CwCUp)Jq%G0bIG%?{_*Y#5IHf*5M@wPo6A{$Um++Co$wLC=J1aoG93&T7Ho}P z=mGEPP7GbvoG!uD$k(H3A$Z))+i{Hy?QHdk>3xSBXR0j!11O^mEe9RHmw!pvzv?Ua~2_l2Yh~_!s1qS`|0~0)YsbHSz8!mG)WiJE| z2f($6TQtt6L_f~ApQYQKSb=`053LgrQq7G@98#igV>y#i==-nEjQ!XNu9 z~;mE+gtj4IDDNQJ~JVk5Ux6&LCSFL!y=>79kE9=V}J7tD==Ga+IW zX)r7>VZ9dY=V&}DR))xUoV!u(Z|%3ciQi_2jl}3=$Agc(`RPb z8kEBpvY>1FGQ9W$n>Cq=DIpski};nE)`p3IUw1Oz0|wxll^)4dq3;CCY@RyJgFgc# zKouFh!`?Xuo{IMz^xi-h=StCis_M7yq$u) z?XHvw*HP0VgR+KR6wI)jEMX|ssqYvSf*_3W8zVTQzD?3>H!#>InzpSO)@SC8q*ii- z%%h}_#0{4JG;Jm`4zg};BPTGkYamx$Xo#O~lBirRY)q=5M45n{GCfV7h9qwyu1NxOMoP4)jjZMxmT|IQQh0U7C$EbnMN<3)Kk?fFHYq$d|ICu>KbY_hO zTZM+uKHe(cIZfEqyzyYSUBZa8;Fcut-GN!HSA9ius`ltNebF46ZX_BbZNU}}ZOm{M2&nANL9@0qvih15(|`S~z}m&h!u4x~(%MAO$jHRWNfuxWF#B)E&g3ghSQ9|> z(MFaLQj)NE0lowyjvg8z0#m6FIuKE9lDO~Glg}nSb7`~^&#(Lw{}GVOS>U)m8bF}x zVjbXljBm34Cs-yM6TVusr+3kYFjr28STT3g056y3cH5Tmge~ASxBj z%|yb>$eF;WgrcOZf569sDZOVwoo%8>XO>XQOX1OyN9I-SQgrm;U;+#3OI(zrWyow3 zk==|{lt2xrQ%FIXOTejR>;wv(Pb8u8}BUpx?yd(Abh6? zsoO3VYWkeLnF43&@*#MQ9-i-d0t*xN-UEyNKeyNMHw|A(k(_6QKO=nKMCxD(W(Yop zsRQ)QeL4X3Lxp^L%wzi2-WVSsf61dqliPUM7srDB?Wm6Lzn0&{*}|IsKQW;02(Y&| zaTKv|`U(pSzuvR6Rduu$wzK_W-Y-7>7s?G$)U}&uK;<>vU}^^ns@Z!p+9?St1s)dG zK%y6xkPyyS1$~&6v{kl?Md6gwM|>mt6Upm>oa8RLD^8T{0?HC!Z>;(Bob7el(DV6x zi`I)$&E&ngwFS@bi4^xFLAn`=fzTC;aimE^!cMI2n@Vo%Ae-ne`RF((&5y6xsjjAZ zVguVoQ?Z9uk$2ON;ersE%PU*xGO@T*;j1BO5#TuZKEf(mB7|g7pcEA=nYJ{s3vlbg zd4-DUlD{*6o%Gc^N!Nptgay>j6E5;3psI+C3Q!1ZIbeCubW%w4pq9)MSDyB{HLm|k zxv-{$$A*pS@csolri$Ge<4VZ}e~78JOL-EVyrbxKra^d{?|NnPp86!q>t<&IP07?Z z^>~IK^k#OEKgRH+LjllZXk7iA>2cfH6+(e&9ku5poo~6y{GC5>(bRK7hwjiurqAiZ zg*DmtgY}v83IjE&AbiWgMyFbaRUPZ{lYiz$U^&Zt2YjG<%m((&_JUbZcfJ22(>bi5 z!J?<7AySj0JZ&<-qXX;mcV!f~>G=sB0KnjWca4}vrtunD^1TrpfeS^4dvFr!65knK zZh`d;*VOkPs4*-9kL>$GP0`(M!j~B;#x?Ba~&s6CopvO86oM?-? zOw#dIRc;6A6T?B`Qp%^<U5 z19x(ywSH$_N+Io!6;e?`tWaM$`=Db!gzx|lQ${DG!zb1Zl&|{kX0y6xvO1o z220r<-oaS^^R2pEyY;=Qllqpmue|5yI~D|iI!IGt@iod{Opz@*ml^w2bNs)p`M(Io z|E;;m*Xpjd9l)4G#KaWfV(t8YUn@A;nK^#xgv=LtnArX|vWQVuw3}B${h+frU2>9^ z!l6)!Uo4`5k`<<;E(ido7M6lKTgWezNLq>U*=uz&s=cc$1%>VrAeOoUtA|T6gO4>UNqsdK=NF*8|~*sl&wI=x9-EGiq*aqV!(VVXA57 zw9*o6Ir8Lj1npUXvlevtn(_+^X5rzdR>#(}4YcB9O50q97%rW2me5_L=%ffYPUSRc z!vv?Kv>dH994Qi>U(a<0KF6NH5b16enCp+mw^Hb3Xs1^tThFpz!3QuN#}KBbww`(h z7GO)1olDqy6?T$()R7y%NYx*B0k_2IBiZ14&8|JPFxeMF{vW>HF-Vi3+ZOI=+qP}n zw(+!WcTd~4ZJX1!ZM&y!+uyt=&i!+~d(V%GjH;-NsEEv6nS1TERt|RHh!0>W4+4pp z1-*EzAM~i`+1f(VEHI8So`S`akPfPTfq*`l{Fz`hS%k#JS0cjT2mS0#QLGf=J?1`he3W*;m4)ce8*WFq1sdP=~$5RlH1EdWm|~dCvKOi4*I_96{^95p#B<(n!d?B z=o`0{t+&OMwKcxiBECznJcfH!fL(z3OvmxP#oWd48|mMjpE||zdiTBdWelj8&Qosv zZFp@&UgXuvJw5y=q6*28AtxZzo-UUpkRW%ne+Ylf!V-0+uQXBW=5S1o#6LXNtY5!I z%Rkz#(S8Pjz*P7bqB6L|M#Er{|QLae-Y{KA>`^} z@lPjeX>90X|34S-7}ZVXe{wEei1<{*e8T-Nbj8JmD4iwcE+Hg_zhkPVm#=@b$;)h6 z<<6y`nPa`f3I6`!28d@kdM{uJOgM%`EvlQ5B2bL)Sl=|y@YB3KeOzz=9cUW3clPAU z^sYc}xf9{4Oj?L5MOlYxR{+>w=vJjvbyO5}ptT(o6dR|ygO$)nVCvNGnq(6;bHlBd zl?w-|plD8spjDF03g5ip;W3Z z><0{BCq!Dw;h5~#1BuQilq*TwEu)qy50@+BE4bX28+7erX{BD4H)N+7U`AVEuREE8 z;X?~fyhF-x_sRfHIj~6f(+^@H)D=ngP;mwJjxhQUbUdzk8f94Ab%59-eRIq?ZKrwD z(BFI=)xrUlgu(b|hAysqK<}8bslmNNeD=#JW*}^~Nrswn^xw*nL@Tx!49bfJecV&KC2G4q5a!NSv)06A_5N3Y?veAz;Gv+@U3R% z)~UA8-0LvVE{}8LVDOHzp~2twReqf}ODIyXMM6=W>kL|OHcx9P%+aJGYi_Om)b!xe zF40Vntn0+VP>o<$AtP&JANjXBn7$}C@{+@3I@cqlwR2MdwGhVPxlTIcRVu@Ho-wO` z_~Or~IMG)A_`6-p)KPS@cT9mu9RGA>dVh5wY$NM9-^c@N=hcNaw4ITjm;iWSP^ZX| z)_XpaI61<+La+U&&%2a z0za$)-wZP@mwSELo#3!PGTt$uy0C(nTT@9NX*r3Ctw6J~7A(m#8fE)0RBd`TdKfAT zCf@$MAxjP`O(u9s@c0Fd@|}UQ6qp)O5Q5DPCeE6mSIh|Rj{$cAVIWsA=xPKVKxdhg zLzPZ`3CS+KIO;T}0Ip!fAUaNU>++ZJZRk@I(h<)RsJUhZ&Ru9*!4Ptn;gX^~4E8W^TSR&~3BAZc#HquXn)OW|TJ`CTahk+{qe`5+ixON^zA9IFd8)kc%*!AiLu z>`SFoZ5bW-%7}xZ>gpJcx_hpF$2l+533{gW{a7ce^B9sIdmLrI0)4yivZ^(Vh@-1q zFT!NQK$Iz^xu%|EOK=n>ug;(7J4OnS$;yWmq>A;hsD_0oAbLYhW^1Vdt9>;(JIYjf zdb+&f&D4@4AS?!*XpH>8egQvSVX`36jMd>$+RgI|pEg))^djhGSo&#lhS~9%NuWfX zDDH;3T*GzRT@5=7ibO>N-6_XPBYxno@mD_3I#rDD?iADxX`! zh*v8^i*JEMzyN#bGEBz7;UYXki*Xr(9xXax(_1qVW=Ml)kSuvK$coq2A(5ZGhs_pF z$*w}FbN6+QDseuB9=fdp_MTs)nQf!2SlROQ!gBJBCXD&@-VurqHj0wm@LWX-TDmS= z71M__vAok|@!qgi#H&H%Vg-((ZfxPAL8AI{x|VV!9)ZE}_l>iWk8UPTGHs*?u7RfP z5MC&=c6X;XlUzrz5q?(!eO@~* zoh2I*%J7dF!!_!vXoSIn5o|wj1#_>K*&CIn{qSaRc&iFVxt*^20ngCL;QonIS>I5^ zMw8HXm>W0PGd*}Ko)f|~dDd%;Wu_RWI_d;&2g6R3S63Uzjd7dn%Svu-OKpx*o|N>F zZg=-~qLb~VRLpv`k zWSdfHh@?dp=s_X`{yxOlxE$4iuyS;Z-x!*E6eqmEm*j2bE@=ZI0YZ5%Yj29!5+J$4h{s($nakA`xgbO8w zi=*r}PWz#lTL_DSAu1?f%-2OjD}NHXp4pXOsCW;DS@BC3h-q4_l`<))8WgzkdXg3! zs1WMt32kS2E#L0p_|x+x**TFV=gn`m9BWlzF{b%6j-odf4{7a4y4Uaef@YaeuPhU8 zHBvRqN^;$Jizy+ z=zW{E5<>2gp$pH{M@S*!sJVQU)b*J5*bX4h>5VJve#Q6ga}cQ&iL#=(u+KroWrxa%8&~p{WEUF0il=db;-$=A;&9M{Rq`ouZ5m%BHT6%st%saGsD6)fQgLN}x@d3q>FC;=f%O3Cyg=Ke@Gh`XW za@RajqOE9UB6eE=zhG%|dYS)IW)&y&Id2n7r)6p_)vlRP7NJL(x4UbhlcFXWT8?K=%s7;z?Vjts?y2+r|uk8Wt(DM*73^W%pAkZa1Jd zNoE)8FvQA>Z`eR5Z@Ig6kS5?0h;`Y&OL2D&xnnAUzQz{YSdh0k zB3exx%A2TyI)M*EM6htrxSlep!Kk(P(VP`$p0G~f$smld6W1r_Z+o?=IB@^weq>5VYsYZZR@` z&XJFxd5{|KPZmVOSxc@^%71C@;z}}WhbF9p!%yLj3j%YOlPL5s>7I3vj25 z@xmf=*z%Wb4;Va6SDk9cv|r*lhZ`(y_*M@>q;wrn)oQx%B(2A$9(74>;$zmQ!4fN; z>XurIk-7@wZys<+7XL@0Fhe-f%*=(weaQEdR9Eh6>Kl-EcI({qoZqyzziGwpg-GM#251sK_ z=3|kitS!j%;fpc@oWn65SEL73^N&t>Ix37xgs= zYG%eQDJc|rqHFia0!_sm7`@lvcv)gfy(+KXA@E{3t1DaZ$DijWAcA)E0@X?2ziJ{v z&KOYZ|DdkM{}t+@{@*6ge}m%xfjIxi%qh`=^2Rwz@w0cCvZ&Tc#UmCDbVwABrON^x zEBK43FO@weA8s7zggCOWhMvGGE`baZ62cC)VHyy!5Zbt%ieH+XN|OLbAFPZWyC6)p z4P3%8sq9HdS3=ih^0OOlqTPbKuzQ?lBEI{w^ReUO{V?@`ARsL|S*%yOS=Z%sF)>-y z(LAQdhgAcuF6LQjRYfdbD1g4o%tV4EiK&ElLB&^VZHbrV1K>tHTO{#XTo>)2UMm`2 z^t4s;vnMQgf-njU-RVBRw0P0-m#d-u`(kq7NL&2T)TjI_@iKuPAK-@oH(J8?%(e!0Ir$yG32@CGUPn5w4)+9@8c&pGx z+K3GKESI4*`tYlmMHt@br;jBWTei&(a=iYslc^c#RU3Q&sYp zSG){)V<(g7+8W!Wxeb5zJb4XE{I|&Y4UrFWr%LHkdQ;~XU zgy^dH-Z3lmY+0G~?DrC_S4@=>0oM8Isw%g(id10gWkoz2Q%7W$bFk@mIzTCcIB(K8 zc<5h&ZzCdT=9n-D>&a8vl+=ZF*`uTvQviG_bLde*k>{^)&0o*b05x$MO3gVLUx`xZ z43j+>!u?XV)Yp@MmG%Y`+COH2?nQcMrQ%k~6#O%PeD_WvFO~Kct za4XoCM_X!c5vhRkIdV=xUB3xI2NNStK*8_Zl!cFjOvp-AY=D;5{uXj}GV{LK1~IE2 z|KffUiBaStRr;10R~K2VVtf{TzM7FaPm;Y(zQjILn+tIPSrJh&EMf6evaBKIvi42-WYU9Vhj~3< zZSM-B;E`g_o8_XTM9IzEL=9Lb^SPhe(f(-`Yh=X6O7+6ALXnTcUFpI>ekl6v)ZQeNCg2 z^H|{SKXHU*%nBQ@I3It0m^h+6tvI@FS=MYS$ZpBaG7j#V@P2ZuYySbp@hA# ze(kc;P4i_-_UDP?%<6>%tTRih6VBgScKU^BV6Aoeg6Uh(W^#J^V$Xo^4#Ekp ztqQVK^g9gKMTHvV7nb64UU7p~!B?>Y0oFH5T7#BSW#YfSB@5PtE~#SCCg3p^o=NkMk$<8- z6PT*yIKGrvne7+y3}_!AC8NNeI?iTY(&nakN>>U-zT0wzZf-RuyZk^X9H-DT_*wk= z;&0}6LsGtfVa1q)CEUPlx#(ED@-?H<1_FrHU#z5^P3lEB|qsxEyn%FOpjx z3S?~gvoXy~L(Q{Jh6*i~=f%9kM1>RGjBzQh_SaIDfSU_9!<>*Pm>l)cJD@wlyxpBV z4Fmhc2q=R_wHCEK69<*wG%}mgD1=FHi4h!98B-*vMu4ZGW~%IrYSLGU{^TuseqVgV zLP<%wirIL`VLyJv9XG_p8w@Q4HzNt-o;U@Au{7%Ji;53!7V8Rv0^Lu^Vf*sL>R(;c zQG_ZuFl)Mh-xEIkGu}?_(HwkB2jS;HdPLSxVU&Jxy9*XRG~^HY(f0g8Q}iqnVmgjI zfd=``2&8GsycjR?M%(zMjn;tn9agcq;&rR!Hp z$B*gzHsQ~aXw8c|a(L^LW(|`yGc!qOnV(ZjU_Q-4z1&0;jG&vAKuNG=F|H?@m5^N@ zq{E!1n;)kNTJ>|Hb2ODt-7U~-MOIFo%9I)_@7fnX+eMMNh>)V$IXesJpBn|uo8f~#aOFytCT zf9&%MCLf8mp4kwHTcojWmM3LU=#|{3L>E}SKwOd?%{HogCZ_Z1BSA}P#O(%H$;z7XyJ^sjGX;j5 zrzp>|Ud;*&VAU3x#f{CKwY7Vc{%TKKqmB@oTHA9;>?!nvMA;8+Jh=cambHz#J18x~ zs!dF>$*AnsQ{{82r5Aw&^7eRCdvcgyxH?*DV5(I$qXh^zS>us*I66_MbL8y4d3ULj z{S(ipo+T3Ag!+5`NU2sc+@*m{_X|&p#O-SAqF&g_n7ObB82~$p%fXA5GLHMC+#qqL zdt`sJC&6C2)=juQ_!NeD>U8lDVpAOkW*khf7MCcs$A(wiIl#B9HM%~GtQ^}yBPjT@ z+E=|A!Z?A(rwzZ;T}o6pOVqHzTr*i;Wrc%&36kc@jXq~+w8kVrs;%=IFdACoLAcCAmhFNpbP8;s`zG|HC2Gv?I~w4ITy=g$`0qMQdkijLSOtX6xW%Z9Nw<;M- zMN`c7=$QxN00DiSjbVt9Mi6-pjv*j(_8PyV-il8Q-&TwBwH1gz1uoxs6~uU}PrgWB zIAE_I-a1EqlIaGQNbcp@iI8W1sm9fBBNOk(k&iLBe%MCo#?xI$%ZmGA?=)M9D=0t7 zc)Q0LnI)kCy{`jCGy9lYX%mUsDWwsY`;jE(;Us@gmWPqjmXL+Hu#^;k%eT>{nMtzj zsV`Iy6leTA8-PndszF;N^X@CJrTw5IIm!GPeu)H2#FQitR{1p;MasQVAG3*+=9FYK zw*k!HT(YQorfQj+1*mCV458(T5=fH`um$gS38hw(OqVMyunQ;rW5aPbF##A3fGH6h z@W)i9Uff?qz`YbK4c}JzQpuxuE3pcQO)%xBRZp{zJ^-*|oryTxJ-rR+MXJ)!f=+pp z10H|DdGd2exhi+hftcYbM0_}C0ZI-2vh+$fU1acsB-YXid7O|=9L!3e@$H*6?G*Zp z%qFB(sgl=FcC=E4CYGp4CN>=M8#5r!RU!u+FJVlH6=gI5xHVD&k;Ta*M28BsxfMV~ zLz+@6TxnfLhF@5=yQo^1&S}cmTN@m!7*c6z;}~*!hNBjuE>NLVl2EwN!F+)0$R1S! zR|lF%n!9fkZ@gPW|x|B={V6x3`=jS*$Pu0+5OWf?wnIy>Y1MbbGSncpKO0qE(qO=ts z!~@&!N`10S593pVQu4FzpOh!tvg}p%zCU(aV5=~K#bKi zHdJ1>tQSrhW%KOky;iW+O_n;`l9~omqM%sdxdLtI`TrJzN6BQz+7xOl*rM>xVI2~# z)7FJ^Dc{DC<%~VS?@WXzuOG$YPLC;>#vUJ^MmtbSL`_yXtNKa$Hk+l-c!aC7gn(Cg ze?YPYZ(2Jw{SF6MiO5(%_pTo7j@&DHNW`|lD`~{iH+_eSTS&OC*2WTT*a`?|9w1dh zh1nh@$a}T#WE5$7Od~NvSEU)T(W$p$s5fe^GpG+7fdJ9=enRT9$wEk+ZaB>G3$KQO zgq?-rZZnIv!p#>Ty~}c*Lb_jxJg$eGM*XwHUwuQ|o^}b3^T6Bxx{!?va8aC@-xK*H ztJBFvFfsSWu89%@b^l3-B~O!CXs)I6Y}y#0C0U0R0WG zybjroj$io0j}3%P7zADXOwHwafT#uu*zfM!oD$6aJx7+WL%t-@6^rD_a_M?S^>c;z zMK580bZXo1f*L$CuMeM4Mp!;P@}b~$cd(s5*q~FP+NHSq;nw3fbWyH)i2)-;gQl{S zZO!T}A}fC}vUdskGSq&{`oxt~0i?0xhr6I47_tBc`fqaSrMOzR4>0H^;A zF)hX1nfHs)%Zb-(YGX;=#2R6C{BG;k=?FfP?9{_uFLri~-~AJ;jw({4MU7e*d)?P@ zXX*GkNY9ItFjhwgAIWq7Y!ksbMzfqpG)IrqKx9q{zu%Mdl+{Dis#p9q`02pr1LG8R z@As?eG!>IoROgS!@J*to<27coFc1zpkh?w=)h9CbYe%^Q!Ui46Y*HO0mr% zEff-*$ndMNw}H2a5@BsGj5oFfd!T(F&0$<{GO!Qdd?McKkorh=5{EIjDTHU`So>8V zBA-fqVLb2;u7UhDV1xMI?y>fe3~4urv3%PX)lDw+HYa;HFkaLqi4c~VtCm&Ca+9C~ zge+67hp#R9`+Euq59WhHX&7~RlXn=--m8$iZ~~1C8cv^2(qO#X0?vl91gzUKBeR1J z^p4!!&7)3#@@X&2aF2-)1Ffcc^F8r|RtdL2X%HgN&XU-KH2SLCbpw?J5xJ*!F-ypZ zMG%AJ!Pr&}`LW?E!K~=(NJxuSVTRCGJ$2a*Ao=uUDSys!OFYu!Vs2IT;xQ6EubLIl z+?+nMGeQQhh~??0!s4iQ#gm3!BpMpnY?04kK375e((Uc7B3RMj;wE?BCoQGu=UlZt!EZ1Q*auI)dj3Jj{Ujgt zW5hd~-HWBLI_3HuO) zNrb^XzPsTIb=*a69wAAA3J6AAZZ1VsYbIG}a`=d6?PjM)3EPaDpW2YP$|GrBX{q*! z$KBHNif)OKMBCFP5>!1d=DK>8u+Upm-{hj5o|Wn$vh1&K!lVfDB&47lw$tJ?d5|=B z^(_9=(1T3Fte)z^>|3**n}mIX;mMN5v2F#l(q*CvU{Ga`@VMp#%rQkDBy7kYbmb-q z<5!4iuB#Q_lLZ8}h|hPODI^U6`gzLJre9u3k3c#%86IKI*^H-@I48Bi*@avYm4v!n0+v zWu{M{&F8#p9cx+gF0yTB_<2QUrjMPo9*7^-uP#~gGW~y3nfPAoV%amgr>PSyVAd@l)}8#X zR5zV6t*uKJZL}?NYvPVK6J0v4iVpwiN|>+t3aYiZSp;m0!(1`bHO}TEtWR1tY%BPB z(W!0DmXbZAsT$iC13p4f>u*ZAy@JoLAkJhzFf1#4;#1deO8#8d&89}en&z!W&A3++^1(;>0SB1*54d@y&9Pn;^IAf3GiXbfT`_>{R+Xv; zQvgL>+0#8-laO!j#-WB~(I>l0NCMt_;@Gp_f0#^c)t?&#Xh1-7RR0@zPyBz!U#0Av zT?}n({(p?p7!4S2ZBw)#KdCG)uPnZe+U|0{BW!m)9 zi_9$F?m<`2!`JNFv+w8MK_K)qJ^aO@7-Ig>cM4-r0bi=>?B_2mFNJ}aE3<+QCzRr*NA!QjHw# z`1OsvcoD0?%jq{*7b!l|L1+Tw0TTAM4XMq7*ntc-Ived>Sj_ZtS|uVdpfg1_I9knY z2{GM_j5sDC7(W&}#s{jqbybqJWyn?{PW*&cQIU|*v8YGOKKlGl@?c#TCnmnAkAzV- zmK={|1G90zz=YUvC}+fMqts0d4vgA%t6Jhjv?d;(Z}(Ep8fTZfHA9``fdUHkA+z3+ zhh{ohP%Bj?T~{i0sYCQ}uC#5BwN`skI7`|c%kqkyWIQ;!ysvA8H`b-t()n6>GJj6xlYDu~8qX{AFo$Cm3d|XFL=4uvc?Keb zzb0ZmMoXca6Mob>JqkNuoP>B2Z>D`Q(TvrG6m`j}-1rGP!g|qoL=$FVQYxJQjFn33lODt3Wb1j8VR zlR++vIT6^DtYxAv_hxupbLLN3e0%A%a+hWTKDV3!Fjr^cWJ{scsAdfhpI)`Bms^M6 zQG$waKgFr=c|p9Piug=fcJvZ1ThMnNhQvBAg-8~b1?6wL*WyqXhtj^g(Ke}mEfZVM zJuLNTUVh#WsE*a6uqiz`b#9ZYg3+2%=C(6AvZGc=u&<6??!slB1a9K)=VL zY9EL^mfyKnD zSJyYBc_>G;5RRnrNgzJz#Rkn3S1`mZgO`(r5;Hw6MveN(URf_XS-r58Cn80K)ArH4 z#Rrd~LG1W&@ttw85cjp8xV&>$b%nSXH_*W}7Ch2pg$$c0BdEo-HWRTZcxngIBJad> z;C>b{jIXjb_9Jis?NZJsdm^EG}e*pR&DAy0EaSGi3XWTa(>C%tz1n$u?5Fb z1qtl?;_yjYo)(gB^iQq?=jusF%kywm?CJP~zEHi0NbZ);$(H$w(Hy@{i>$wcVRD_X|w-~(0Z9BJyh zhNh;+eQ9BEIs;tPz%jSVnfCP!3L&9YtEP;svoj_bNzeGSQIAjd zBss@A;)R^WAu-37RQrM%{DfBNRx>v!G31Z}8-El9IOJlb_MSoMu2}GDYycNaf>uny z+8xykD-7ONCM!APry_Lw6-yT>5!tR}W;W`C)1>pxSs5o1z#j7%m=&=7O4hz+Lsqm` z*>{+xsabZPr&X=}G@obTb{nPTkccJX8w3CG7X+1+t{JcMabv~UNv+G?txRqXib~c^Mo}`q{$`;EBNJ;#F*{gvS12kV?AZ%O0SFB$^ zn+}!HbmEj}w{Vq(G)OGAzH}R~kS^;(-s&=ectz8vN!_)Yl$$U@HNTI-pV`LSj7Opu zTZ5zZ)-S_{GcEQPIQXLQ#oMS`HPu{`SQiAZ)m1at*Hy%3xma|>o`h%E%8BEbi9p0r zVjcsh<{NBKQ4eKlXU|}@XJ#@uQw*$4BxKn6#W~I4T<^f99~(=}a`&3(ur8R9t+|AQ zWkQx7l}wa48-jO@ft2h+7qn%SJtL%~890FG0s5g*kNbL3I&@brh&f6)TlM`K^(bhr zJWM6N6x3flOw$@|C@kPi7yP&SP?bzP-E|HSXQXG>7gk|R9BTj`e=4de9C6+H7H7n# z#GJeVs1mtHhLDmVO?LkYRQc`DVOJ_vdl8VUihO-j#t=0T3%Fc1f9F73ufJz*adn*p zc%&vi(4NqHu^R>sAT_0EDjVR8bc%wTz#$;%NU-kbDyL_dg0%TFafZwZ?5KZpcuaO54Z9hX zD$u>q!-9`U6-D`E#`W~fIfiIF5_m6{fvM)b1NG3xf4Auw;Go~Fu7cth#DlUn{@~yu z=B;RT*dp?bO}o%4x7k9v{r=Y@^YQ^UUm(Qmliw8brO^=NP+UOohLYiaEB3^DB56&V zK?4jV61B|1Uj_5fBKW;8LdwOFZKWp)g{B%7g1~DgO&N& z#lisxf?R~Z@?3E$Mms$$JK8oe@X`5m98V*aV6Ua}8Xs2#A!{x?IP|N(%nxsH?^c{& z@vY&R1QmQs83BW28qAmJfS7MYi=h(YK??@EhjL-t*5W!p z^gYX!Q6-vBqcv~ruw@oMaU&qp0Fb(dbVzm5xJN%0o_^@fWq$oa3X?9s%+b)x4w-q5Koe(@j6Ez7V@~NRFvd zfBH~)U5!ix3isg`6be__wBJp=1@yfsCMw1C@y+9WYD9_C%{Q~7^0AF2KFryfLlUP# zwrtJEcH)jm48!6tUcxiurAMaiD04C&tPe6DI0#aoqz#Bt0_7_*X*TsF7u*zv(iEfA z;$@?XVu~oX#1YXtceQL{dSneL&*nDug^OW$DSLF0M1Im|sSX8R26&)<0Fbh^*l6!5wfSu8MpMoh=2l z^^0Sr$UpZp*9oqa23fcCfm7`ya2<4wzJ`Axt7e4jJrRFVf?nY~2&tRL* zd;6_njcz01c>$IvN=?K}9ie%Z(BO@JG2J}fT#BJQ+f5LFSgup7i!xWRKw6)iITjZU z%l6hPZia>R!`aZjwCp}I zg)%20;}f+&@t;(%5;RHL>K_&7MH^S+7<|(SZH!u zznW|jz$uA`P9@ZWtJgv$EFp>)K&Gt+4C6#*khZQXS*S~6N%JDT$r`aJDs9|uXWdbg zBwho$phWx}x!qy8&}6y5Vr$G{yGSE*r$^r{}pw zVTZKvikRZ`J_IJrjc=X1uw?estdwm&bEahku&D04HD+0Bm~q#YGS6gp!KLf$A{%Qd z&&yX@Hp>~(wU{|(#U&Bf92+1i&Q*-S+=y=3pSZy$#8Uc$#7oiJUuO{cE6=tsPhwPe| zxQpK>`Dbka`V)$}e6_OXKLB%i76~4N*zA?X+PrhH<&)}prET;kel24kW%+9))G^JI zsq7L{P}^#QsZViX%KgxBvEugr>ZmFqe^oAg?{EI=&_O#e)F3V#rc z8$4}0Zr19qd3tE4#$3_f=Bbx9oV6VO!d3(R===i-7p=Vj`520w0D3W6lQfY48}!D* z&)lZMG;~er2qBoI2gsX+Ts-hnpS~NYRDtPd^FPzn!^&yxRy#CSz(b&E*tL|jIkq|l zf%>)7Dtu>jCf`-7R#*GhGn4FkYf;B$+9IxmqH|lf6$4irg{0ept__%)V*R_OK=T06 zyT_m-o@Kp6U{l5h>W1hGq*X#8*y@<;vsOFqEjTQXFEotR+{3}ODDnj;o0@!bB5x=N z394FojuGOtVKBlVRLtHp%EJv_G5q=AgF)SKyRN5=cGBjDWv4LDn$IL`*=~J7u&Dy5 zrMc83y+w^F&{?X(KOOAl-sWZDb{9X9#jrQtmrEXD?;h-}SYT7yM(X_6qksM=K_a;Z z3u0qT0TtaNvDER_8x*rxXw&C^|h{P1qxK|@pS7vdlZ#P z7PdB7MmC2}%sdzAxt>;WM1s0??`1983O4nFK|hVAbHcZ3x{PzytQLkCVk7hA!Lo` zEJH?4qw|}WH{dc4z%aB=0XqsFW?^p=X}4xnCJXK%c#ItOSjdSO`UXJyuc8bh^Cf}8 z@Ht|vXd^6{Fgai8*tmyRGmD_s_nv~r^Fy7j`Bu`6=G)5H$i7Q7lvQnmea&TGvJp9a|qOrUymZ$6G|Ly z#zOCg++$3iB$!6!>215A4!iryregKuUT344X)jQb3|9qY>c0LO{6Vby05n~VFzd?q zgGZv&FGlkiH*`fTurp>B8v&nSxNz)=5IF$=@rgND4d`!AaaX;_lK~)-U8la_Wa8i?NJC@BURO*sUW)E9oyv3RG^YGfN%BmxzjlT)bp*$<| zX3tt?EAy<&K+bhIuMs-g#=d1}N_?isY)6Ay$mDOKRh z4v1asEGWoAp=srraLW^h&_Uw|6O+r;wns=uwYm=JN4Q!quD8SQRSeEcGh|Eb5Jg8m zOT}u;N|x@aq)=&;wufCc^#)5U^VcZw;d_wwaoh9$p@Xrc{DD6GZUqZ ziC6OT^zSq@-lhbgR8B+e;7_Giv;DK5gn^$bs<6~SUadiosfewWDJu`XsBfOd1|p=q zE>m=zF}!lObA%ePey~gqU8S6h-^J2Y?>7)L2+%8kV}Gp=h`Xm_}rlm)SyUS=`=S7msKu zC|T!gPiI1rWGb1z$Md?0YJQ;%>uPLOXf1Z>N~`~JHJ!^@D5kSXQ4ugnFZ>^`zH8CAiZmp z6Ms|#2gcGsQ{{u7+Nb9sA?U>(0e$5V1|WVwY`Kn)rsnnZ4=1u=7u!4WexZD^IQ1Jk zfF#NLe>W$3m&C^ULjdw+5|)-BSHwpegdyt9NYC{3@QtMfd8GrIWDu`gd0nv-3LpGCh@wgBaG z176tikL!_NXM+Bv#7q^cyn9$XSeZR6#!B4JE@GVH zoobHZN_*RF#@_SVYKkQ_igme-Y5U}cV(hkR#k1c{bQNMji zU7aE`?dHyx=1`kOYZo_8U7?3-7vHOp`Qe%Z*i+FX!s?6huNp0iCEW-Z7E&jRWmUW_ z67j>)Ew!yq)hhG4o?^z}HWH-e=es#xJUhDRc4B51M4~E-l5VZ!&zQq`gWe`?}#b~7w1LH4Xa-UCT5LXkXQWheBa2YJYbyQ zl1pXR%b(KCXMO0OsXgl0P0Og<{(@&z1aokU-Pq`eQq*JYgt8xdFQ6S z6Z3IFSua8W&M#`~*L#r>Jfd6*BzJ?JFdBR#bDv$_0N!_5vnmo@!>vULcDm`MFU823 zpG9pqjqz^FE5zMDoGqhs5OMmC{Y3iVcl>F}5Rs24Y5B^mYQ;1T&ks@pIApHOdrzXF z-SdX}Hf{X;TaSxG_T$0~#RhqKISGKNK47}0*x&nRIPtmdwxc&QT3$8&!3fWu1eZ_P zJveQj^hJL#Sn!*4k`3}(d(aasl&7G0j0-*_2xtAnoX1@9+h zO#c>YQg60Z;o{Bi=3i7S`Ic+ZE>K{(u|#)9y}q*j8uKQ1^>+(BI}m%1v3$=4ojGBc zm+o1*!T&b}-lVvZqIUBc8V}QyFEgm#oyIuC{8WqUNV{Toz`oxhYpP!_p2oHHh5P@iB*NVo~2=GQm+8Yrkm2Xjc_VyHg1c0>+o~@>*Qzo zHVBJS>$$}$_4EniTI;b1WShX<5-p#TPB&!;lP!lBVBbLOOxh6FuYloD%m;n{r|;MU3!q4AVkua~fieeWu2 zQAQ$ue(IklX6+V;F1vCu-&V?I3d42FgWgsb_e^29ol}HYft?{SLf>DrmOp9o!t>I^ zY7fBCk+E8n_|apgM|-;^=#B?6RnFKlN`oR)`e$+;D=yO-(U^jV;rft^G_zl`n7qnM zL z*-Y4Phq+ZI1$j$F-f;`CD#|`-T~OM5Q>x}a>B~Gb3-+9i>Lfr|Ca6S^8g*{*?_5!x zH_N!SoRP=gX1?)q%>QTY!r77e2j9W(I!uAz{T`NdNmPBBUzi2{`XMB^zJGGwFWeA9 z{fk33#*9SO0)DjROug+(M)I-pKA!CX;IY(#gE!UxXVsa)X!UftIN98{pt#4MJHOhY zM$_l}-TJlxY?LS6Nuz1T<44m<4i^8k@D$zuCPrkmz@sdv+{ciyFJG2Zwy&%c7;atIeTdh!a(R^QXnu1Oq1b42*OQFWnyQ zWeQrdvP|w_idy53Wa<{QH^lFmEd+VlJkyiC>6B#s)F;w-{c;aKIm;Kp50HnA-o3lY z9B~F$gJ@yYE#g#X&3ADx&tO+P_@mnQTz9gv30_sTsaGXkfNYXY{$(>*PEN3QL>I!k zp)KibPhrfX3%Z$H6SY`rXGYS~143wZrG2;=FLj50+VM6soI~up_>fU(2Wl@{BRsMi zO%sL3x?2l1cXTF)k&moNsHfQrQ+wu(gBt{sk#CU=UhrvJIncy@tJX5klLjgMn>~h= zg|FR&;@eh|C7`>s_9c~0-{IAPV){l|Ts`i=)AW;d9&KPc3fMeoTS%8@V~D8*h;&(^>yjT84MM}=%#LS7shLAuuj(0VAYoozhWjq z4LEr?wUe2^WGwdTIgWBkDUJa>YP@5d9^Rs$kCXmMRxuF*YMVrn?0NFyPl}>`&dqZb z<5eqR=ZG3>n2{6v6BvJ`YBZeeTtB88TAY(x0a58EWyuf>+^|x8Qa6wA|1Nb_p|nA zWWa}|z8a)--Wj`LqyFk_a3gN2>5{Rl_wbW?#by7&i*^hRknK%jwIH6=dQ8*-_{*x0j^DUfMX0`|K@6C<|1cgZ~D(e5vBFFm;HTZF(!vT8=T$K+|F)x3kqzBV4-=p1V(lzi(s7jdu0>LD#N=$Lk#3HkG!a zIF<7>%B7sRNzJ66KrFV76J<2bdYhxll0y2^_rdG=I%AgW4~)1Nvz=$1UkE^J%BxLo z+lUci`UcU062os*=`-j4IfSQA{w@y|3}Vk?i;&SSdh8n+$iHA#%ERL{;EpXl6u&8@ zzg}?hkEOUOJt?ZL=pWZFJ19mI1@P=$U5*Im1e_8Z${JsM>Ov?nh8Z zP5QvI!{Jy@&BP48%P2{Jr_VgzW;P@7)M9n|lDT|Ep#}7C$&ud&6>C^5ZiwKIg2McPU(4jhM!BD@@L(Gd*Nu$ji(ljZ<{FIeW_1Mmf;76{LU z-ywN~=uNN)Xi6$<12A9y)K%X|(W0p|&>>4OXB?IiYr||WKDOJPxiSe01NSV-h24^L z_>m$;|C+q!Mj**-qQ$L-*++en(g|hw;M!^%_h-iDjFHLo-n3JpB;p?+o2;`*jpvJU zLY^lt)Un4joij^^)O(CKs@7E%*!w>!HA4Q?0}oBJ7Nr8NQ7QmY^4~jvf0-`%waOLn zdNjAPaC0_7c|RVhw)+71NWjRi!y>C+Bl;Z`NiL^zn2*0kmj5gyhCLCxts*cWCdRI| zjsd=sT5BVJc^$GxP~YF$-U{-?kW6r@^vHXB%{CqYzU@1>dzf#3SYedJG-Rm6^RB7s zGM5PR(yKPKR)>?~vpUIeTP7A1sc8-knnJk*9)3t^e%izbdm>Y=W{$wm(cy1RB-19i za#828DMBY+ps#7Y8^6t)=Ea@%Nkt)O6JCx|ybC;Ap}Z@Zw~*}3P>MZLPb4Enxz9Wf zssobT^(R@KuShj8>@!1M7tm|2%-pYYDxz-5`rCbaTCG5{;Uxm z*g=+H1X8{NUvFGzz~wXa%Eo};I;~`37*WrRU&K0dPSB$yk(Z*@K&+mFal^?c zurbqB-+|Kb5|sznT;?Pj!+kgFY1#Dr;_%A(GIQC{3ct|{*Bji%FNa6c-thbpBkA;U zURV!Dr&X{0J}iht#-Qp2=xzuh(fM>zRoiGrYl5ttw2#r34gC41CCOC31m~^UPTK@s z6;A@)7O7_%C)>bnAXerYuAHdE93>j2N}H${zEc6&SbZ|-fiG*-qtGuy-qDelH(|u$ zorf8_T6Zqe#Ub!+e3oSyrskt_HyW_^5lrWt#30l)tHk|j$@YyEkXUOV;6B51L;M@=NIWZXU;GrAa(LGxO%|im%7F<-6N;en0Cr zLH>l*y?pMwt`1*cH~LdBPFY_l;~`N!Clyfr;7w<^X;&(ZiVdF1S5e(+Q%60zgh)s4 zn2yj$+mE=miVERP(g8}G4<85^-5f@qxh2ec?n+$A_`?qN=iyT1?U@t?V6DM~BIlBB z>u~eXm-aE>R0sQy!-I4xtCNi!!qh?R1!kKf6BoH2GG{L4%PAz0{Sh6xpuyI%*~u)s z%rLuFl)uQUCBQAtMyN;%)zFMx4loh7uTfKeB2Xif`lN?2gq6NhWhfz0u5WP9J>=V2 zo{mLtSy&BA!mSzs&CrKWq^y40JF5a&GSXIi2= z{EYb59J4}VwikL4P=>+mc6{($FNE@e=VUwG+KV21;<@lrN`mnz5jYGASyvz7BOG_6(p^eTxD-4O#lROgon;R35=|nj#eHIfJBYPWG>H>`dHKCDZ3`R{-?HO0mE~(5_WYcFmp8sU?wr*UkAQiNDGc6T zA%}GOLXlOWqL?WwfHO8MB#8M8*~Y*gz;1rWWoVSXP&IbKxbQ8+s%4Jnt?kDsq7btI zCDr0PZ)b;B%!lu&CT#RJzm{l{2fq|BcY85`w~3LSK<><@(2EdzFLt9Y_`;WXL6x`0 zDoQ?=?I@Hbr;*VVll1Gmd8*%tiXggMK81a+T(5Gx6;eNb8=uYn z5BG-0g>pP21NPn>$ntBh>`*})Fl|38oC^9Qz>~MAazH%3Q~Qb!ALMf$srexgPZ2@&c~+hxRi1;}+)-06)!#Mq<6GhP z-Q?qmgo${aFBApb5p}$1OJKTClfi8%PpnczyVKkoHw7Ml9e7ikrF0d~UB}i3vizos zXW4DN$SiEV9{faLt5bHy2a>33K%7Td-n5C*N;f&ZqAg#2hIqEb(y<&f4u5BWJ>2^4 z414GosL=Aom#m&=x_v<0-fp1r%oVJ{T-(xnomNJ(Dryv zh?vj+%=II_nV+@NR+(!fZZVM&(W6{6%9cm+o+Z6}KqzLw{(>E86uA1`_K$HqINlb1 zKelh3-jr2I9V?ych`{hta9wQ2c9=MM`2cC{m6^MhlL2{DLv7C^j z$xXBCnDl_;l|bPGMX@*tV)B!c|4oZyftUlP*?$YU9C_eAsuVHJ58?)zpbr30P*C`T z7y#ao`uE-SOG(Pi+`$=e^mle~)pRrdwL5)N;o{gpW21of(QE#U6w%*C~`v-z0QqBML!!5EeYA5IQB0 z^l01c;L6E(iytN!LhL}wfwP7W9PNAkb+)Cst?qg#$n;z41O4&v+8-zPs+XNb-q zIeeBCh#ivnFLUCwfS;p{LC0O7tm+Sf9Jn)~b%uwP{%69;QC)Ok0t%*a5M+=;y8j=v z#!*pp$9@!x;UMIs4~hP#pnfVc!%-D<+wsG@R2+J&%73lK|2G!EQC)O05TCV=&3g)C!lT=czLpZ@Sa%TYuoE?v8T8`V;e$#Zf2_Nj6nvBgh1)2 GZ~q4|mN%#X literal 62076 zcmb5VV{~QRw)Y#`wrv{~+qP{x72B%VwzFc}c2cp;N~)5ZbDrJayPv(!dGEd-##*zr z)#n-$y^sH|_dchh3@8{H5D*j;5D<{i*8l5IFJ|DjL!e)upfGNX(kojugZ3I`oH1PvW`wFW_ske0j@lB9bX zO;2)`y+|!@X(fZ1<2n!Qx*)_^Ai@Cv-dF&(vnudG?0CsddG_&Wtae(n|K59ew)6St z#dj7_(Cfwzh$H$5M!$UDd8=4>IQsD3xV=lXUq($;(h*$0^yd+b{qq63f0r_de#!o_ zXDngc>zy`uor)4A^2M#U*DC~i+dc<)Tb1Tv&~Ev@oM)5iJ4Sn#8iRw16XXuV50BS7 zdBL5Mefch(&^{luE{*5qtCZk$oFr3RH=H!c3wGR=HJ(yKc_re_X9pD` zJ;uxPzUfVpgU>DSq?J;I@a+10l0ONXPcDkiYcihREt5~T5Gb}sT0+6Q;AWHl`S5dV>lv%-p9l#xNNy7ZCr%cyqHY%TZ8Q4 zbp&#ov1*$#grNG#1vgfFOLJCaNG@K|2!W&HSh@3@Y%T?3YI75bJp!VP*$*!< z;(ffNS_;@RJ`=c7yX04!u3JP*<8jeqLHVJu#WV&v6wA!OYJS4h<_}^QI&97-;=ojW zQ-1t)7wnxG*5I%U4)9$wlv5Fr;cIizft@&N+32O%B{R1POm$oap@&f| zh+5J{>U6ftv|vAeKGc|zC=kO(+l7_cLpV}-D#oUltScw})N>~JOZLU_0{Ka2e1evz z{^a*ZrLr+JUj;)K&u2CoCAXLC2=fVScI(m_p~0FmF>>&3DHziouln?;sxW`NB}cSX z8?IsJB)Z=aYRz!X=yJn$kyOWK%rCYf-YarNqKzmWu$ZvkP12b4qH zhS9Q>j<}(*frr?z<%9hl*i^#@*O2q(Z^CN)c2c z>1B~D;@YpG?G!Yk+*yn4vM4sO-_!&m6+`k|3zd;8DJnxsBYtI;W3We+FN@|tQ5EW= z!VU>jtim0Mw#iaT8t_<+qKIEB-WwE04lBd%Letbml9N!?SLrEG$nmn7&W(W`VB@5S zaY=sEw2}i@F_1P4OtEw?xj4@D6>_e=m=797#hg}f*l^`AB|Y0# z9=)o|%TZFCY$SzgSjS|8AI-%J4x}J)!IMxY3_KYze`_I=c1nmrk@E8c9?MVRu)7+Ue79|)rBX7tVB7U|w4*h(;Gi3D9le49B38`wuv zp7{4X^p+K4*$@gU(Tq3K1a#3SmYhvI42)GzG4f|u zwQFT1n_=n|jpi=70-yE9LA+d*T8u z`=VmmXJ_f6WmZveZPct$Cgu^~gFiyL>Lnpj*6ee>*0pz=t$IJ}+rE zsf@>jlcG%Wx;Cp5x)YSVvB1$yyY1l&o zvwX=D7k)Dn;ciX?Z)Pn8$flC8#m`nB&(8?RSdBvr?>T9?E$U3uIX7T?$v4dWCa46 z+&`ot8ZTEgp7G+c52oHJ8nw5}a^dwb_l%MOh(ebVj9>_koQP^$2B~eUfSbw9RY$_< z&DDWf2LW;b0ZDOaZ&2^i^g+5uTd;GwO(-bbo|P^;CNL-%?9mRmxEw~5&z=X^Rvbo^WJW=n_%*7974RY}JhFv46> zd}`2|qkd;89l}R;i~9T)V-Q%K)O=yfVKNM4Gbacc7AOd>#^&W&)Xx!Uy5!BHnp9kh z`a(7MO6+Ren#>R^D0K)1sE{Bv>}s6Rb9MT14u!(NpZOe-?4V=>qZ>}uS)!y~;jEUK z&!U7Fj&{WdgU#L0%bM}SYXRtM5z!6M+kgaMKt%3FkjWYh=#QUpt$XX1!*XkpSq-pl zhMe{muh#knk{9_V3%qdDcWDv}v)m4t9 zQhv{;} zc{}#V^N3H>9mFM8`i`0p+fN@GqX+kl|M94$BK3J-X`Hyj8r!#x6Vt(PXjn?N)qedP z=o1T^#?1^a{;bZ&x`U{f?}TMo8ToN zkHj5v|}r}wDEi7I@)Gj+S1aE-GdnLN+$hw!=DzglMaj#{qjXi_dwpr|HL(gcCXwGLEmi|{4&4#OZ4ChceA zKVd4K!D>_N=_X;{poT~4Q+!Le+ZV>=H7v1*l%w`|`Dx8{)McN@NDlQyln&N3@bFpV z_1w~O4EH3fF@IzJ9kDk@7@QctFq8FbkbaH7K$iX=bV~o#gfh?2JD6lZf(XP>~DACF)fGFt)X%-h1yY~MJU{nA5 ze2zxWMs{YdX3q5XU*9hOH0!_S24DOBA5usB+Ws$6{|AMe*joJ?RxfV}*7AKN9V*~J zK+OMcE@bTD>TG1*yc?*qGqjBN8mgg@h1cJLDv)0!WRPIkC` zZrWXrceVw;fB%3`6kq=a!pq|hFIsQ%ZSlo~)D z|64!aCnw-?>}AG|*iOl44KVf8@|joXi&|)1rB;EQWgm+iHfVbgllP$f!$Wf42%NO5b(j9Bw6L z;0dpUUK$5GX4QbMlTmLM_jJt!ur`_0~$b#BB7FL*%XFf<b__1o)Ao3rlobbN8-(T!1d-bR8D3S0@d zLI!*GMb5s~Q<&sjd}lBb8Nr0>PqE6_!3!2d(KAWFxa{hm`@u|a(%#i(#f8{BP2wbs zt+N_slWF4IF_O|{w`c~)Xvh&R{Au~CFmW#0+}MBd2~X}t9lz6*E7uAD`@EBDe$>7W zzPUkJx<`f$0VA$=>R57^(K^h86>09?>_@M(R4q($!Ck6GG@pnu-x*exAx1jOv|>KH zjNfG5pwm`E-=ydcb+3BJwuU;V&OS=6yM^4Jq{%AVqnTTLwV`AorIDD}T&jWr8pB&j28fVtk_y*JRP^t@l*($UZ z6(B^-PBNZ+z!p?+e8@$&jCv^EWLb$WO=}Scr$6SM*&~B95El~;W_0(Bvoha|uQ1T< zO$%_oLAwf1bW*rKWmlD+@CP&$ObiDy=nh1b2ejz%LO9937N{LDe7gle4i!{}I$;&Y zkexJ9Ybr+lrCmKWg&}p=`2&Gf10orS?4$VrzWidT=*6{KzOGMo?KI0>GL0{iFWc;C z+LPq%VH5g}6V@-tg2m{C!-$fapJ9y}c$U}aUmS{9#0CM*8pC|sfer!)nG7Ji>mfRh z+~6CxNb>6eWKMHBz-w2{mLLwdA7dA-qfTu^A2yG1+9s5k zcF=le_UPYG&q!t5Zd_*E_P3Cf5T6821bO`daa`;DODm8Ih8k89=RN;-asHIigj`n=ux>*f!OC5#;X5i;Q z+V!GUy0|&Y_*8k_QRUA8$lHP;GJ3UUD08P|ALknng|YY13)}!!HW@0z$q+kCH%xet zlWf@BXQ=b=4}QO5eNnN~CzWBbHGUivG=`&eWK}beuV*;?zt=P#pM*eTuy3 zP}c#}AXJ0OIaqXji78l;YrP4sQe#^pOqwZUiiN6^0RCd#D271XCbEKpk`HI0IsN^s zES7YtU#7=8gTn#lkrc~6)R9u&SX6*Jk4GFX7){E)WE?pT8a-%6P+zS6o&A#ml{$WX zABFz#i7`DDlo{34)oo?bOa4Z_lNH>n;f0nbt$JfAl~;4QY@}NH!X|A$KgMmEsd^&Y zt;pi=>AID7ROQfr;MsMtClr5b0)xo|fwhc=qk33wQ|}$@?{}qXcmECh>#kUQ-If0$ zseb{Wf4VFGLNc*Rax#P8ko*=`MwaR-DQ8L8V8r=2N{Gaips2_^cS|oC$+yScRo*uF zUO|5=?Q?{p$inDpx*t#Xyo6=s?bbN}y>NNVxj9NZCdtwRI70jxvm3!5R7yiWjREEd zDUjrsZhS|P&|Ng5r+f^kA6BNN#|Se}_GF>P6sy^e8kBrgMv3#vk%m}9PCwUWJg-AD zFnZ=}lbi*mN-AOm zCs)r=*YQAA!`e#1N>aHF=bb*z*hXH#Wl$z^o}x##ZrUc=kh%OHWhp=7;?8%Xj||@V?1c ziWoaC$^&04;A|T)!Zd9sUzE&$ODyJaBpvqsw19Uiuq{i#VK1!htkdRWBnb z`{rat=nHArT%^R>u#CjjCkw-7%g53|&7z-;X+ewb?OLWiV|#nuc8mp*LuGSi3IP<<*Wyo9GKV7l0Noa4Jr0g3p_$ z*R9{qn=?IXC#WU>48-k5V2Oc_>P;4_)J@bo1|pf=%Rcbgk=5m)CJZ`caHBTm3%!Z9 z_?7LHr_BXbKKr=JD!%?KhwdYSdu8XxPoA{n8^%_lh5cjRHuCY9Zlpz8g+$f@bw@0V z+6DRMT9c|>1^3D|$Vzc(C?M~iZurGH2pXPT%F!JSaAMdO%!5o0uc&iqHx?ImcX6fI zCApkzc~OOnfzAd_+-DcMp&AOQxE_EsMqKM{%dRMI5`5CT&%mQO?-@F6tE*xL?aEGZ z8^wH@wRl`Izx4sDmU>}Ym{ybUm@F83qqZPD6nFm?t?(7>h*?`fw)L3t*l%*iw0Qu#?$5eq!Qc zpQvqgSxrd83NsdO@lL6#{%lsYXWen~d3p4fGBb7&5xqNYJ)yn84!e1PmPo7ChVd%4 zHUsV0Mh?VpzZD=A6%)Qrd~i7 z96*RPbid;BN{Wh?adeD_p8YU``kOrGkNox3D9~!K?w>#kFz!4lzOWR}puS(DmfjJD z`x0z|qB33*^0mZdM&6$|+T>fq>M%yoy(BEjuh9L0>{P&XJ3enGpoQRx`v6$txXt#c z0#N?b5%srj(4xmPvJxrlF3H%OMB!jvfy z;wx8RzU~lb?h_}@V=bh6p8PSb-dG|-T#A?`c&H2`_!u+uenIZe`6f~A7r)`9m8atC zt(b|6Eg#!Q*DfRU=Ix`#B_dK)nnJ_+>Q<1d7W)eynaVn`FNuN~%B;uO2}vXr5^zi2 z!ifIF5@Zlo0^h~8+ixFBGqtweFc`C~JkSq}&*a3C}L?b5Mh-bW=e)({F_g4O3 zb@SFTK3VD9QuFgFnK4Ve_pXc3{S$=+Z;;4+;*{H}Rc;845rP?DLK6G5Y-xdUKkA6E3Dz&5f{F^FjJQ(NSpZ8q-_!L3LL@H* zxbDF{gd^U3uD;)a)sJwAVi}7@%pRM&?5IaUH%+m{E)DlA_$IA1=&jr{KrhD5q&lTC zAa3c)A(K!{#nOvenH6XrR-y>*4M#DpTTOGQEO5Jr6kni9pDW`rvY*fs|ItV;CVITh z=`rxcH2nEJpkQ^(;1c^hfb8vGN;{{oR=qNyKtR1;J>CByul*+=`NydWnSWJR#I2lN zTvgnR|MBx*XFsfdA&;tr^dYaqRZp*2NwkAZE6kV@1f{76e56eUmGrZ>MDId)oqSWw z7d&r3qfazg+W2?bT}F)4jD6sWaw`_fXZGY&wnGm$FRPFL$HzVTH^MYBHWGCOk-89y zA+n+Q6EVSSCpgC~%uHfvyg@ufE^#u?JH?<73A}jj5iILz4Qqk5$+^U(SX(-qv5agK znUkfpke(KDn~dU0>gdKqjTkVk`0`9^0n_wzXO7R!0Thd@S;U`y)VVP&mOd-2 z(hT(|$=>4FY;CBY9#_lB$;|Wd$aOMT5O_3}DYXEHn&Jrc3`2JiB`b6X@EUOD zVl0S{ijm65@n^19T3l%>*;F(?3r3s?zY{thc4%AD30CeL_4{8x6&cN}zN3fE+x<9; zt2j1RRVy5j22-8U8a6$pyT+<`f+x2l$fd_{qEp_bfxfzu>ORJsXaJn4>U6oNJ#|~p z`*ZC&NPXl&=vq2{Ne79AkQncuxvbOG+28*2wU$R=GOmns3W@HE%^r)Fu%Utj=r9t` zd;SVOnA(=MXgnOzI2@3SGKHz8HN~Vpx&!Ea+Df~`*n@8O=0!b4m?7cE^K*~@fqv9q zF*uk#1@6Re_<^9eElgJD!nTA@K9C732tV~;B`hzZ321Ph=^BH?zXddiu{Du5*IPg} zqDM=QxjT!Rp|#Bkp$(mL)aar)f(dOAXUiw81pX0DC|Y4;>Vz>>DMshoips^8Frdv} zlTD=cKa48M>dR<>(YlLPOW%rokJZNF2gp8fwc8b2sN+i6&-pHr?$rj|uFgktK@jg~ zIFS(%=r|QJ=$kvm_~@n=ai1lA{7Z}i+zj&yzY+!t$iGUy|9jH#&oTNJ;JW-3n>DF+ z3aCOzqn|$X-Olu_p7brzn`uk1F*N4@=b=m;S_C?#hy{&NE#3HkATrg?enaVGT^$qIjvgc61y!T$9<1B@?_ibtDZ{G zeXInVr5?OD_nS_O|CK3|RzzMmu+8!#Zb8Ik;rkIAR%6?$pN@d<0dKD2c@k2quB%s( zQL^<_EM6ow8F6^wJN1QcPOm|ehA+dP(!>IX=Euz5qqIq}Y3;ibQtJnkDmZ8c8=Cf3 zu`mJ!Q6wI7EblC5RvP*@)j?}W=WxwCvF3*5Up_`3*a~z$`wHwCy)2risye=1mSp%p zu+tD6NAK3o@)4VBsM!@);qgsjgB$kkCZhaimHg&+k69~drbvRTacWKH;YCK(!rC?8 zP#cK5JPHSw;V;{Yji=55X~S+)%(8fuz}O>*F3)hR;STU`z6T1aM#Wd+FP(M5*@T1P z^06O;I20Sk!bxW<-O;E081KRdHZrtsGJflFRRFS zdi5w9OVDGSL3 zNrC7GVsGN=b;YH9jp8Z2$^!K@h=r-xV(aEH@#JicPy;A0k1>g1g^XeR`YV2HfmqXY zYbRwaxHvf}OlCAwHoVI&QBLr5R|THf?nAevV-=~V8;gCsX>jndvNOcFA+DI+zbh~# zZ7`qNk&w+_+Yp!}j;OYxIfx_{f0-ONc?mHCiCUak=>j>~>YR4#w# zuKz~UhT!L~GfW^CPqG8Lg)&Rc6y^{%3H7iLa%^l}cw_8UuG;8nn9)kbPGXS}p3!L_ zd#9~5CrH8xtUd?{d2y^PJg+z(xIfRU;`}^=OlehGN2=?}9yH$4Rag}*+AWotyxfCJ zHx=r7ZH>j2kV?%7WTtp+-HMa0)_*DBBmC{sd$)np&GEJ__kEd`xB5a2A z*J+yx>4o#ZxwA{;NjhU*1KT~=ZK~GAA;KZHDyBNTaWQ1+;tOFFthnD)DrCn`DjBZ% zk$N5B4^$`n^jNSOr=t(zi8TN4fpaccsb`zOPD~iY=UEK$0Y70bG{idLx@IL)7^(pL z{??Bnu=lDeguDrd%qW1)H)H`9otsOL-f4bSu};o9OXybo6J!Lek`a4ff>*O)BDT_g z<6@SrI|C9klY(>_PfA^qai7A_)VNE4c^ZjFcE$Isp>`e5fLc)rg@8Q_d^Uk24$2bn z9#}6kZ2ZxS9sI(RqT7?El2@B+($>eBQrNi_k#CDJ8D9}8$mmm z4oSKO^F$i+NG)-HE$O6s1--6EzJa?C{x=QgK&c=)b(Q9OVoAXYEEH20G|q$}Hue%~ zO3B^bF=t7t48sN zWh_zA`w~|){-!^g?6Mqf6ieV zFx~aPUOJGR=4{KsW7I?<=J2|lY`NTU=lt=%JE9H1vBpkcn=uq(q~=?iBt_-r(PLBM zP-0dxljJO>4Wq-;stY)CLB4q`-r*T$!K2o}?E-w_i>3_aEbA^MB7P5piwt1dI-6o!qWCy0 ztYy!x9arGTS?kabkkyv*yxvsPQ7Vx)twkS6z2T@kZ|kb8yjm+^$|sEBmvACeqbz)RmxkkDQX-A*K!YFziuhwb|ym>C$}U|J)4y z$(z#)GH%uV6{ec%Zy~AhK|+GtG8u@c884Nq%w`O^wv2#A(&xH@c5M`Vjk*SR_tJnq z0trB#aY)!EKW_}{#L3lph5ow=@|D5LzJYUFD6 z7XnUeo_V0DVSIKMFD_T0AqAO|#VFDc7c?c-Q%#u00F%!_TW1@JVnsfvm@_9HKWflBOUD~)RL``-!P;(bCON_4eVdduMO>?IrQ__*zE@7(OX zUtfH@AX*53&xJW*Pu9zcqxGiM>xol0I~QL5B%Toog3Jlenc^WbVgeBvV8C8AX^Vj& z^I}H})B=VboO%q1;aU5ACMh{yK4J;xlMc`jCnZR^!~LDs_MP&8;dd@4LDWw~*>#OT zeZHwdQWS!tt5MJQI~cw|Ka^b4c|qyd_ly(+Ql2m&AAw^ zQeSXDOOH!!mAgzAp0z)DD>6Xo``b6QwzUV@w%h}Yo>)a|xRi$jGuHQhJVA%>)PUvK zBQ!l0hq<3VZ*RnrDODP)>&iS^wf64C;MGqDvx>|p;35%6(u+IHoNbK z;Gb;TneFo*`zUKS6kwF*&b!U8e5m4YAo03a_e^!5BP42+r)LFhEy?_7U1IR<; z^0v|DhCYMSj<-;MtY%R@Fg;9Kky^pz_t2nJfKWfh5Eu@_l{^ph%1z{jkg5jQrkvD< z#vdK!nku*RrH~TdN~`wDs;d>XY1PH?O<4^U4lmA|wUW{Crrv#r%N>7k#{Gc44Fr|t z@UZP}Y-TrAmnEZ39A*@6;ccsR>)$A)S>$-Cj!=x$rz7IvjHIPM(TB+JFf{ehuIvY$ zsDAwREg*%|=>Hw$`us~RP&3{QJg%}RjJKS^mC_!U;E5u>`X`jW$}P`Mf}?7G7FX#{ zE(9u1SO;3q@ZhDL9O({-RD+SqqPX)`0l5IQu4q)49TUTkxR(czeT}4`WV~pV*KY&i zAl3~X%D2cPVD^B43*~&f%+Op)wl<&|D{;=SZwImydWL6@_RJjxP2g)s=dH)u9Npki zs~z9A+3fj0l?yu4N0^4aC5x)Osnm0qrhz@?nwG_`h(71P znbIewljU%T*cC=~NJy|)#hT+lx#^5MuDDnkaMb*Efw9eThXo|*WOQzJ*#3dmRWm@! zfuSc@#kY{Um^gBc^_Xdxnl!n&y&}R4yAbK&RMc+P^Ti;YIUh|C+K1|=Z^{nZ}}rxH*v{xR!i%qO~o zTr`WDE@k$M9o0r4YUFFeQO7xCu_Zgy)==;fCJ94M_rLAv&~NhfvcLWCoaGg2ao~3e zBG?Ms9B+efMkp}7BhmISGWmJsKI@a8b}4lLI48oWKY|8?zuuNc$lt5Npr+p7a#sWu zh!@2nnLBVJK!$S~>r2-pN||^w|fY`CT{TFnJy`B|e5;=+_v4l8O-fkN&UQbA4NKTyntd zqK{xEKh}U{NHoQUf!M=2(&w+eef77VtYr;xs%^cPfKLObyOV_9q<(%76-J%vR>w9!us-0c-~Y?_EVS%v!* z15s2s3eTs$Osz$JayyH|5nPAIPEX=U;r&p;K14G<1)bvn@?bM5kC{am|C5%hyxv}a z(DeSKI5ZfZ1*%dl8frIX2?);R^^~LuDOpNpk-2R8U1w92HmG1m&|j&J{EK=|p$;f9 z7Rs5|jr4r8k5El&qcuM+YRlKny%t+1CgqEWO>3;BSRZi(LA3U%Jm{@{y+A+w(gzA< z7dBq6a1sEWa4cD0W7=Ld9z0H7RI^Z7vl(bfA;72j?SWCo`#5mVC$l1Q2--%V)-uN* z9ha*s-AdfbDZ8R8*fpwjzx=WvOtmSzGFjC#X)hD%Caeo^OWjS(3h|d9_*U)l%{Ab8 zfv$yoP{OuUl@$(-sEVNt{*=qi5P=lpxWVuz2?I7Dc%BRc+NGNw+323^ z5BXGfS71oP^%apUo(Y#xkxE)y?>BFzEBZ}UBbr~R4$%b7h3iZu3S(|A;&HqBR{nK& z$;GApNnz=kNO^FL&nYcfpB7Qg;hGJPsCW44CbkG1@l9pn0`~oKy5S777uH)l{irK!ru|X+;4&0D;VE*Ii|<3P zUx#xUqvZT5kVQxsF#~MwKnv7;1pR^0;PW@$@T7I?s`_rD1EGUdSA5Q(C<>5SzE!vw z;{L&kKFM-MO>hy#-8z`sdVx})^(Dc-dw;k-h*9O2_YZw}|9^y-|8RQ`BWJUJL(Cer zP5Z@fNc>pTXABbTRY-B5*MphpZv6#i802giwV&SkFCR zGMETyUm(KJbh+&$8X*RB#+{surjr;8^REEt`2&Dubw3$mx>|~B5IKZJ`s_6fw zKAZx9&PwBqW1Oz0r0A4GtnZd7XTKViX2%kPfv+^X3|_}RrQ2e3l=KG_VyY`H?I5&CS+lAX5HbA%TD9u6&s#v!G> zzW9n4J%d5ye7x0y`*{KZvqyXUfMEE^ZIffzI=Hh|3J}^yx7eL=s+TPH(Q2GT-sJ~3 zI463C{(ag7-hS1ETtU;_&+49ABt5!A7CwLwe z=SoA8mYZIQeU;9txI=zcQVbuO%q@E)JI+6Q!3lMc=Gbj(ASg-{V27u>z2e8n;Nc*pf}AqKz1D>p9G#QA+7mqqrEjGfw+85Uyh!=tTFTv3|O z+)-kFe_8FF_EkTw!YzwK^Hi^_dV5x-Ob*UWmD-})qKj9@aE8g240nUh=g|j28^?v7 zHRTBo{0KGaWBbyX2+lx$wgXW{3aUab6Bhm1G1{jTC7ota*JM6t+qy)c5<@ zpc&(jVdTJf(q3xB=JotgF$X>cxh7k*(T`-V~AR+`%e?YOeALQ2Qud( zz35YizXt(aW3qndR}fTw1p()Ol4t!D1pitGNL95{SX4ywzh0SF;=!wf=?Q?_h6!f* zh7<+GFi)q|XBsvXZ^qVCY$LUa{5?!CgwY?EG;*)0ceFe&=A;!~o`ae}Z+6me#^sv- z1F6=WNd6>M(~ z+092z>?Clrcp)lYNQl9jN-JF6n&Y0mp7|I0dpPx+4*RRK+VQI~>en0Dc;Zfl+x z_e_b7s`t1_A`RP3$H}y7F9_na%D7EM+**G_Z0l_nwE+&d_kc35n$Fxkd4r=ltRZhh zr9zER8>j(EdV&Jgh(+i}ltESBK62m0nGH6tCBr90!4)-`HeBmz54p~QP#dsu%nb~W z7sS|(Iydi>C@6ZM(Us!jyIiszMkd)^u<1D+R@~O>HqZIW&kearPWmT>63%_t2B{_G zX{&a(gOYJx!Hq=!T$RZ&<8LDnxsmx9+TBL0gTk$|vz9O5GkK_Yx+55^R=2g!K}NJ3 zW?C;XQCHZl7H`K5^BF!Q5X2^Mj93&0l_O3Ea3!Ave|ixx+~bS@Iv18v2ctpSt4zO{ zp#7pj!AtDmti$T`e9{s^jf(ku&E|83JIJO5Qo9weT6g?@vX!{7)cNwymo1+u(YQ94 zopuz-L@|5=h8A!(g-MXgLJC0MA|CgQF8qlonnu#j z;uCeq9ny9QSD|p)9sp3ebgY3rk#y0DA(SHdh$DUm^?GI<>%e1?&}w(b zdip1;P2Z=1wM+$q=TgLP$}svd!vk+BZ@h<^4R=GS2+sri7Z*2f`9 z5_?i)xj?m#pSVchk-SR!2&uNhzEi+#5t1Z$o0PoLGz*pT64%+|Wa+rd5Z}60(j?X= z{NLjtgRb|W?CUADqOS@(*MA-l|E342NxRaxLTDqsOyfWWe%N(jjBh}G zm7WPel6jXijaTiNita+z(5GCO0NM=Melxud57PP^d_U## zbA;9iVi<@wr0DGB8=T9Ab#2K_#zi=$igyK48@;V|W`fg~7;+!q8)aCOo{HA@vpSy-4`^!ze6-~8|QE||hC{ICKllG9fbg_Y7v z$jn{00!ob3!@~-Z%!rSZ0JO#@>|3k10mLK0JRKP-Cc8UYFu>z93=Ab-r^oL2 zl`-&VBh#=-?{l1TatC;VweM^=M7-DUE>m+xO7Xi6vTEsReyLs8KJ+2GZ&rxw$d4IT zPXy6pu^4#e;;ZTsgmG+ZPx>piodegkx2n0}SM77+Y*j^~ICvp#2wj^BuqRY*&cjmL zcKp78aZt>e{3YBb4!J_2|K~A`lN=u&5j!byw`1itV(+Q_?RvV7&Z5XS1HF)L2v6ji z&kOEPmv+k_lSXb{$)of~(BkO^py&7oOzpjdG>vI1kcm_oPFHy38%D4&A4h_CSo#lX z2#oqMCTEP7UvUR3mwkPxbl8AMW(e{ARi@HCYLPSHE^L<1I}OgZD{I#YH#GKnpRmW3 z2jkz~Sa(D)f?V?$gNi?6)Y;Sm{&?~2p=0&BUl_(@hYeX8YjaRO=IqO7neK0RsSNdYjD zaw$g2sG(>JR=8Iz1SK4`*kqd_3-?;_BIcaaMd^}<@MYbYisWZm2C2|Np_l|8r9yM|JkUngSo@?wci(7&O9a z%|V(4C1c9pps0xxzPbXH=}QTxc2rr7fXk$9`a6TbWKPCz&p=VsB8^W96W=BsB|7bc zf(QR8&Ktj*iz)wK&mW`#V%4XTM&jWNnDF56O+2bo<3|NyUhQ%#OZE8$Uv2a@J>D%t zMVMiHh?es!Ex19q&6eC&L=XDU_BA&uR^^w>fpz2_`U87q_?N2y;!Z!bjoeKrzfC)} z?m^PM=(z{%n9K`p|7Bz$LuC7!>tFOuN74MFELm}OD9?%jpT>38J;=1Y-VWtZAscaI z_8jUZ#GwWz{JqvGEUmL?G#l5E=*m>`cY?m*XOc*yOCNtpuIGD+Z|kn4Xww=BLrNYS zGO=wQh}Gtr|7DGXLF%|`G>J~l{k^*{;S-Zhq|&HO7rC_r;o`gTB7)uMZ|WWIn@e0( zX$MccUMv3ABg^$%_lNrgU{EVi8O^UyGHPNRt%R!1#MQJn41aD|_93NsBQhP80yP<9 zG4(&0u7AtJJXLPcqzjv`S~5;Q|5TVGccN=Uzm}K{v)?f7W!230C<``9(64}D2raRU zAW5bp%}VEo{4Rko`bD%Ehf=0voW?-4Mk#d3_pXTF!-TyIt6U+({6OXWVAa;s-`Ta5 zTqx&8msH3+DLrVmQOTBOAj=uoxKYT3DS1^zBXM?1W+7gI!aQNPYfUl{3;PzS9*F7g zWJN8x?KjBDx^V&6iCY8o_gslO16=kh(|Gp)kz8qlQ`dzxQv;)V&t+B}wwdi~uBs4? zu~G|}y!`3;8#vIMUdyC7YEx6bb^1o}G!Jky4cN?BV9ejBfN<&!4M)L&lRKiuMS#3} z_B}Nkv+zzxhy{dYCW$oGC&J(Ty&7%=5B$sD0bkuPmj7g>|962`(Q{ZZMDv%YMuT^KweiRDvYTEop3IgFv#)(w>1 zSzH>J`q!LK)c(AK>&Ib)A{g`Fdykxqd`Yq@yB}E{gnQV$K!}RsgMGWqC3DKE(=!{}ekB3+(1?g}xF>^icEJbc z5bdxAPkW90atZT+&*7qoLqL#p=>t-(-lsnl2XMpZcYeW|o|a322&)yO_8p(&Sw{|b zn(tY$xn5yS$DD)UYS%sP?c|z>1dp!QUD)l;aW#`%qMtQJjE!s2z`+bTSZmLK7SvCR z=@I4|U^sCwZLQSfd*ACw9B@`1c1|&i^W_OD(570SDLK`MD0wTiR8|$7+%{cF&){$G zU~|$^Ed?TIxyw{1$e|D$050n8AjJvvOWhLtLHbSB|HIfjMp+gu>DraHZJRrdO53(= z+o-f{+qNog+qSLB%KY;5>Av6X(>-qYk3IIEwZ5~6a+P9lMpC^ z8CJ0q>rEpjlsxCvJm=kms@tlN4+sv}He`xkr`S}bGih4t`+#VEIt{1veE z{ZLtb_pSbcfcYPf4=T1+|BtR!x5|X#x2TZEEkUB6kslKAE;x)*0x~ES0kl4Dex4e- zT2P~|lT^vUnMp{7e4OExfxak0EE$Hcw;D$ehTV4a6hqxru0$|Mo``>*a5=1Ym0u>BDJKO|=TEWJ5jZu!W}t$Kv{1!q`4Sn7 zrxRQOt>^6}Iz@%gA3&=5r;Lp=N@WKW;>O!eGIj#J;&>+3va^~GXRHCY2}*g#9ULab zitCJt-OV0*D_Q3Q`p1_+GbPxRtV_T`jyATjax<;zZ?;S+VD}a(aN7j?4<~>BkHK7bO8_Vqfdq1#W&p~2H z&w-gJB4?;Q&pG9%8P(oOGZ#`!m>qAeE)SeL*t8KL|1oe;#+uOK6w&PqSDhw^9-&Fa zuEzbi!!7|YhlWhqmiUm!muO(F8-F7|r#5lU8d0+=;<`{$mS=AnAo4Zb^{%p}*gZL! zeE!#-zg0FWsSnablw!9$<&K(#z!XOW z;*BVx2_+H#`1b@>RtY@=KqD)63brP+`Cm$L1@ArAddNS1oP8UE$p05R=bvZoYz+^6 z<)!v7pRvi!u_-V?!d}XWQR1~0q(H3{d^4JGa=W#^Z<@TvI6J*lk!A zZ*UIKj*hyO#5akL*Bx6iPKvR3_2-^2mw|Rh-3O_SGN3V9GRo52Q;JnW{iTGqb9W99 z7_+F(Op6>~3P-?Q8LTZ-lwB}xh*@J2Ni5HhUI3`ct|*W#pqb>8i*TXOLn~GlYECIj zhLaa_rBH|1jgi(S%~31Xm{NB!30*mcsF_wgOY2N0XjG_`kFB+uQuJbBm3bIM$qhUyE&$_u$gb zpK_r{99svp3N3p4yHHS=#csK@j9ql*>j0X=+cD2dj<^Wiu@i>c_v zK|ovi7}@4sVB#bzq$n3`EgI?~xDmkCW=2&^tD5RuaSNHf@Y!5C(Is$hd6cuyoK|;d zO}w2AqJPS`Zq+(mc*^%6qe>1d&(n&~()6-ZATASNPsJ|XnxelLkz8r1x@c2XS)R*H(_B=IN>JeQUR;T=i3<^~;$<+8W*eRKWGt7c#>N`@;#!`kZ!P!&{9J1>_g8Zj zXEXxmA=^{8A|3=Au+LfxIWra)4p<}1LYd_$1KI0r3o~s1N(x#QYgvL4#2{z8`=mXy zQD#iJ0itk1d@Iy*DtXw)Wz!H@G2St?QZFz zVPkM%H8Cd2EZS?teQN*Ecnu|PrC!a7F_XX}AzfZl3fXfhBtc2-)zaC2eKx*{XdM~QUo4IwcGgVdW69 z1UrSAqqMALf^2|(I}hgo38l|Ur=-SC*^Bo5ej`hb;C$@3%NFxx5{cxXUMnTyaX{>~ zjL~xm;*`d08bG_K3-E+TI>#oqIN2=An(C6aJ*MrKlxj?-;G zICL$hi>`F%{xd%V{$NhisHSL~R>f!F7AWR&7b~TgLu6!3s#~8|VKIX)KtqTH5aZ8j zY?wY)XH~1_a3&>#j7N}0az+HZ;is;Zw(Am{MX}YhDTe(t{ZZ;TG}2qWYO+hdX}vp9 z@uIRR8g#y~-^E`Qyem(31{H0&V?GLdq9LEOb2(ea#e-$_`5Q{T%E?W(6 z(XbX*Ck%TQM;9V2LL}*Tf`yzai{0@pYMwBu%(I@wTY!;kMrzcfq0w?X`+y@0ah510 zQX5SU(I!*Fag4U6a7Lw%LL;L*PQ}2v2WwYF(lHx_Uz2ceI$mnZ7*eZ?RFO8UvKI0H z9Pq-mB`mEqn6n_W9(s~Jt_D~j!Ln9HA)P;owD-l~9FYszs)oEKShF9Zzcmnb8kZ7% zQ`>}ki1kwUO3j~ zEmh140sOkA9v>j@#56ymn_RnSF`p@9cO1XkQy6_Kog?0ivZDb`QWOX@tjMd@^Qr(p z!sFN=A)QZm!sTh(#q%O{Ovl{IxkF!&+A)w2@50=?a-+VuZt6On1;d4YtUDW{YNDN_ zG@_jZi1IlW8cck{uHg^g=H58lPQ^HwnybWy@@8iw%G! zwB9qVGt_?~M*nFAKd|{cGg+8`+w{j_^;nD>IrPf-S%YjBslSEDxgKH{5p)3LNr!lD z4ii)^%d&cCXIU7UK?^ZQwmD(RCd=?OxmY(Ko#+#CsTLT;p#A%{;t5YpHFWgl+@)N1 zZ5VDyB;+TN+g@u~{UrWrv)&#u~k$S&GeW)G{M#&Di)LdYk?{($Cq zZGMKeYW)aMtjmKgvF0Tg>Mmkf9IB#2tYmH-s%D_9y3{tfFmX1BSMtbe<(yqAyWX60 zzkgSgKb3c{QPG2MalYp`7mIrYg|Y<4Jk?XvJK)?|Ecr+)oNf}XLPuTZK%W>;<|r+% zTNViRI|{sf1v7CsWHvFrkQ$F7+FbqPQ#Bj7XX=#M(a~9^80}~l-DueX#;b}Ajn3VE z{BWI}$q{XcQ3g{(p>IOzFcAMDG0xL)H%wA)<(gl3I-oVhK~u_m=hAr&oeo|4lZbf} z+pe)c34Am<=z@5!2;_lwya;l?xV5&kWe}*5uBvckm(d|7R>&(iJNa6Y05SvlZcWBlE{{%2- z`86)Y5?H!**?{QbzGG~|k2O%eA8q=gxx-3}&Csf6<9BsiXC)T;x4YmbBIkNf;0Nd5 z%whM^!K+9zH>on_<&>Ws?^v-EyNE)}4g$Fk?Z#748e+GFp)QrQQETx@u6(1fk2!(W zWiCF~MomG*y4@Zk;h#2H8S@&@xwBIs|82R*^K(i*0MTE%Rz4rgO&$R zo9Neb;}_ulaCcdn3i17MO3NxzyJ=l;LU*N9ztBJ30j=+?6>N4{9YXg$m=^9@Cl9VY zbo^{yS@gU=)EpQ#;UIQBpf&zfCA;00H-ee=1+TRw@(h%W=)7WYSb5a%$UqNS@oI@= zDrq|+Y9e&SmZrH^iA>Of8(9~Cf-G(P^5Xb%dDgMMIl8gk6zdyh`D3OGNVV4P9X|EvIhplXDld8d z^YWtYUz@tpg*38Xys2?zj$F8%ivA47cGSl;hjD23#*62w3+fwxNE7M7zVK?x_`dBSgPK zWY_~wF~OEZi9|~CSH8}Xi>#8G73!QLCAh58W+KMJJC81{60?&~BM_0t-u|VsPBxn* zW7viEKwBBTsn_A{g@1!wnJ8@&h&d>!qAe+j_$$Vk;OJq`hrjzEE8Wjtm)Z>h=*M25 zOgETOM9-8xuuZ&^@rLObtcz>%iWe%!uGV09nUZ*nxJAY%&KAYGY}U1WChFik7HIw% zZP$3Bx|TG_`~19XV7kfi2GaBEhKap&)Q<9`aPs#^!kMjtPb|+-fX66z3^E)iwyXK7 z8)_p<)O{|i&!qxtgBvWXx8*69WO$5zACl++1qa;)0zlXf`eKWl!0zV&I`8?sG)OD2Vy?reNN<{eK+_ za4M;Hh%&IszR%)&gpgRCP}yheQ+l#AS-GnY81M!kzhWxIR?PW`G3G?} z$d%J28uQIuK@QxzGMKU_;r8P0+oIjM+k)&lZ39i#(ntY)*B$fdJnQ3Hw3Lsi8z&V+ zZly2}(Uzpt2aOubRjttzqrvinBFH4jrN)f0hy)tj4__UTwN)#1fj3-&dC_Vh7}ri* zfJ=oqLMJ-_<#rwVyN}_a-rFBe2>U;;1(7UKH!$L??zTbbzP#bvyg7OQBGQklJ~DgP zd<1?RJ<}8lWwSL)`jM53iG+}y2`_yUvC!JkMpbZyb&50V3sR~u+lok zT0uFRS-yx@8q4fPRZ%KIpLp8R#;2%c&Ra4p(GWRT4)qLaPNxa&?8!LRVdOUZ)2vrh zBSx&kB%#Y4!+>~)<&c>D$O}!$o{<1AB$M7-^`h!eW;c(3J~ztoOgy6Ek8Pwu5Y`Xion zFl9fb!k2`3uHPAbd(D^IZmwR5d8D$495nN2`Ue&`W;M-nlb8T-OVKt|fHk zBpjX$a(IR6*-swdNk@#}G?k6F-~c{AE0EWoZ?H|ZpkBxqU<0NUtvubJtwJ1mHV%9v?GdDw; zAyXZiD}f0Zdt-cl9(P1la+vQ$Er0~v}gYJVwQazv zH#+Z%2CIfOf90fNMGos|{zf&N`c0@x0N`tkFv|_9af3~<0z@mnf*e;%r*Fbuwl-IW z{}B3=(mJ#iwLIPiUP`J3SoP~#)6v;aRXJ)A-pD2?_2_CZ#}SAZ<#v7&Vk6{*i(~|5 z9v^nC`T6o`CN*n%&9+bopj^r|E(|pul;|q6m7Tx+U|UMjWK8o-lBSgc3ZF=rP{|l9 zc&R$4+-UG6i}c==!;I#8aDIbAvgLuB66CQLRoTMu~jdw`fPlKy@AKYWS-xyZzPg&JRAa@m-H43*+ne!8B7)HkQY4 zIh}NL4Q79a-`x;I_^>s$Z4J4-Ngq=XNWQ>yAUCoe&SMAYowP>r_O}S=V+3=3&(O=h zNJDYNs*R3Y{WLmBHc?mFEeA4`0Y`_CN%?8qbDvG2m}kMAiqCv`_BK z_6a@n`$#w6Csr@e2YsMx8udNWtNt=kcqDZdWZ-lGA$?1PA*f4?X*)hjn{sSo8!bHz zb&lGdAgBx@iTNPK#T_wy`KvOIZvTWqSHb=gWUCKXAiB5ckQI`1KkPx{{%1R*F2)Oc z(9p@yG{fRSWE*M9cdbrO^)8vQ2U`H6M>V$gK*rz!&f%@3t*d-r3mSW>D;wYxOhUul zk~~&ip5B$mZ~-F1orsq<|1bc3Zpw6)Ws5;4)HilsN;1tx;N6)tuePw& z==OlmaN*ybM&-V`yt|;vDz(_+UZ0m&&9#{9O|?0I|4j1YCMW;fXm}YT$0%EZ5^YEI z4i9WV*JBmEU{qz5O{#bs`R1wU%W$qKx?bC|e-iS&d*Qm7S=l~bMT{~m3iZl+PIXq{ zn-c~|l)*|NWLM%ysfTV-oR0AJ3O>=uB-vpld{V|cWFhI~sx>ciV9sPkC*3i0Gg_9G!=4ar*-W?D9)?EFL1=;O+W8}WGdp8TT!Fgv z{HKD`W>t(`Cds_qliEzuE!r{ihwEv1l5o~iqlgjAyGBi)$%zNvl~fSlg@M=C{TE;V zQkH`zS8b&!ut(m)%4n2E6MB>p*4(oV>+PT51#I{OXs9j1vo>9I<4CL1kv1aurV*AFZ^w_qfVL*G2rG@D2 zrs87oV3#mf8^E5hd_b$IXfH6vHe&lm@7On~Nkcq~YtE!}ad~?5*?X*>y`o;6Q9lkk zmf%TYonZM`{vJg$`lt@MXsg%*&zZZ0uUSse8o=!=bfr&DV)9Y6$c!2$NHyYAQf*Rs zk{^?gl9E z5Im8wlAsvQ6C2?DyG@95gUXZ3?pPijug25g;#(esF_~3uCj3~94}b*L>N2GSk%Qst z=w|Z>UX$m!ZOd(xV*2xvWjN&c5BVEdVZ0wvmk)I+YxnyK%l~caR=7uNQ=+cnNTLZ@&M!I$Mj-r{!P=; z`C2)D=VmvK8@T5S9JZoRtN!S*D_oqOxyy!q6Zk|~4aT|*iRN)fL)c>-yycR>-is0X zKrko-iZw(f(!}dEa?hef5yl%p0-v-8#8CX8!W#n2KNyT--^3hq6r&`)5Y@>}e^4h- zlPiDT^zt}Ynk&x@F8R&=)k8j$=N{w9qUcIc&)Qo9u4Y(Ae@9tA`3oglxjj6c{^pN( zQH+Uds2=9WKjH#KBIwrQI%bbs`mP=7V>rs$KG4|}>dxl_k!}3ZSKeEen4Iswt96GGw`E6^5Ov)VyyY}@itlj&sao|>Sb5 zeY+#1EK(}iaYI~EaHQkh7Uh>DnzcfIKv8ygx1Dv`8N8a6m+AcTa-f;17RiEed>?RT zk=dAksmFYPMV1vIS(Qc6tUO+`1jRZ}tcDP? zt)=7B?yK2RcAd1+Y!$K5*ds=SD;EEqCMG6+OqPoj{&8Y5IqP(&@zq@=A7+X|JBRi4 zMv!czlMPz)gt-St2VZwDD=w_S>gRpc-g zUd*J3>bXeZ?Psjohe;z7k|d<*T21PA1i)AOi8iMRwTBSCd0ses{)Q`9o&p9rsKeLaiY zluBw{1r_IFKR76YCAfl&_S1*(yFW8HM^T()&p#6y%{(j7Qu56^ZJx1LnN`-RTwimdnuo*M8N1ISl+$C-%=HLG-s} zc99>IXRG#FEWqSV9@GFW$V8!{>=lSO%v@X*pz*7()xb>=yz{E$3VE;e)_Ok@A*~El zV$sYm=}uNlUxV~6e<6LtYli1!^X!Ii$L~j4e{sI$tq_A(OkGquC$+>Rw3NFObV2Z)3Rt~Jr{oYGnZaFZ^g5TDZlg;gaeIP} z!7;T{(9h7mv{s@piF{-35L=Ea%kOp;^j|b5ZC#xvD^^n#vPH=)lopYz1n?Kt;vZmJ z!FP>Gs7=W{sva+aO9S}jh0vBs+|(B6Jf7t4F^jO3su;M13I{2rd8PJjQe1JyBUJ5v zcT%>D?8^Kp-70bP8*rulxlm)SySQhG$Pz*bo@mb5bvpLAEp${?r^2!Wl*6d7+0Hs_ zGPaC~w0E!bf1qFLDM@}zso7i~(``)H)zRgcExT_2#!YOPtBVN5Hf5~Ll3f~rWZ(UsJtM?O*cA1_W0)&qz%{bDoA}{$S&-r;0iIkIjbY~ zaAqH45I&ALpP=9Vof4OapFB`+_PLDd-0hMqCQq08>6G+C;9R~}Ug_nm?hhdkK$xpI zgXl24{4jq(!gPr2bGtq+hyd3%Fg%nofK`psHMs}EFh@}sdWCd!5NMs)eZg`ZlS#O0 zru6b8#NClS(25tXqnl{|Ax@RvzEG!+esNW-VRxba(f`}hGoqci$U(g30i}2w9`&z= zb8XjQLGN!REzGx)mg~RSBaU{KCPvQx8)|TNf|Oi8KWgv{7^tu}pZq|BS&S<53fC2K4Fw6>M^s$R$}LD*sUxdy6Pf5YKDbVet;P!bw5Al-8I1Nr(`SAubX5^D9hk6$agWpF}T#Bdf{b9-F#2WVO*5N zp+5uGgADy7m!hAcFz{-sS0kM7O)qq*rC!>W@St~^OW@R1wr{ajyYZq5H!T?P0e+)a zaQ%IL@X_`hzp~vRH0yUblo`#g`LMC%9}P;TGt+I7qNcBSe&tLGL4zqZqB!Bfl%SUa z6-J_XLrnm*WA`34&mF+&e1sPCP9=deazrM=Pc4Bn(nV;X%HG^4%Afv4CI~&l!Sjzb z{rHZ3od0!Al{}oBO>F*mOFAJrz>gX-vs!7>+_G%BB(ljWh$252j1h;9p~xVA=9_`P z5KoFiz96_QsTK%B&>MSXEYh`|U5PjX1(+4b#1PufXRJ*uZ*KWdth1<0 zsAmgjT%bowLyNDv7bTUGy|g~N34I-?lqxOUtFpTLSV6?o?<7-UFy*`-BEUsrdANh} zBWkDt2SAcGHRiqz)x!iVoB~&t?$yn6b#T=SP6Ou8lW=B>=>@ik93LaBL56ub`>Uo!>0@O8?e)$t(sgy$I z6tk3nS@yFFBC#aFf?!d_3;%>wHR;A3f2SP?Na8~$r5C1N(>-ME@HOpv4B|Ty7%jAv zR}GJwsiJZ5@H+D$^Cwj#0XA_(m^COZl8y7Vv(k=iav1=%QgBOVzeAiw zaDzzdrxzj%sE^c9_uM5D;$A_7)Ln}BvBx^=)fO+${ou%B*u$(IzVr-gH3=zL6La;G zu0Kzy5CLyNGoKRtK=G0-w|tnwI)puPDOakRzG(}R9fl7#<|oQEX;E#yCWVg95 z;NzWbyF&wGg_k+_4x4=z1GUcn6JrdX4nOVGaAQ8#^Ga>aFvajQN{!+9rgO-dHP zIp@%&ebVg}IqnRWwZRTNxLds+gz2@~VU(HI=?Epw>?yiEdZ>MjajqlO>2KDxA>)cj z2|k%dhh%d8SijIo1~20*5YT1eZTDkN2rc^zWr!2`5}f<2f%M_$to*3?Ok>e9$X>AV z2jYmfAd)s|(h?|B(XYrIfl=Wa_lBvk9R1KaP{90-z{xKi+&8=dI$W0+qzX|ZovWGOotP+vvYR(o=jo?k1=oG?%;pSqxcU* zWVGVMw?z__XQ9mnP!hziHC`ChGD{k#SqEn*ph6l46PZVkm>JF^Q{p&0=MKy_6apts z`}%_y+Tl_dSP(;Ja&sih$>qBH;bG;4;75)jUoVqw^}ee=ciV;0#t09AOhB^Py7`NC z-m+ybq1>_OO+V*Z>dhk}QFKA8V?9Mc4WSpzj{6IWfFpF7l^au#r7&^BK2Ac7vCkCn{m0uuN93Ee&rXfl1NBY4NnO9lFUp zY++C1I;_{#OH#TeP2Dp?l4KOF8ub?m6zE@XOB5Aiu$E~QNBM@;r+A5mF2W1-c7>ex zHiB=WJ&|`6wDq*+xv8UNLVUy4uW1OT>ey~Xgj@MMpS@wQbHAh>ysYvdl-1YH@&+Q! z075(Qd4C!V`9Q9jI4 zSt{HJRvZec>vaL_brKhQQwbpQd4_Lmmr0@1GdUeU-QcC{{8o=@nwwf>+dIKFVzPriGNX4VjHCa zTbL9w{Y2V87c2ofX%`(48A+4~mYTiFFl!e{3K^C_k%{&QTsgOd0*95KmWN)P}m zTRr{`f7@=v#+z_&fKYkQT!mJn{*crj%ZJz#(+c?>cD&2Lo~FFAWy&UG*Op^pV`BR^I|g?T>4l5;b|5OQ@t*?_Slp`*~Y3`&RfKD^1uLezIW(cE-Dq2z%I zBi8bWsz0857`6e!ahet}1>`9cYyIa{pe53Kl?8|Qg2RGrx@AlvG3HAL-^9c^1GW;)vQt8IK+ zM>!IW*~682A~MDlyCukldMd;8P|JCZ&oNL(;HZgJ>ie1PlaInK7C@Jg{3kMKYui?e!b`(&?t6PTb5UPrW-6DVU%^@^E`*y-Fd(p|`+JH&MzfEq;kikdse ziFOiDWH(D< zyV7Rxt^D0_N{v?O53N$a2gu%1pxbeK;&ua`ZkgSic~$+zvt~|1Yb=UfKJW2F7wC^evlPf(*El+#}ZBy0d4kbVJsK- z05>;>?HZO(YBF&v5tNv_WcI@O@LKFl*VO?L(!BAd!KbkVzo;v@~3v`-816GG?P zY+H3ujC>5=Am3RIZDdT#0G5A6xe`vGCNq88ZC1aVXafJkUlcYmHE^+Z{*S->ol%-O znm9R0TYTr2w*N8Vs#s-5=^w*{Y}qp5GG)Yt1oLNsH7y~N@>Eghms|K*Sdt_u!&I}$ z+GSdFTpbz%KH+?B%Ncy;C`uW6oWI46(tk>r|5|-K6)?O0d_neghUUOa9BXHP*>vi; z={&jIGMn-92HvInCMJcyXwHTJ42FZp&Wxu+9Rx;1x(EcIQwPUQ@YEQQ`bbMy4q3hP zNFoq~Qd0=|xS-R}k1Im3;8s{BnS!iaHIMLx)aITl)+)?Yt#fov|Eh>}dv@o6R{tG>uHsy&jGmWN5+*wAik|78(b?jtysPHC#e+Bzz~V zS3eEXv7!Qn4uWi!FS3B?afdD*{fr9>B~&tc671fi--V}~E4un;Q|PzZRwk-azprM$4AesvUb5`S`(5x#5VJ~4%ET6&%GR$}muHV-5lTsCi_R|6KM(g2PCD@|yOpKluT zakH!1V7nKN)?6JmC-zJoA#ciFux8!)ajiY%K#RtEg$gm1#oKUKX_Ms^%hvKWi|B=~ zLbl-L)-=`bfhl`>m!^sRR{}cP`Oim-{7}oz4p@>Y(FF5FUEOfMwO!ft6YytF`iZRq zfFr{!&0Efqa{1k|bZ4KLox;&V@ZW$997;+Ld8Yle91he{BfjRhjFTFv&^YuBr^&Pe zswA|Bn$vtifycN8Lxr`D7!Kygd7CuQyWqf}Q_PM}cX~S1$-6xUD%-jrSi24sBTFNz(Fy{QL2AmNbaVggWOhP;UY4D>S zqKr!UggZ9Pl9Nh_H;qI`-WoH{ceXj?m8y==MGY`AOJ7l0Uu z)>M%?dtaz2rjn1SW3k+p`1vs&lwb%msw8R!5nLS;upDSxViY98IIbxnh{}mRfEp=9 zbrPl>HEJeN7J=KnB6?dwEA6YMs~chHNG?pJsEj#&iUubdf3JJwu=C(t?JpE6xMyhA3e}SRhunDC zn-~83*9=mADUsk^sCc%&&G1q5T^HR9$P#2DejaG`Ui*z1hI#h7dwpIXg)C{8s< z%^#@uQRAg-$z&fmnYc$Duw63_Zopx|n{Bv*9Xau{a)2%?H<6D>kYY7_)e>OFT<6TT z0A}MQLgXbC2uf`;67`mhlcUhtXd)Kbc$PMm=|V}h;*_%vCw4L6r>3Vi)lE5`8hkSg zNGmW-BAOO)(W((6*e_tW&I>Nt9B$xynx|sj^ux~?q?J@F$L4;rnm_xy8E*JYwO-02u9_@@W0_2@?B@1J{y~Q39N3NX^t7#`=34Wh)X~sU&uZWgS1Z09%_k|EjA4w_QqPdY`oIdv$dJZ;(!k)#U8L+|y~gCzn+6WmFt#d{OUuKHqh1-uX_p*Af8pFYkYvKPKBxyid4KHc}H` z*KcyY;=@wzXYR{`d{6RYPhapShXIV?0cg_?ahZ7do)Ot#mxgXYJYx}<%E1pX;zqHd zf!c(onm{~#!O$2`VIXezECAHVd|`vyP)Uyt^-075X@NZDBaQt<>trA3nY-Dayki4S zZ^j6CCmx1r46`4G9794j-WC0&R9(G7kskS>=y${j-2;(BuIZTLDmAyWTG~`0)Bxqk zd{NkDe9ug|ms@0A>JVmB-IDuse9h?z9nw!U6tr7t-Lri5H`?TjpV~8(gZWFq4Vru4 z!86bDB;3lpV%{rZ`3gtmcRH1hjj!loI9jN>6stN6A*ujt!~s!2Q+U1(EFQEQb(h4E z6VKuRouEH`G6+8Qv2C)K@^;ldIuMVXdDDu}-!7FS8~k^&+}e9EXgx~)4V4~o6P^52 z)a|`J-fOirL^oK}tqD@pqBZi_;7N43%{IQ{v&G9^Y^1?SesL`;Z(dt!nn9Oj5Odde%opv&t zxJ><~b#m+^KV&b?R#)fRi;eyqAJ_0(nL*61yPkJGt;gZxSHY#t>ATnEl-E%q$E16% zZdQfvhm5B((y4E3Hk6cBdwGdDy?i5CqBlCVHZr-rI$B#>Tbi4}Gcvyg_~2=6O9D-8 zY2|tKrNzbVR$h57R?Pe+gUU_il}ZaWu|Az#QO@};=|(L-RVf0AIW zq#pO+RfM7tdV`9lI6g;{qABNId`fG%U9Va^ravVT^)CklDcx)YJKeJdGpM{W1v8jg z@&N+mR?BPB=K1}kNwXk_pj44sd>&^;d!Z~P>O78emE@Qp@&8PyB^^4^2f7e)gekMv z2aZNvP@;%i{+_~>jK7*2wQc6nseT^n6St9KG#1~Y@$~zR_=AcO2hF5lCoH|M&c{vR zSp(GRVVl=T*m~dIA;HvYm8HOdCkW&&4M~UDd^H)`p__!4k+6b)yG0Zcek8OLw$C^K z3-BbLiG_%qX|ZYpXJ$(c@aa7b4-*IQkDF}=gZSV`*ljP|5mWuHSCcf$5qqhZTv&P?I$z^>}qP(q!Aku2yA5vu38d8x*q{6-1`%PrE_r0-9Qo?a#7Zbz#iGI7K<(@k^|i4QJ1H z4jx?{rZbgV!me2VT72@nBjucoT zUM9;Y%TCoDop?Q5fEQ35bCYk7!;gH*;t9t-QHLXGmUF;|vm365#X)6b2Njsyf1h9JW#x$;@x5Nx2$K$Z-O3txa%;OEbOn6xBzd4n4v)Va=sj5 z%rb#j7{_??Tjb8(Hac<^&s^V{yO-BL*uSUk2;X4xt%NC8SjO-3?;Lzld{gM5A=9AV z)DBu-Z8rRvXXwSVDH|dL-3FODWhfe1C_iF``F05e{dl(MmS|W%k-j)!7(ARkV?6r~ zF=o42y+VapxdZn;GnzZfGu<6oG-gQ7j7Zvgo7Am@jYxC2FpS@I;Jb%EyaJDBQC(q% zKlZ}TVu!>;i3t~OAgl@QYy1X|T~D{HOyaS*Bh}A}S#a9MYS{XV{R-|niEB*W%GPW! zP^NU(L<}>Uab<;)#H)rYbnqt|dOK(-DCnY==%d~y(1*{D{Eo1cqIV8*iMfx&J*%yh zx=+WHjt0q2m*pLx8=--UqfM6ZWjkev>W-*}_*$Y(bikH`#-Gn#!6_ zIA&kxn;XYI;eN9yvqztK-a113A%97in5CL5Z&#VsQ4=fyf&3MeKu70)(x^z_uw*RG zo2Pv&+81u*DjMO6>Mrr7vKE2CONqR6C0(*;@4FBM;jPIiuTuhQ-0&C)JIzo_k>TaS zN_hB;_G=JJJvGGpB?uGgSeKaix~AkNtYky4P7GDTW6{rW{}V9K)Cn^vBYKe*OmP!; zohJs=l-0sv5&phSCi&8JSrokrKP$LVa!LbtlN#T^cedgH@ijt5T-Acxd9{fQY z4qsg1O{|U5Rzh_j;9QD(g*j+*=xULyi-FY|-mUXl7-2O`TYQny<@jSQ%^ye*VW_N< z4mmvhrDYBJ;QSoPvwgi<`7g*Pwg5ANA8i%Kum;<=i|4lwEdN+`)U3f2%bcRZRK!P z70kd~`b0vX=j20UM5rBO#$V~+grM)WRhmzb15ya^Vba{SlSB4Kn}zf#EmEEhGruj| zBn0T2n9G2_GZXnyHcFkUlzdRZEZ0m&bP-MxNr zd;kl7=@l^9TVrg;Y6J(%!p#NV*Lo}xV^Nz0#B*~XRk0K2hgu5;7R9}O=t+R(r_U%j z$`CgPL|7CPH&1cK5vnBo<1$P{WFp8#YUP%W)rS*a_s8kKE@5zdiAh*cjmLiiKVoWD z!y$@Cc5=Wj^VDr$!04FI#%pu6(a9 zM_FAE+?2tp2<$Sqp5VtADB>yY*cRR+{OeZ5g2zW=`>(tA~*-T)X|ahF{xQmypWp%2X{385+=0S|Jyf`XA-c7wAx`#5n2b-s*R>m zP30qtS8aUXa1%8KT8p{=(yEvm2Gvux5z22;isLuY5kN{IIGwYE1Pj);?AS@ex~FEt zQ`Gc|)o-eOyCams!|F0_;YF$nxcMl^+z0sSs@ry01hpsy3p<|xOliR zr-dxK0`DlAydK!br?|Xi(>buASy4@C8)ccRCJ3w;v&tA1WOCaieifLl#(J% zODPi5fr~ASdz$Hln~PVE6xekE{Xb286t(UtYhDWo8JWN6sNyRVkIvC$unIl8QMe@^ z;1c<0RO5~Jv@@gtDGPDOdqnECOurq@l02NC#N98-suyq_)k(`G=O`dJU8I8LcP!4z z8fkgqViqFbR+3IkwLa)^>Z@O{qxTLU63~^lod{@${q;-l?S|4Tq0)As-Gz!D(*P)Vf6wm6B8GGWi7B)Q^~T?sseZeI+}LyBAG!LRZn_ktDlht1j2ok@ljteyuNUkG67 zipkCx-7k(FZQhYjZ%T9X7`tO99$Wj~K`9r0IkWhPul`Q_t1YnVK=YI1dMc_b!FEU4 zkv=PGf{5$P#w{|m92tfVnsnfd%%KW;1a*cLmga4bSYl^*49M4cs+Fe>P!n=$G6hL6 z>IM&0+c(Nvr0I!5CGx7WK*Z3V^w0+QcF=hU0B4=+;=tn*+XDxKa;NB-z4O~I zf}TSb^Z;L_Og>!D1`;w@zf@GCqCUNY%N?IPmEkTco^}bX~BWM_Hamu05>#B zBh%QfUeHPu`MsYVQQ3hOT;HmP_C|nOl zjluk7vaSICyQ01h`^c)DWp>cxPjGEc6D^~2L79hyK_J#<9H#8o`&XM4=aB`@< z<|1oR6Djf))P1l2C{qSwa4u-&LDG{FLz#ym_@I+vo}D}#%;vNN%& zW&9||THv_^B!1Fo+$3A6hEAed$I-{a^6FVvwMtT~e%*&RvY5mj<@(-{y^xn6ZCYqNK|#v^xbWpy15YL18z#Y&5YwOnd!A*@>k^7CaX0~4*6QB{Bgh$KJqesFc(lSQ{iQAKY%Ge}2CeuFJ{4YmgrP(gpcH zXJQjSH^cw`Z0tV^axT&RkOBP2A~#fvmMFrL&mwdDn<*l3;3A425_lzHL`+6sT9LeY zu@TH0u4tj199jQBzz*~Up5)7=4OP%Ok{rxQYNb!hphAoW-BFJn>O=%ov*$ir?dIx% z56Y`>?(1YQ8Fc(D7pq2`9swz@*RIoTAvMT%CPbt;$P%eG(P%*ZMjklLoXqTE*Jg^T zlEQbMi@_E|ll_>pTJ!(-x41R}4sY<5A2VVQ^#4eE{imHt#NEi+#p#EBC2C=9B4A|n zqe03T*czDqQ-VxZ+jPQG!}!M0SlFm^@wTW?otBZ+q~xkk29u1i7Q|kaJ(9{AiP1`p zbEe5&!>V;1wnQ1-Qpyn2B5!S(lh=38hl6IilCC6n4|yz~q94S9_5+Od*$c)%r|)f~ z;^-lf=6POs>Ur4i-F>-wm;3(v7Y_itzt)*M!b~&oK%;re(p^>zS#QZ+Rt$T#Y%q1{ zx+?@~+FjR1MkGr~N`OYBSsVr}lcBZ+ij!0SY{^w((2&U*M`AcfSV9apro+J{>F&tX zT~e zMvsv$Q)AQl_~);g8OOt4plYESr8}9?T!yO(Wb?b~1n0^xVG;gAP}d}#%^9wqN7~F5 z!jWIpqxZ28LyT|UFH!u?V>F6&Hd~H|<(3w*o{Ps>G|4=z`Ws9oX5~)V=uc?Wmg6y< zJKnB4Opz^9v>vAI)ZLf2$pJdm>ZwOzCX@Yw0;-fqB}Ow+u`wglzwznQAP(xbs`fA7 zylmol=ea)g}&;8;)q0h7>xCJA+01w+RY`x`RO% z9g1`ypy?w-lF8e5xJXS4(I^=k1zA46V)=lkCv?k-3hR9q?oZPzwJl$yOHWeMc9wFuE6;SObNsmC4L6;eWPuAcfHoxd59gD7^Xsb$lS_@xI|S-gb? z*;u@#_|4vo*IUEL2Fxci+@yQY6<&t=oNcWTVtfi1Ltveqijf``a!Do0s5e#BEhn5C zBXCHZJY-?lZAEx>nv3k1lE=AN10vz!hpeUY9gy4Xuy940j#Rq^yH`H0W2SgXtn=X1 zV6cY>fVbQhGwQIaEG!O#p)aE8&{gAS z^oVa-0M`bG`0DE;mV)ATVNrt;?j-o*?Tdl=M&+WrW12B{+5Um)qKHd_HIv@xPE+;& zPI|zXfrErYzDD2mOhtrZLAQ zP#f9e!vqBSyoKZ#{n6R1MAW$n8wH~)P3L~CSeBrk4T0dzIp&g9^(_5zY*7$@l%%nL zG$Z}u8pu^Mw}%{_KDBaDjp$NWes|DGAn~WKg{Msbp*uPiH9V|tJ_pLQROQY?T0Pmt zs4^NBZbn7B^L%o#q!-`*+cicZS9Ycu+m)rDb98CJ+m1u}e5ccKwbc0|q)ICBEnLN# zV)8P1s;r@hE3sG2wID0@`M9XIn~hm+W1(scCZr^Vs)w4PKIW_qasyjbOBC`ixG8K$ z9xu^v(xNy4HV{wu2z-B87XG#yWu~B6@|*X#BhR!_jeF*DG@n_RupAvc{DsC3VCHT# za6Z&9k#<*y?O0UoK3MLlSX6wRh`q&E>DOZTG=zRxj0pR0c3vskjPOqkh9;o>a1>!P zxD|LU0qw6S4~iN8EIM2^$k72(=a6-Tk?%1uSj@0;u$0f*LhC%|mC`m`w#%W)IK zN_UvJkmzdP84ZV7CP|@k>j^ zPa%;PDu1TLyNvLQdo!i1XA|49nN}DuTho6=z>Vfduv@}mpM({Jh289V%W@9opFELb z?R}D#CqVew1@W=XY-SoMNul(J)zX(BFP?#@9x<&R!D1X&d|-P;VS5Gmd?Nvu$eRNM zG;u~o*~9&A2k&w}IX}@x>LMHv`ith+t6`uQGZP8JyVimg>d}n$0dDw$Av{?qU=vRq zU@e2worL8vTFtK@%pdbaGdUK*BEe$XE=pYxE_q{(hUR_Gzkn=c#==}ZS^C6fKBIfG z@hc);p+atn`3yrTY^x+<y`F0>p02jUL8cgLa|&yknDj;g73m&Sm&@ju91?uG*w?^d%Yap&d2Bp3v7KlQmh z(N<38o-iRk9*UV?wFirV>|46JqxOZ_o8xv_eJ1dv} zw&zDHZOU%`U{9ckU8DS$lB6J!B`JuThCnwKphODv`3bd?_=~tjNHstM>xoA53-p#F zLCVB^E`@r_D>yHLr10Sm4NRX8FQ+&zw)wt)VsPmLK|vLwB-}}jwEIE!5fLE;(~|DA ztMr8D0w^FPKp{trPYHXI7-;UJf;2+DOpHt%*qRgdWawy1qdsj%#7|aRSfRmaT=a1> zJ8U>fcn-W$l-~R3oikH+W$kRR&a$L!*HdKD_g}2eu*3p)twz`D+NbtVCD|-IQdJlFnZ0%@=!g`nRA(f!)EnC0 zm+420FOSRm?OJ;~8D2w5HD2m8iH|diz%%gCWR|EjYI^n7vRN@vcBrsyQ;zha15{uh zJ^HJ`lo+k&C~bcjhccoiB77-5=SS%s7UC*H!clrU$4QY@aPf<9 z0JGDeI(6S%|K-f@U#%SP`{>6NKP~I#&rSHBTUUvHn#ul4*A@BcRR`#yL%yfZj*$_% zAa$P%`!8xJp+N-Zy|yRT$gj#4->h+eV)-R6l}+)9_3lq*A6)zZ)bnogF9`5o!)ub3 zxCx|7GPCqJlnRVPb&!227Ok@-5N2Y6^j#uF6ihXjTRfbf&ZOP zVc$!`$ns;pPW_=n|8Kw4*2&qx+WMb9!DQ7lC1f@DZyr|zeQcC|B6ma*0}X%BSmFJ6 zeDNWGf=Pmmw5b{1)OZ6^CMK$kw2z*fqN+oup2J8E^)mHj?>nWhBIN|hm#Km4eMyL= zXRqzro9k7(ulJi5J^<`KHJAh-(@W=5x>9+YMFcx$6A5dP-5i6u!k*o-zD z37IkyZqjlNh*%-)rAQrCjJo)u9Hf9Yb1f3-#a=nY&M%a{t0g7w6>{AybZ9IY46i4+%^u zwq}TCN@~S>i7_2T>GdvrCkf&=-OvQV9V3$RR_Gk7$t}63L}Y6d_4l{3b#f9vup-7s z3yKz5)54OVLzH~Ty=HwVC=c$Tl=cvi1L?R>*#ki4t6pgqdB$sx6O(IIvYO8Q>&kq;c3Y-T?b z*6XAc?orv>?V7#vxmD7geKjf%v~%yjbp%^`%e>dw96!JAm4ybAJLo0+4=TB% zShgMl)@@lgdotD?C1Ok^o&hFRYfMbmlbfk677k%%Qy-BG3V9txEjZmK+QY5nlL2D$Wq~04&rwN`-ujpp)wUm5YQc}&tK#zUR zW?HbbHFfSDsT{Xh&RoKiGp)7WPX4 zD^3(}^!TS|hm?YC16YV59v9ir>ypihBLmr?LAY87PIHgRv*SS>FqZwNJKgf6hy8?9 zaGTxa*_r`ZhE|U9S*pn5Mngb7&%!as3%^ifE@zDvX`GP+=oz@p)rAl2KL}ZO1!-us zY`+7ln`|c!2=?tVsO{C}=``aibcdc1N#;c^$BfJr84=5DCy+OT4AB1BUWkDw1R$=FneVh*ajD&(j2IcWH8stMShVcMe zAi6d7p)>hgPJbcb(=NMw$Bo;gQ}3=hCQsi{6{2s~=ZEOizY(j{zYY-W8RiNjycv00 z8(JpE{}=CHx0ib3(nZgo776X=wBUbfk$y2r*}aNG@A0_zOa4k3?1EeH7Z43{@IP>{^M+M`M)0w*@Go z>kg~UfgP1{vH+IU(0p(VRVlLNMHN1C&3cFnp*}4d1a*kwHJL)rjf`Fi5z)#RGTr7E zOhWfTtQyCo&8_N(zIYEugQI}_k|2X(=dMA43Nt*e93&otv`ha-i;ACB$tIK% zRDOtU^1CD5>7?&Vbh<+cz)(CBM}@a)qZ^ld?uYfp3OjiZOCP7u6~H# zMU;=U=1&DQ9Qp|7j4qpN5Dr7sH(p^&Sqy|{uH)lIv3wk?xoVuN`ILg}HUCLs1Bp2^ za8&M?ZQVWFX>Rg4_i$C$U`89i6O(RmWQ4&O=?B6@6`a8fI)Q6q0t{&o%)|n7jN)7V z{S;u+{UzXnUJN}bCE&4u5wBxaFv7De0huAjhy#o~6NH&1X{OA4Y>v0$F-G*gZqFym zhTZ7~nfaMdN8I&2ri;fk*`LhES$vkyq-dBuRF!BC)q%;lt0`Z(*=Sl>uvU`LAvbyt zL1|M@Jas<@1hK!prK}$@&fbf70o7>3&CovCKi815v$6T7R&1GOG~R4pEu2B z%bxG{n`u$7ps(}Tt(P608J@{+>X(?=-j8CkF!T79c`1@E%?vOL%TYrMe1ozi<##IsIC1YRojP!gD%|+7|z^-Vj$a85gbmtB#unyoy%gw9m1yB z|L^-wylT%}=pNpq!QYz9zoV7>zM2g2d9lm{Q zP|dx3=De3NSNGuMWRdO_ctQJUud?_96HbrHiSKmp;{MHZhX#*L+^I11#r;grJ8_21 zt6b*wmCaAw(>A`ftjlL@vi06Z7xF<&xNOrTHrDeMHk*$$+pGK0p+|}H=Kgl{=naBy zclyQsRTraO4!uo})OTSp_x`^0jj7>|H=FOGnAbKT_LuSUiSd3QuCMq>sEhB=V63Nm zZxrtB0)U@x2A#VHqo2ab=pn~tu>kJ;TVASb_&ePAgVcic@>^YM?^LYRLr^O12>~45 z-EE?-Z$xjxsN92EaBi)~D~1OzRVH`o!)kYv7IIx??(B)>R|xa&(wmlU2gdV0+N+3% z7r$w5(L<|?@46ITJZS5koAELgVV_&KHj(9KG??A);@gL`s1th*c#t5>U(*+nb0+H% zOhJG5tth59%*>S~JIi%<0VAi;k>}&(Ojg!fyH0(fza!1kA~a}Vt{|3z{`Pt@VuYyB zFUt(kR$<`X_J&UQ%;ui2zob1!H{PL8X>>wbpGn~@&h__AfBit)4`D^#->1+Qn^MH9 zYD?%)Pa)D-xQzVGm!g)N$^_z`9)(>)gyQ+(7N@k4GO?~43wcE-|77;CPwPXHQcfcJ^I&IOOah zzL|dhoR*#m5sw{b&L=@<-30s9F|{@V05;4Wf6Z_1gpZnJ*SVN}3O7)-=yYuj2)O0d zX=I9TzzTK%QG&ujvS!F*aJ8eqt4|#VE;``yKqCx7#8QC7AmVn+zW9km3L5TN=R>{5 zLcW`6NKkTz`c{`-w!X9zMG;JZP|skLGs7qBHaWj7Ew!VR=`>n30NX)7j~-RbDmQ6b zHr)zVcn^~e2xqFCBG4P$ZCcRDml-&1^5fqN=CHgBVu1yTg32_N>tZ;N%h*TwOf^1lE#w1$yF$kXaP|V$2XuZ+3wH4Ws6%U;^iP|c6`#etHogQ+E@+~PZ1zdGAty6qTmBM z>!)Wfgq~%lD)m>avXMm)ReN}s9!T_>ic6xA|m7$(&n(Z&j} zHC=}~I(^-*PS2pc7%>)6w}F1il&p*0jX1z)jSvG%S{I3d9w$A|5;TS)4w81yzq5f8 zZVfF~`74m1KXQg|`OS>;FCgZw!AL;2PV{&8%~rG!;`eD=g!luE0k40GjIgjD!JSDNf$eW zZtPMF)&EH_#?IwVLEx&Tosh9K8Ln4Pb$`j2=><6MAezsQvhP#YNnw&cL>12xf)dPz z1tk;{SH6HDcbV0x(+5=2n;A->&iYDa5Zr9$&j?2iAz-(l1;#Vc3-ULyqRV9d0*psG7QHE! z*J=*^sKK?iTO$g*+j~C?QzzIu`6Z{2N-ANrd5*?o%x& z&WMin)$Wq%G!?{EH(2}A?Wx@ zn8|q7xPad4Gu>l^&SBl|mhUxp;S+Cb125`h5aBz9pM34$7n-GHGx*=yqAphZKkds7 z$=5Jnt*6&8@y80jNXm|>2IR<$D5frk;c2f5zLS5xe*^W>kkZa5R1+Am34;mo{Gr=Z zD=z8fgTHwx%)7hzjOo9*Cogbru8GgDzrE;3y%TR+u`|zz%c0Tyd8;#EQXdr4Rgx(2LPRzVI2FwsbXwnF;DP^fg zdYOd|zU&AqgCJ;R+?oSgEgZM`ZX>7&$A-j2m|Tcz4ictXoQkz6Tr<2zhOudU16k<7 zLdk&FCL>=a^>0gV@m#9SnMd)R$5&1mh8p2McnUbk;1|C;`7pPkYjf|o>|a6`x`z1O zt>8~Q%zHX%C=D2!;_1eo3qfbB4QQK^{ON_f*7XhLk{6sr2(KIVmax}fUtF-zHZiUd zHPb9jidV`dE;lsw?1uQH!b%MvPE|lh9-8R_z4^PC8{XAf?S73(n*FvYPoMES+LfOx zcjm4ZZOmKY>M2e${QBVT+XnBQ(oC0fAYcXi7+=}_!hS9m>Y%G@zxn3z#Pb;bJ~-kI zAHNmWgQJp$e8L-uKQ|c4B;#0BTsfRB+}pl7xe=2_1U7pahx5S$TVbRnU0oi1?Wh|A zR7ebg9TK1GgKa4@ic#q_*<;c8?CkjX zMMyq`J()_&(j-FZY7q%z6CN^a0%V{UL)jmrvEg{doZd?qIjgJ^UPr(QUs`68;qkdI zzj_XBQ|#K2U!5?fmIEtXX6^rFY;h4=Vx<-C(d;W6Bi_Xsg{ZJPL*K;I?5U$=V-BNP zn9pKiMc=hZNe**GZBw1kVs#-8c2ZRjol}}^V@^}BqY7c0=!mA;v0`d|(d;R-iT|GK z>zt>Tt3oV09%Y;^RM6=p9C-ys_a``HB_D-pnyX(CeA(GiJqx7xxFE52Y`j~iMv;sP z%jPmx#8p%5`flAU(b!c9XBvV+fygn`BP-C#lyRa;9%>YyW6~A_g?@2J+oY0HAg{qO znT4%ViCgw&eE=W8yt-0{cw`tMieWOG3wyNX#3a^qPhE8TH1?QhwhR~}Ic zZ^q$TF8$p0b0=L8aw&qaTjuAYPmr-6x;U*k*vRnOaBwb_( z5+ls5b(E!(71*l)M&(7ZEgBCtB{6Kh#ArV4u0iNnK!ml!nK5=3;9e76yD9oU4xTAK zPGsGkjtFMMY3pRP5u07;#af?b0C7u) zD^=9X@DRasHaf#c>4rF5GAT!Ggj0!7!z?Q-1_X6ZP2g|+?nVutp|rp}eFlKc8}Q&_ z17$NpDQvQolMWZfj0W0|WKm`nd_KXYH_#wRRzs1aRBYqo#feM}a?joONn30Z4Z9PG zg1c!_<52-9D53Wq4z8pUzGkEFm1@Ws(kp4}CO7csZ-7+b)^)M)(xo}_IpTLl7}5BmbBCI{4>rw>4c_gBQHtRd5Z=SW&6Qp2qMOjr3W+ZRmP;S(U+h=^BHKohhRp6Zgf zwt&$zQXhMm@kh1@SB%dIE*kFDZym3Mky$NRljX?}&JGK`PIV1C;Pf!JV{hb4y;Ju- zlpfEPUd+mV5XQH<#BRFhZ}>b#IdF?a?x;rBg-v)@fZpA?+J{3WZjbl3E zv(a&1=pGYPxP@K!6Qg5Vx=-jwc=BA{xL3+QWb&9~DGS1EFkIC+>55{dvY4LV@s5$C zKJmCjigp7?m27*GN_GROz}y+y5%iIj=*JTYccaFjvD&VN%ewfSp=0P zspdFfDqj?gs!N64cEy5uR~wD>af!1PE*xo{^a^8BPIL2=U>B!m2AM0Jf<8qWLoHxi zxQfkbbwkRXgJgLW_j{ZkCxHLBU{@D6T5u90UNs5P769Zei|C$@nA5$L$4ZvxQl1i? z8vLHg17}e{zM$=&h%8Swbfz7yw~X^N|7Chp1bC(oV72l#R8&%Ne5>F=7wR(dB; zkDX!%&fxS19JBjP<6H7+!dO`nPLvB~xn{aDh#^iHKP|A5UQlCG%v%x9@q1w2fa#&% za^UwHu!~(qrv99G%9_e4OBbJ-CkB*1M_?t6UXZ#}4JFDzB|x(1Z}ckuiY}${zj`eVo})!rN8Je z%h2CVJG1$K$2deXx^h8trLs~Han^e>_-M6@0o4C7d548|#mKtm@DvdVAX5ZzA8=*! zKq5C+cM9u)qJ%YBJ1UAcG}6Ji4=$piaZ(K@>1BiD;$R9bR*QP`dH2T=)dgW#f7U)S zZ~i#VYLOnUZt^~Iu3x8QPJaHVUxtRyipQ+tbmWKl14iW1!f6JSDvT$xt8>~7-1ZlJ zU|)Ab*lhvz-JO!$a}RBH9u8$=R)*qeD@iS@(px~OVvML-qqO5&Ujnhw1>G~**Ld{W zE+7h|!{rDZ#;ipZx4^Tcr9vnO)0>WFPzpFu*MYST(`GFzCq*@Gqse6VwDH#x?-{rs z+=dqd$W0*AuAEhzM@GC&!oZa1*lRsx>>mP>DNYigdm^A~xzo}=uV$w#iadO+!&q_~ zT>AsHXOEGsNyfcJt2V$rhGxaIcTEvZr7CMVEu=>l30N~52^71U^<_uw6h@v@`BA2! z)ViU+wF#^$=5o44TpOj?#eyq*+A&c0ghrt8%}SiK)FgLk-;-^+ zXt|1}1vcKAAuR|?L*a8;04p%!M~U2~UC-OJK)DMtBQ#+ZttJgDFNA4zchA*T)cN(E zmpIMLU*c*NrCSV^qdLXD751DsO`#V#K1BVX4qI-B3Rg(zcvlg^mgY^V3Q*5RRQ4-8 z_kAlUisma2SNEx47euK5Y#eu_-gwRW0}M90hEI}eIJ9aU?t11^jSCn4>e~XLSF7Y3 z7JF)1ZbS_P<$<#y(*u@w!jF4FW_f~bxzi%cgP~B1K5N6GFYSAf=D_s5XomU0G9I%Y zPWc{&MItPR#^Le)?zsRkQMmHx^Cnn&;TrPzRVG`wyNH*U;|r3^2NY(z0lwikP}cWF z`p%R@?dy*7H~0&3ST>L9)b7#kwg+|n0#E&-FNf+Z_t7tpa711FogBPV`S3MW_FMGQ zJ@8Z}qXR4-l%p76mvcH`{Fu(^O;8H2@#LZUH#9p6!EX$AEYV$c`s zkPimL3kv>y=WQ+?KIAuim``%cAeBhA6g8}p_*FBH(#{vKi)CIz_D)DFXPql*ccC}O zRW;+Y6V@=&*d6QJUbRxPX+-_24tc-hYHEFaP-IAj*|-P5%xbWujQvu#TF>xigr_r! znuu7b(!PyYX=O#>;+0cGRx>Sy39(3y=TCf_BZ$<%m#inup$>o(3dA1Byfsip8S975-iVe7UklFm|$4&kaJ!n66_k-7-k}Z_?){LQe&wTeJ^CR{u6p+U#4_iSZZ1wjB-1gVGNQqnkk*-wFLj(eK8Ut{waU zb1jwb2I?Wg&98jSQWom8c?2>BWt*!3WQ?>fB$KguB9_sStno%x=JXPEFrT|hh~Po2 zSPzu3IL10O?9U(3{X8OLN-!l6DJVtgr$yYXeAPh~%(FECDe;$mIY7R4Miv1GEFk9x zpw`}E5M)qTr60D^;a#OCd0xP*w8y+my1^l8Qd*V`wLoj)GFFj;;esW2PMO=sbas{yX6asXIJ$|LW< zts$A+JaxoM({kv+2d@#bhl?#V#FZn_=8tTTvup?Vq!p!46W{be)EP=VlYE|UzAU}) zz})UzJVWi;9br0k&5>}sqwa_`TP*c}^$9+q)Dks#qEVg>p)71sqKF-YLP@UF{(>lp7;CHAWK;K0TZ_+?>EtZKprfU@;52a1IU8HNx-mnoZrb8| zP8FPb#T$0VE+G-l508;d{DSfC6#dbp(j|^i^I3z9?Qmkr+(dw^w??h}WTN{_ls-GuE~lF;1Urgbtq|Ud_r>wecb@?{{z? zX>X$&Ud+(I(5}5d^>&Z2m+qy=h#vR*lS084ATwUWZLg6PX1Ft+YI`0iI)ynij}{4X zrQE!Mr1m^-?kw<|VT0mG+5J{!;j;zJT`?_=P*09n+=e``CN|7rC$u~Ksg7LSMS(Q~ z51!n1htcK0q7*K-*u0?c8ZlvPXcNwXmFe0Or2}}R@?j@{ECCNZ6va1tZ>|ZOgGZ1j z9?mRkeSK%{X4O>J$@hyFsD)7s67Uldb>O93wQQiV%-FfbEY_@q>1VUstIJs|QgB`o1z**F#s z^joAYN~5{EQ_wZ~R6-nEV#HsQbNU59dT;G zovb$}pb=LdR^{W2Nh~8yWfq*vC_DvJxM=)2N`5x+N6Sl`3{Wl@$*BYol#0^idTuM` zJ=prt$REkxn6%dimg%99{(Dt6D67sTUR6l1F@9&Z9<)XgWK#x zVohUH6>_xRuw1^V**+BCZ@dZj97T*67OBO>6UUivH`<@ray~ym^E?bO=vKqFfK3Kv z`RKxs4raHacB<(XAeH`@0G*K2@ill_U@m=icT@F{k1PU3j4VBde`ThtW8%Z~A>)45ARjQCDXbH}_rS^IxHGp#utBEj3W3KSAU+$6I4s~9OWueETo!J-f~+DV8< z+VMtdcQ?M+?S}kl&uImYiIUJ-K0-te7W4sdWpS6Fqs-I!Tj{8Qp6lMn$Zm8uU)s{X z8|O}HN%8sEl4em&qv{VBq{}$@cCG{B z5~3DY$WRYSkO~z=sxRct5^G5bPZW;LF)(zY)HREgpRrkYV@H3^BTD6u+bJE~$cqr< zw@Gb3^|n*kHZ%Vnu6~B7pB4iM0C4kDuk8Q1R^<(x%>|sCOl%CTe^N)K?Tiepg?|#m z94!og0*38u|67h%*!)SJhUdvFimsktaqp#im9IpH-$fQc79gi259qPkEZ)XU?2uWW zRg?$8`vl;V%-Tk+rwpTGaxy)h%3AmF^78<#i+Q6~M4#>J4`NNEEzy~xZ&O*9q%}@7 zs9XBO#vSKSM<-OjPIDzO9JiAYFWrK14Am{uZT=S3zaCu~K%kZo&u*=k9L#xi6vyaG zQFD76MOE&=c1G;7Zivp<%%fRq+@3wgZg>k@AYQf|*Qyzy$tqc20m?F5nGbG@V#gW` z8RMb2oBxgiqa?)_G6&-;L#(HCoaJrs_ED{IUZ^$~)+e#0iZT!AJDb2V{Sen*70TO& zyI`*~#ZdLFhYP_#DTuoqQ0OS6j0o15r{}O&YoT5wCp|x_dD{#Y;Y}0P1ta?2VEh4* ztrRN5tL6UvoH@M9L z=%FKpf@iSp2P>C(*o<-Ng4qF#A?i!AxjXLG8%Gm`$rZxw;ZqSvv5@@sZ|N*~do5fb zKWR)T_>`kxaS|MHFh`-`fc`C%=i@EFk$O&)*_OVrgP4MWsZkE2RJB(WC>w}him zb3KV>1I&nHP9};o8Kw-K$wF8`(R?UMzNB22kSIn#dEe|V-CuMw8I7|#`qSB6dpYg$ zoaDHj%zV6*;`u`VVdsTBKv&g75Q`68rdQU6O>_wkMT9d!z@)q2E)R3(j$*C4jp$Fo z2pE>*ih{4Xzh}W+5!Qw)#M*^E(0X-6-!%wj@4*^)8F=N*0Y5Or+>d= zhMNs@R~>R9;KmyP@I@bpU3&w?)jj0rGrb@q)P>wLVbz1!TZY$#+H-mK6B^0{vdvt0 zaJ0~7p%I#1PpPm1DvBzh7*UsCl^I5^`@XzPzbg+v3T_WyKN?TJ9J=57v^IUO`aQN} z@>Y>WIj+gT@-sobU-tW%L5GP(qY?Eep&I;@osY}O*3i1Ar?Sv|EI6S-pK_!~*A$K| zs-hHESqd`vv;zIzgv2ho5-hsIL5Ke~siJ(v0`Qm7W_Rms2rB67=p&HGRhA-)$p-BS zvXSmgGIGgeJMBcsgp=L8U3Ep$VPBFhvJ!3M5{pocGBS~iZj0({9Jt9nbC{Z$LVb%= zGqzRBjlqkAU{#sOX56})^QjX;jQ26M`poAFIZ#H31td9sQlgBBrfIYgDC9+kO~}s{ zb1i*{#{5tPWhv4pecAZygXG>?5xKx7iPXd?nR;QaIfhlhqNBaLDy>9Yd1Sf3P!s4~ zhfHaFGsIFy&ZM=6^qc>>V>o!zk%5Lk5BtS7oU=YfjWUN;c zrh$6Cyr%KC@QNTzTZvb)QXQkV)01MEY+EzC%CJx)Q&6MM={paB}Dp=qCn^eJ}5LeXG9Gqynt0ir>DvSIZ=i?*_xR3=% zppf1w51ypF2KL6ug zCm}eCi>&>xT;Idzh^PmtDWrU(&eC2hAt(nmd#?;W)*&4lb2Z2Ykv*XLNDEm`_1n3C z`l!wZwiF9b?mN@z?s~>v%hT01C{E3md6M5_Xi3fKD6s26Tt~Z>8|~Ao9ds!cF_Y1| zRG>!=TD0k0`|T*)oX!SlSt8g4Uh@nc(QosCoen@i*ZCSyh|IliliuhEw$8?4ZL9N2 zMQ%%S=3Tj_QilhHW@cSr1UYTtDem{A-ZxyCa$K9A%(!`X_?ieJzXbfERST|JxqmbL zHe!hSqYk|!=!$8CJ5>q}Pj63@Q#PO{gpVb+0-qHFM`j5x_s#~dxvy5u62vywq8upP z_)N)3n9cn7YEf2D8L}x0#_B_~>HT8;;8JC5q+}1gEyd%XqYvY?deQzwD1Lx{ghI3; zv?f;&6CY$H&dDL$k#)hb)5lIqUZ~oU!z)hMI!B9THhw?9!}ykqpFJ|hB?JjV9uwqb z3_70pMV^C7I<3Cg&yMi8JJ3V2gYTOMV=IopfZ#1o>&+j-mB-V${Ok(f?I3{+vR~zE_RR$?9xI~^% z53~ z&bCl+6UeKkUWJ-%mnK{9K>?(3BM3C`@xi}v8)q#;YJhMr5dWvMtAL7X``!bHv~(%m zH8d#Q4N6G~lEW}aGn9ZZNT?v9bV$emf)dg#ASDV?(nu+wpu!_X;(vL<<1zBo-~X&N z>keyizVGaP&c65DbIyEwFn2%(L`P424ZI3nFBA%w{yJ?E} zlwSKF;jIhs(!TFOdMUW|(=qHjr#U-k>`>1u1_yL5Gyy;7@WTOt_)nfIp{D9kwR8f0 z;^Fq=iF(&yd|z30&+I`FBM-P6ouHQ@96TkIe@9=pDDL#_zgXos)-ri5lX-&2D~DsI z4R>xVM$c&aFLgFjwq{1I;jpODOx|n*#@e2+Wgdkm(E(Fad_)peD`1^CJ2TpglmgoC)F(Z)F7y2rzzDU^4wvO{bzw{mzSs4tF;*qabKkC?D!j!tbF z4D_6zbqFVI>n@2-Qmg1BiDdD}>E(72)aMv1Y9duOxwlG|E!L(QmQ#j5vmN@a7v{zIt3qQSP?96^$ITE=h~sLn|N|v8YqmA~-0HWgcPHZ@!3Dzm2X{Bozc{qm>J`Ehp}`FQ%Ecbw%+|H8f`pykvo-%&0a z?&ZtJF*{#AYs8Z|z(IFI8sBiZs)L!C9#1W@;hEInZZZdPz2ZnmhoSP9VHQt7mzZUZ zhM!!5IJbe4Z@zEoMjKaxH&Px8p}1<0YmtWwcG@ZPY@*oQSteU zRy+W=Rs>sJ##v^8EJJt0=5---o<@^?fOEp=N<~xXvcf?$gXD0zVHziRMMmC#Mp3o ze(eT!dvjmXp9_C%pV_>{H=nsqYO)n1J?Ihi zjy7f00`|S<;)I!ZyUO{~#+wXX)z(BWsN|$7n9s}H%ZzE8YQv#vRTHjq@D%tYyfe=3)|7jYxRT#E16nFk&1jFC6CH5d4kiJCVq+%r_$Rec7=G!GuZ-0*$5N2GqXB(dqWPS1Um4{xgi2k=;eO_LDy&GR=Q!)bjKY{f!0yoc0Rol&!E`2BkI$5y4U^*k0=GyL-m8XJL%8prM%;fwyX9M^ zs48n3Oh#a>FVWI7dsm~*l0$^J)lxnfTTw~1ceZ73yNvNurwd`;+^1XuucaFN85M8? z$fNl!D9g*O>6IE^POaoDq`86Sw0t4%jIi`&*EEZI?wwOiEvH8(qpfyDvAe`4pWf7k z3-pFgeT{qtj)B!1ZamZ5g3z6Nd40P(%^Kf@#!uzbIk~8w`9wbhWc~1E|sw6-FsOqrhb2DLDwlaq@)Y zAi$KoA=Vyn=Yxqxtf7wu*$47Ht>WZi{AdeN79#9ws~CtE;~gC$q7T>*5yKK3VT)Q=sllRR}lBIGd17+bOu| zeUeUrMgF=Gjk-{epAyUd_KNgwZK_Pz=H$+{4~E_ZRa3IJpU~IZ5U4Z3l%u3{Ls~`H z(iysmm+!HBJTC-$EpHM9yrXUM^_FZ(3sdmsyZ6=lU8bb3V(WK>P0$l~#QA&NMj@OA z*OQ>^-s_D-bda022~!G!bTh7@FR>t!1r`Js1;4$(^_*hH-_pUPf5C}K-v$%i#KBB! zU{~a7)R>ix z#LA|<6v#rwKkB1JBLWkWu#M0#8i1J0e4dFDP3jrlFfxhkDs%Q~)e6e7fR$U?e$<{x zfZb0?UMsB|E}Fk)@|^{)_^L7O%rp1GRNig@bUX(^6}6HoGi8IXoSKpI1A(GV)uA=7 zOXG&KjZYVjYn6}2YV0yfnKsnpDlF)h$Gv--|6$BsWFg|IWnp|#sk}zOAb6Bb?vb@t zs^7=4IdiKE_rUT@rG!D4Zy zcnas#XT77V&%igMXY(lQS|)lgO{pN9!P-94KeZH_+PK5jESYCSPMN)=D(JIAVeB%D zI_>_lvD;pylkZ#Ral0IzC6ei$J$4NnGw(pnVd`&aaNT5mfq-4)aPjj(v;`VvJ6Xxjm@3DX+Kju z@9-h++s7x>idTEL zd)ptYy?P2$S*_DI;eMR0ZdAuS)~fGEZEguO&+3AwW@Sw$&KvgJr6aGK*Ar;0wx`lr z7V&!+9C7`VcV^t+Wj~AweOGQL!)0)serr$8Fez7kC(VSVRdjqpQuq964RW^2euIre zh10&Tv)|dj*CoRozrW<4y_+5}3EGRok+G7ODl3-CF1r?JYDdw&NbcVT=7ljq_K+8bMeG3uRw@3=cof?j+v+WaKI`WqwByf#7aFK3 z0+R34xQ-6nxQ&9xJKl}`C9FlUe1-h^i?5fr5kjot#MA-$%k106t>*gM+yF3m2X#=1tt07`cK)37dA^A4d8%6R>@0U-UZ~wSvzMlK$tlm~aK`%e8|quXyH`aLM0#Dcu%sqEsKV%i zVn_*W-Qbnl)h?RP>)$rZ5JL!*H;Z{ zk7(FB`lo~h&zB|S6j-Na;y$QM*rn^tkO{>#DWZN@IwJps3*Nm&ox0{{;=J~hvPb-* zvAOEPImrdq()yl~`j`Q;R1Y%CdLKKw*;gtNaM~WDO95YXsTjKCOdRD2Is@aVRTYFD zpS=_EB!@Ub&c*JmNMF=F+)Bq)52|=83IEG;M5(Ol*97!W(S-5X-5w&7->`1Pw-0Ml zpA>jaofnyPQTCzoIG}OK9j^nn>F>jC#$iSnJY8y6ue4nxs@3HtfNx01XVK7NcX#Cu z34g-z=0!7ip&@wI>>6ynJYyFTEgH6DA?b>~V%2s_@NPDza5&6cno!S(|85*74}6_M z%s1c4`B{lqMu``(4~Jk#_`^=tu36TgXPv_}{lhhyi(rrSM_uoVVNuZOuxCXom9|wg zNf&BtzX=hVi*4dG&1J!^QW;O%fQ$jVH=W74B8WR)*tM1{(@cHRqiS_W6R^h8uxd@zV>KNI zR(-LNNkLqh>e=CmL|q9sRHm#15%q$o7_GQMp8FLX-HGnJ<+(;k{Q%+Sk+!^mM+2#1y9+gG2IDZGt%;Cfk{+ zT5}^x=!i2$tnH_se6eC zkn;kK>%ICpo=X&=cSsbxQ|AjJ;5Ff;AyIj>$YA8cw*?W^Nn}S|1jrbf@Bd zr82I8KlOh4#5C0sw3oVvuC0NFPKH4S0$~F$U4JM1Im$B%%oGm_5$Lnr{#Pv}eL1k& zMP(pG$MI^8&!nYffq#$zJ^3GF|cC%2d4V@qKV#fu6u2O

k)oKu82Fu=RODzQrHPEC+Mz{hW(G7VuCl8g1ou-Ot!41bp_>OC1&@A_6e*hc)1X zMuDvzEZyB*fW1^+7dL0%ofr;-xT6B@0~|VazatI{60!X=po^uOr6UB$1POKmuI_&b zOL&O+w*!>`k+y%?Z|wm4$@_1|WC|pKM(F{k8TR$-4hs?i|GBc9)qa{vYq)~5qa(2N zsR?s}0Pp^ufVGEB8oE9VCFa0K$x0HSpem!tIyR69y0rnjg8cqjmWyz7*Kx3~X> z|BZX}Y;oVB1HX@l9_-y7dI*WgruY@?rC&64`}3W`ECA>O@Y#Q@JS<4WBF(QbwJqHM zt)fE#6jTSyZ^E8y0INaIf!omWjvS=@15`O%V2CKg+}z=M9##kLKRN0uJuK250bXVU zwzT&n@30^dzKnlL^us;wClg?CKWEtiEb#zhPVx{PxFQiwEPp^C53zN21EdZAz?3D& zC6fK|_!S5Mq&0z;xWGLEv}!zjfpRg_orp7|fXMx=uP!@X`yT@5(N_Hza}p5fBk&|)J7fZ`NQ9Nz@5xT? zi?iV$q+bG!2LZUpF)>Yl!u;DEHV3!i{ipcJm_8Gj@Dac%N3|SQVGqRhrJ;WOR|CtrwzPTW^&$A6!A$E)h7xohm>hA8p{PUZ~ z_&zeg@OL3PxPtzkfsNZAqXCZ8Is7yQ+plm~8;}|~DEkv&f@?q5hB*OGQYXuwVQOp0 z?QQ`6qyp|-$47wjuV74IE_x2I17$+grwMBE^25d<5!lYhnszuh|5Yk;RB+Uk*hk=m zu73=E^7ul{40{A^?Rg^fq0ZfZO@C1HupR*_d;J>lkFv6&x&}4N;t}1T@2}~AC^<3b zA}RxFPPZe5R{_6dIN9N-GT29Oa}RzA2ekKuEVZbuMOB?Xf**`N5&m}?)TjigdY(rF z?~+a=`0);TlDa1j)1G`AfW? zRl883QPq=w zbB|bHEx%_u*$t@Yl#Vc;y*?2W^|^NJ)DmioQFr~1&>MSBL_b(YIpGWdDm3bT=Mgm1 e+h0K+-~H6qzyuy}`;+tYAZFmzUSVSYum1yJqxCBQ diff --git a/fabric/1.20/gradle/wrapper/gradle-wrapper.properties b/fabric/1.20/gradle/wrapper/gradle-wrapper.properties index 37aef8d3..9355b415 100644 --- a/fabric/1.20/gradle/wrapper/gradle-wrapper.properties +++ b/fabric/1.20/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/fabric/1.20/gradlew b/fabric/1.20/gradlew index aeb74cbb..f5feea6d 100644 --- a/fabric/1.20/gradlew +++ b/fabric/1.20/gradlew @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # @@ -55,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -83,7 +85,9 @@ done # This is normally unused # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -130,10 +134,13 @@ location of your Java installation." fi else JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. @@ -141,7 +148,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -149,7 +156,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -198,11 +205,11 @@ fi # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ diff --git a/fabric/1.20/gradlew.bat b/fabric/1.20/gradlew.bat index 93e3f59f..9d21a218 100644 --- a/fabric/1.20/gradlew.bat +++ b/fabric/1.20/gradlew.bat @@ -13,6 +13,8 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## @@ -43,11 +45,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -57,11 +59,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail diff --git a/fabric/1.21/gradle/wrapper/gradle-wrapper.jar b/fabric/1.21/gradle/wrapper/gradle-wrapper.jar index e6441136f3d4ba8a0da8d277868979cfbc8ad796..a4b76b9530d66f5e68d973ea569d8e19de379189 100644 GIT binary patch delta 12612 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 HJ4oML2Lo<@i8BwbL^1~GkG`E7C$SEa_ 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 diff --git a/fabric/1.21/gradle/wrapper/gradle-wrapper.properties b/fabric/1.21/gradle/wrapper/gradle-wrapper.properties index a4413138..9355b415 100644 --- a/fabric/1.21/gradle/wrapper/gradle-wrapper.properties +++ b/fabric/1.21/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/fabric/1.21/gradlew b/fabric/1.21/gradlew index b740cf13..f5feea6d 100644 --- a/fabric/1.21/gradlew +++ b/fabric/1.21/gradlew @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # @@ -84,7 +86,8 @@ done # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum diff --git a/fabric/1.21/gradlew.bat b/fabric/1.21/gradlew.bat index 25da30db..9d21a218 100644 --- a/fabric/1.21/gradlew.bat +++ b/fabric/1.21/gradlew.bat @@ -13,6 +13,8 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## diff --git a/forge/1.12/gradle/wrapper/gradle-wrapper.jar b/forge/1.12/gradle/wrapper/gradle-wrapper.jar index 249e5832f090a2944b7473328c07c9755baa3196..afba109285af78dbd2a1d187e33ac4f87c76e392 100644 GIT binary patch delta 36621 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%0A;APSd3WM%p;X}YQ z_l^I}#dN^i^EY{*M9rzRiDU#5HXb)Z8b{}B2E)#MG`cF4@`I><s*TzV;S1HvrWxlyO7oO14DFcLQgh*so92D&+67+aAtniim2ga9rPhDQ zk{QUeGX$XlQb=R}32^3-jQKdXDM+133PbX}J2D_#)W^8m9ZJF7tAc&Ab{ugStrHOnwtx3Fg8i1c|lre!Dq#SVt=9oBWO3ZoP`HZ?ns)JfQp_u z_q22vtfGHIL#?2!v&dv|evtlGrfU#J2_XOD6$k+W!uEd`4@P3>00XB*V~hYrS`2tM zKcK?N7>Y|sqsmV1fHm2|aHzc;OV|1iJV%Y3kKJES$)9BIzt#s~!u`Y+0!~v@_!QE~ z&wh`*b3U^^Tf2aOZ!qV;v{;TRF18BGyJ1O0CB{qb3UoGR!83_^n9ARWp~jxUg>u?g zzZV6&ab66bL>~QT0V$mWzh0?DefaVyW=^N!VLQwUMYW#DP+i!53}v-E{7}Q0`s_Wx zIb9`X5&YM1U-On=N6knhI>l7Avgw@A;mqzzZ(K`?isKWpr3ZC;e3^t`$FNX*C{WTu^$ASE{eH?gvpn`p%of@2g2}xHv<0W7wj2nc~r>oI>8zMLat{$ z1^5|(XXTa#rFA_^E~2Yl&$#!KYZ5X7hCWYGk2~kJEJ~>X_818co+TqE3)B#ueIt5s ze;t-bxL?2#K;lr^dYKoX|8+DDG&>(Rw}j30@&p}ZOQYYMl4ew#vJF-yyBa}ZhoQ80 z=<|1oC3%^S5(%urWvUDGaHt&+AANU->IC+sewp(y<0gButt>@FRA)W~nL3Pl9WS}j zGHOcg_oCMCMeopBU=7+K@gdiiLdok4m!^C+eOu!I*>g}hb`t>fe^J>={R!In4;4FT z5D?-2i%PSE7HloP5j?l!_9=EVx@097T+w^)wGkQ!$Qf-ii5_OMGAC-X@DUUsSI5U# zeWl~ae`0!jVg^!_q@QMLoNOb626Ye*i&GX14`PT+F)7=8oCV#IN_4v-*rRe}wKmv; zwzjOz7Lqei<=pN<)vmftsJ2(rXzRsKPOH`dQ|F!kKjYCdDLV4Y?3(u_=f>|u4{*Zo zWhnIhXad51TuIP!sC0g3_4Epej{EIburEgF=vQ!9|0;cQyUX!uFeL1HM|vnT7*-rDb}4) zmyM(<33E8a9wA}LTX~xS@snxcc%MLZw zbp~xN7Ee_gQ%ry=^w+fitUscP(->$mOqJ%9ZOukDlydd`j$l+&z4Z|T86xt<3OjJZ zl8H*>ws7#fSsG6LG+zF>07S^aT1>8xjw$km)u>hL0$y`Xj<8@%*qt=!p)$tHZO9{D zHWWCCwpFP1%o$iW*c1yXokQI3gXxM&I=-UStwm#oc^m+njrd%*F%OOr$v6{(sXH)D zJWGL6*sJPdd)r!4i&j+R`(9d&q=gR!vFc^Gfc`HQ#mPiIX`O>T+{LxB;J`-M1=P9T za(+l_4R0(m?-AEik18QF7nuJ>8x=b)A3kI={8EMODKq8kd>cDM5PBMB4rfJ@8uT!4 zhxfEIyBQ!muF?cWJSnjZ;hdxw0=AB80aqVi<}#O1nLv`ia**cql({=ZDhFe^HY~D+ zo>;#}eq_`fN?c2djV6cT8s&g4Fd|V$jbE)_w`#&7_*l$Ph=N-2Tn<%KoGj3EWxqEx zQu!e4`<#J4V5WI8p=H`PCR?Yn$7A`g;HN?*}hRffnY)o z-O-1o>}bZ3yXy~HI<#o+_Oe6xp~_S5v?Dwlsaq9ijiv z(h#5oH;bD3$ey6Z3lSNcA zvyzK;odts8GqzbSdorE}&Its4;LOr%rU7(LYZ9{vid6IYOVu(fp|i54we8PqaM>Z2 z;Gm^~$cPqnwk#iOb80p7cvDirC!;8$d85L-h|)L8I}C}>Vz?T)RR0KAf|R?CjP=*9 zTkKJ7+wV9XdB`}7IOOVO}PH@rE74bU%yG)s~s4lRdCtQM8YDH}}qNmsM zI{QSV40o3)C)FBH4cDjC!gr0er*_9+iov9$`InB3e-GKAiE3aqjckbr+oCFZCZ{+eXZ zeT4PaMA~IuPWs<}1+iW-BhDkPk*dC3sNp8k_9;S!8Ukb0kx@6?00T@;g?A0-QIx5o z-iuJStK4&!bW)?_u4GxN2KH@7E^4rN9bWN&U(BrGmuZ5yRq9g3K}=!O2$2BQz96Fm z2eIqKYzUU43)lLBm8y9$RzUa6;{(i{l*uIo=n8cRU6d(@j*ZY-;t z95pgMC)&FGq9!YVyP=^lRXBJCSh}(hqoIcA5V@CkrEP*;Sr)c9H z6yD8nr>M|F(BF(G=hpC{m5LneM^3iI5m^k-3zXYawp@zLKhw(%L-NV~;g?#$G0ggX zw^dJsTAC5#FXtYWh8v@ZBNE{Pq)LkwA(D*I9}*#Gh`&|x*=eGacQzuDbY{7K4@}Pi zkn!NQ^N;NMYYGdW1LFbUViIxR`7jWr`6px?DQ1)p526zjXN0QEeaJX9Qwhf}Cb*ci zQ;y~5+#%CoOZ%CWwrFbadx_SEu)~)fHn>m9Mcwpx+HJly!MXHfm{_?r2M@U=f7QAF zG|pnX&$b{JlHh&9@w~P^BiOZn2B|g_z?InxQHk}GFfWhPFrome+1p2InQ3Y+^-V4; z+)WbId~(`(=T|DOw->zc-?fxamA&gUjF8&g?|IIp5*{I7ZJ}^ZjkJsod3Tq~J~N7E zTf}RyFjjf6riRpc$}1aIMZy5b!I!U)7T%`p7UmanlQE>*>mU9#^TGR;ZrPokT@|Xa zu2!+lww;hdns@*>EdGvv57)WbJh7(O74UV`#uhX#Ly0dklY&imqvVx#o`uDyLwYkj z^yNZ#9$n{fnQ-L-r0m;xPR)ZUP~)+o7i9Y-;13LwC3sUQejBxLx{6*=g5~|Q|0bsQ zY+@z(_*WrTgx=0{>U(7>c(R4ORjJ9Eh^;A<1np*rW~u;Ug>%2K$|4jYRlVL5anI}k zq$-n-@wzi@|Y4`MA}bay!!@R-|;8~|6h z4R%ryUp+-PQF+(BV6xy) z*_gpA-j z5 z^y;xJisDk*8|880MAaWRjvUkb!g(;o}eTMw(dg`AKlJ;`@Z6sqJ@oSX5O>fN;d zVI0vUYg~@l+m3LTruWItnO9P4pVOutd+@uJd<@5THYPMlcLF2d9Od!lnIuZ|n6d#X zYyN(cI>@s${@YO~m`WcilP6&~5z#DRk;<_eJjB=!9eAKMCa(IyOdQ7it8AF7tky>)vpUw66+LJ#Rli7NgnGA*(ixf z?&B-#WZdL*$fQ*9w_mjOsaErp%zFShAI!D!n??hnexx^;wW)HTNZesr4MSO3)Rz=X zlBmc3|O{U45Dpt1Qp=0u$f**Y6a6>|iZ=zTwUab!E%Z$up z)GZnjS*|4RWvij>GifL9Kao~}Sf}O_&5e|4q37p46U%L$H}Kw&8#eCpaVG%HN%3^w zSkjrJihsP|agfhAe;gVjFP^9Mx)(+>N6dXbr~jo2Mw1r;r=RU9pKN5D@c^piAvF)< z1&qLDnMDVp`o{(!IG}Og8cPa8)q13^Ji*}8TNqZ*xkW$$75kK84Edewu+`P)A3* zd1(d+Xn#bpggu|MM;Tmif`HPXGpD;6*w~@|%X}SuJn@KTjm_-9mI&kyaiH|~A~iEZ z^zTXQ)w<7|Ja+{%bnnS*$(=&bPjKLfdFSm2zVG%I zbh@5i4)j0Uq=4~vV?vvr`Y~Pew2H*79L^Euik$YaS#zbPJyvooWMOC&r3{taggGv$ zNOQ;0t1FtmX0;*MmIokA2(u2FW#hyHtXzyIV!D&H(y7yU?=dpM@9(D@@`1p$D5@>S z7IuQ&-CuCVA3r3ZAFt3C3e&jeBfDSSXYl9oGkvjGE?288fU;6bBAoI}d__*W3KNJq zu0bGfP@3IXlvaZSEFo_-FKrqp)wgDBhv04H_#s^>%SEn;3tqpo1oT_40&lKfNdtzh1Blh` z1gzYEyAa*R3$-N}J1L_>{s{1_oY$_jhQsk1LQ`840wy;WpP_}hS2iq;h^?@l`6QmpwIzah%eMB+`l!|IEhl;)+c1LQzwqf`5* zk4&(H+^#0cGfL;Rw214`k2j_41?}fhdv zsm=_i(xjFk%n~<9vic{~b-jG{=FiK{_S)zN3BbRc!39{-_IMk7DXSG^H)v?j$ml#% zT{xjBe%79ZFJ7?BWpkWGYQC4wWs6WNpWYv)ZI13$ ze@hckYdO5tg`QARXZb}flc}SDW5aY zr~zP%;5Ujs?h}VtT?}T4&bP=|6T}Mx&v2^&s3Qqvn$4~|gY*U|4l!5yZ7yxO_RQ2> zwf60eSEjyUa$~9X^#>o?ZCcGe;a8rnM6=KE_VpINx%BY->(>-tPxgJ*q{rFb5EID{ zO3g5OO2|lfM*iFJ|6N*({kNB52T5l5M*uK!w^nyG@w9MtGqD%5wlK4^aAh*HH*s@I zRhRSK62}lk-$=Bl_pb=0vVkS@r_hXC#!?**NjfM~c3uihPH8b=bt!Ap)nOy&C8g*3 zjC@6II0MrLzU_fOf6@qDk2{`YHUEnC+4eojb2ECsxH0+xaVFe7N(@UM5>4KJO57X+~&A#46^X(v)Drirvz_DtT}Rl&i{9d zdrh};0@XXOVu@pTFDBeEQ80tSjmuVQt;LeV@KLDk!08#Pf5HzcQ{$?BJV2G++xZfj zS#mvwV91-qSx@!mNYbr&0G&rnB?<@^xLx&DHA?qW8qa_(?W_>ObWI$Hc{3|?ukIEJ zV46$GzZJZO6sYk@6@NEzXnb`-1r4w4;gsf9mGOQ$6a0Ib$bUSBzhBK$9O6vGmQyWh zGWf;PdnKo$K<3jh`SOXU^hskr{&oj0ydC>|$RTH*UoXz6gX!fL#x6u7sRh{2;E8XS zpDq|@c|v=2MEQe<>^PxYO*&|P+*M`mnYeu>ch_i(XWBm=~$Btu=2))jQmUFwK6KdeGmdz;k9YAP#v!RY&ucAeYzT zu*TU~*phYOxO84>y7q+gNCWW1EQ(V=M|M^jTcc{bogXGosOb)GMO0x47ppC+&!(wt(vg0tHE7i{bG^w97k@Y%6 zHqb3fvWf$@e3z8INEF3G3YF0(vSPAC=|by7vclXwD>TBn=*DKY$^j&UVH9*yAEIgA z+uX=sT;K=8{2Vtr70mEuS+T1!ojxt>lpc8@U-A*8-3k}ZbOa#^)f=27*lH~&&Y;-7 z@$CiWoiZmdVi7nWh?{At6Q6OH|A(t@3eJTG*R5A=+qP}nwr%TcyK39E+g01PZQJJg z_r5!OCYjtPGjHBJO6rMfEaMmMN8XHrX+ep;!W_JAsm7vc!P==Ga+)N3B8`rFuAwEm zH{&h}l^KBb)YY)bY51Qr-qB{dbG5KHCWUV!+~hxTZceB01d?pt;M{j4tm}2A4=^$C zDPjZ+3(7kv-4e~(c?SEIxN%*ABqM7(y9{o@Y2mmjgi+IK6|fa?b)OT>GM@U4rnnhG4tK+iD$f%m|9EyFsGsc0Ew8$(|i645ue~9oh214jbGDq=?h?$gk ztuCiYvcJJi@S=54f-C1V4Y<;*a^z&Len9^Rl};)+!EP+E6M+OLoJ37wPP%r}0KjF* zNs0&;%zM#Z`agrL)gCd}|O7?Ju(0i~=*Y`*y5tJS)%Ta}}i&xLBQ z?Ia>`b>6kmkfIxw#KKE!NCnxW=qfF;+LwuxDW z&*Mph98E-_4*NCuV&l;7iSb;WmRo49l>emd+K*8NR&0s-u4y!~@cT?OpnXF%8(B9eM>$%_MPk~3sXn#GkcZ#mP65_#QCnki+7`s{5nVrXN0Nmm5cb)K z8|XEseLiRogna&FpB5}il@S~PR=UWzpuh~~(^glF(M}&6t)(U^AUEz@6Cr=vQMh)) z^=Z95^iYS!ca;h;jn&t9PvyTVie+#8mQD03P$^&ddS{;I@W`Aqvq#g!@i!42?Sl8o zsvyj|vjdi7T0GHmNnbw#u)ZgsaSHLmML)S+$mGm0NAsS0tXgruBHP(-;h=Q981fys zi9<>0rO14cp38{}C^Hdge$PCul?jVS-*lNuFQiIFd#pVx5EgohZ!lI`?}+7Od0Mbb z2fGgm3O>W^_(3kTvV;xqDPWTPvCk&;iTt5k><~6#ZiGt3+7cvWX#yrIvL$?z6n~Dl z3zL4)i2R15d&6V;5|RWUr9 zXE8%HflO#A*UiFN3a%S)MsXx%+z&Ac9Rz0}j(dnQs}vLO*|kegtEAqwlAQT#ExbS2 z=aE;hH_9^s$^?6`OfaQO4vxx>@)bIB5$;{TOvJ#n=E~GL2O>?eRRTmEOBMFSFHZ?z z1jCrorO~U15So}wD?#?9Cc$Ei6WUV3s9flSs8KRhr{TKMV-`~7k+|Kf;&-LAvi=(S z`jN)Y(AEC$3E>?JPfp1kSKu5L5P_OM zt|#%oYoBNa8*{J?5bFX_2#q)_ft0QB7-FwG6dWsqgi4&gU(KXL5Xvf~Vo8 zYjXCmT4T*T%c$tu?Ob~mkx1u)lUuG@oR;OvfxC%T;slc0h&w4T%b0!bljE&k#fcd9OX+fSm{G)l5MJ*zRDQV5k%#A5|Wzgu>*!U#9O{3f8$Z)P*XA zqWsCniuP&+oMb#imZZmC+nT9C;MVPPjxs&bRE#l&VBt05<{8DB;KOjEbEP`!jl#v6 zZJD0g%zi0PH^?j;YW7p(rEbgR9J-i!Mjf)>Fb-|PVZmE$dV(Lj2(od4t*ADUk4lkZ zHT>2QV8-6$&b2VjB}j!TN-GhR*=HshESsi8qqEZhBA3|tmbX;t!bo-ERkM#K_b}n7 zXQsC_%{iYN{Id#4D=|(Zo0f3VY7iqiE@8JX3a{9mZsB{Hr{g>fBQ6+ZRn)7-=Xu#I zU;fh`Z~9HQUg2&dJP%L?i`a`R`^4?w$Q3;=Z9i`3ltwmlmQ*S!i|RHGW;Ay$Jn7)F zr-p+9cIm2N90neT$oXU|o}>da{qr2vq0h-+7kIWL9N3~pm+6S9z~uC(FOF8FctkSA z8xycTfVItG3LK;s83j!+i~>eI|BB;}LCEjXWe!$0;^6;~(aE~dsYtx>;C?`$OX<0t z4Ntw!;S)X}&L7iZinzH_aKgC_`41Vv_2ydutlu=EuR)_)2TCRUMKlh^ot7`jw|+6oegiA zq7gsQb%`L8WH}W}DhDrNSCpRrLN=W;x;@$c{(#2)<;1mSWR!v+8rCqkgt7fksnv=k z0#_!DU20t~h%LlkE=*rPbtp%9OH{dqxo(9@|2<5Cs!veL@Y4H#{JvrJsvq0`(ar%> zKtM!5Nd;#lfN59F#k(jC>k1&!ZabZEagy!17eElKN7*OG$9uKTcs8I!?Ms;D*ULBfKh=a01`KrfS z2TQgoe$cb`bG-cHgD&r;2zaMn#_0@mU&frnB6hx&17%cQeIij_1!3s-#0cGkQN!*T zm=kJ%+PgU&U8+!OCe^3{aoA>j?<|GaJ7j(8P!?4E(uWLu?U_kE(jPPwv^!}1^8$`{ z+LTLP-Px+4f@P2f?R|)l*%w6;9#wt`-_`H}rDO7Yy(;I%H}r5E9aMdaH9dwQ40oIxwGtWz(w2cbD3+9sUPd zUflyYv;n2yrdp4rnO;E}>dyW?|Bc2vq6aJ`Z~0yPgiwk{WtYrx{KR0;Xnj7ul9%Xl zlv->huFAS9SM7tnlVjX~58BRXadYUPcoS9esIhpo)sMD`U|iT#a{}MKqUh}|Y78tu zJVvvc4wD6rkl71(qtiid3zvDoyk3EW1W5k!d~I#My~O16}Fo`wryeYX|gn|93|CtHG(!8PDQEYyu0b1E`>2$AON56Jij(Ek2<`;j8Uy{W5hwIntGC)Pp$ zPvk&oI|cIgG9E5Fu@g#R9dzhlb5IqNb<~EuvFGEgjBL3Ce~~+USRB0jeLV3don0j6 z;0O{wZ_7q}xX5NW*Gv&1N$&^M36NR2UxOKKaGS;t;{9z!d&9(1j5IS!mTn~j{&5ic zHYe1;J?oYpmPRIYNya-~60B7~+DQ*yWf%&fFPM0$^GggVnrhzVkF1Wz&6?Fy#&Z(U zz)A?P%I#)|%L97|gW4N&2!n;S08^mCT19R8f*?SaG#hdlN*$@i?`d|d56W7q-s?C| zMS&R-|8r6!`N)Mn$c>OQT$STr&{*^(C5ohV?=-G-!u9-^eKVh4&C4*LU(!y7(NuDq z#v9O!2t>t*gJxE^8=lc$@8_ZPq6OyixWjKEYJ1@5lxS|V##(5^7Yurzj-r@Dd>yao1E{ym};f$--w(%qkYB3MPXGsMx*ucMzA2gTKO4v;< z7oZ|wm%34I*r$sirF+Ul=r3VH25Q$d|M8uUACuA@))sI4B;WyvOoOESy&xmkc-~Yxo7+tk_V&p5F z=W|tron70~UaeU*5ouGl#a(!V=uz6wV*O#=t-h!8tr`L3?Qf=+o>HD-@6NPZeQA9t z9`X!b$^YPD&r=P}ovD9Bi?_}uyp0v&Yy2|h2&>5 z%_LzXA%2B+vG&E-joBj2|Hq2?ksJANbYg(mDY5Uv))Uv8fB*dzFoGb=^8^xO{Uq{{ zFoJMDDESK*$6caishH2psECJVVR1c4Z8N|O?=8PC`brnSUGTyF4&@Jy0UummU|{<} zCYXDh{6dTAr4Ai^hl(3htf!QT$Wsp&`?u-ZcP+t#5Xl0G3&L$sEdtNMVm5=1w_^MpnwN z*b#v}0$~8(Hr+A}+Yiz&Ck%s^t9Pt-{}IMqH=9qG2pdn({!eCeM@5#WGpp7t$+-zh zTVIo=ji?D}E;okhhaPf`?kb;EDU$whh26 z0h=dE^Sp!=r)|8JeV_zTc;87}YxZ8gZij&~t-mg2oY{;kFOn=-JyNNMKh@CJK}$hF z7rjg${XU64a&Zhe#!`vdJ6d6@$S`jki=!|dn5Dfe3k@wRSP9;r7Y)pzJTzwDC|Iq|`Rp#TaX4 zqcu2JAwDae@wU&r0AQ$zX)$f&JQyJ#brA?9mEI-VsO_cH4}dOYcvo11H;1klDY}^0 zZ4o^>Uqq2s!*wMWsohRK*U|$)gpr2Is~AutB3@h8U=J@YP`umMYXGX>U|+aGtVjU* zYOZ1T;icL{>0;%KcSf6hhcUzw$$noyQgiJ_Im);fS&S9*inFaYqDV*JQaU9+N6nsE zarrSemoM(8Uw2u@YjMxBf;BJ#sY?5*;p%F*fw_!{#6IuI$HvGo2jvRIVyDlA(NgE{=+<*E8WRw1Z7<9 z;D>hyQFBki$($V4rGkl{%g6`%L*y#;iT=G|%I@Yh!%p@?6aa($PJrS5b^v=;aViR^ zGwf#AlR$lQOitdnOik5U?b&F8M>bZ;nV$~954h-$K_QEyE!K9NR!E3E!rb47IS22v0O88b@Ga-_{ckya(7%~Ra*#A=EEJB*W%S%~sb zT6tyT3=sgL>w$RvH>FI@ud#^>>IsC;kjE^|8hAu;dk$RW;Ia$}D@s~^!O$7Vs=?!| zr5blVyn>m{Ku?fpJeHGz_Zrj)2l8b{?Wzx&3e+`)Ax)X=%Ajs@>xlq?a)x5DCoykX z=eCF*(LZ-;R(yV18z(dmp}aVkRecRFHv>C|Yc>GlQ;8$BGpLYU+%jip>ZjypWyvC5 zEJPqzqR8$uUrB5hR1FloT7zul(3)!@9S2!*lfXicJ8`fx|Ic(NRq~ujnF8CBl3( zbROUlak~1h9Ue&|TFJ`6Y?*SJTeOkJyaOQtVa#PAo1xG*nl8TwzVSIeKgE0wVrW)e zTh>lh?z#z#9a*`iwY;QQJ2TPRO1iRysv@b$&>o*yB0A?kf4`P5wJlM(M<%`0xq z{?TJ1rV8dGM&b~zPXW|@*se?4-%H(;Fe{-T^p*BeOQl;(x*PEQ1|{m-yLJ>+rBgt4 z`4bVa>VU7BTjcC{%?lM&aO7OG@(mqje6ox=fnSg9hqR9pzKI zuXWJOnO<(*E1{ladMer3lux;1bn2_OM)bl&Q3*K9pVu;TA*0EfPOUC%@eQV}pUx>AGZWG}XMd8|D?l@tvTwUj&nPK+Oyqk`wi-oqr9LU4s@OJ?CI28ksBlRU$}|>cO}#OEMYMX0Ks4RO zrSm2OpZLGG7AV558oXeZTKI%8nl-$h!LILKxb*XXz_9Stb^yTt@Li3!FYn;NfvR29 zSzi7^ZD^e$H=}3u>r0e)XaorhuDv6}5e$uob8;p6Eu0?duDQuu)kcZ^1b06eKFO8C z8C?k5c#-v_#!}~F3BM~TA()d$tqT4$<_EeUG3y~ZK~{W92cM}y$`{l<76h*Mz0rKw zY$=MA&F>nXfB{U|k^6T0gGA>3fpxO|}AOGVI-*_xJ684Kvo(-)HVOA$qu`jl6Z&LuzJ zh21iHnr(Q`4kLXQn($C`6DWkJx*Rxhh;OCMqx$EQ$wOMznN-~}ew=G7^im3zFzGjL zmZMV3AXTI1>}O?t{i3g4EiKVM5-nKQmxpy0(h2Up&99NKao-NwZEcp{x~3N*Q~{4$ zI*Cx42?U_Y)DLrYF!aZL@kCL2LYE%hbOlD1?a=BNTp44P{9#xac#PlrRkJR}20z;^ z7FS<1|L|C+Z7xFlM3~ZTv*7xsFuyTQ`HA}3WVfa3Ato*nwF=!rZeuK(cA9q}+voit z;QC>pMkNC0+8=lelaaZHXoIE~K-jGcEa1ugE*I$jD9}$9*1mKDT>s zZ(nzEKW{}4Ks7@EGeR)5_{zLp>3_1qSP^2Q)lErp6OaY~^}$8Vrly`w(Y^L?`((Vm z$sYP6gOgsIGlO=_iJl?R_Fai#o2Ps5U6H-|bcbwhNm4h7P8|9;1DEMf&qQ5;X5C67 zS$F0;UNU4i{W=+Uc3r+cWX7HnWCxxU2qZ*Xlbf&Oo)|lHMR_%n2YkF;8Uvrgo&ZP! z$o;=WzLMeq6#l6{1V&aAq`s;n+FJ}sVFXEcPEZtNzQXw*;nuWl)#=t(t1289q2!FM zE{c4G;%+n(mvA5{vM8&I@}2fDQ?qrp-2#VasqLfeIgr$?|wB{LM&!Qvh z8S;i&Wo8tGP&zR<+OBKrDpb?4FWxRXL{#@-GRsc@*z&5C>g#b*aBE((P;2r+K2byR zaH2EVv-1)faP+jr1*1~DWyW;-BKwOO^FSVA79{jP1zXg&mt;I_+ZSd&;9qv?*@gUd zDjdzVvJD1}9#!AjVVUysllsdmUOAgjjcFj#VOEKrB64MH+WKsNDP*$7tpubBY1JfB zQ^+*{^L!00z;x`S`$@G|6**C)bPS#G$-(3D%xn=P2HE?>XEy!C3$Zzyu_H~Y^rOzo z&0(yYBz4Sebh-Aep>l)DheK_7^{MIzHrFMZD!4Su6?pTo10-Aq*HUFJBpXsqq-`yn zuA|EDcgtyW_O$S$<_9$wPD^WZ@NCBol5fd?U=?J1LK_M>1sP5{M=$<#dvT8!1Z$=h zzA_1g^va}vQroHLVBipnZbQs1H5u|vF+pP&6Kf=|npixgUP2S6r4i$hteaEmMkP?v zJggRdkuq;hL4TMk4RP#M>yffhZBO>S+JySiZPn&N-N82#$h1N#QKOC0`UaH4?WfNG z;<}A!(TCANVUDQ}8>VnnZ?JW(hmFwqBf&wl_jg`9pCCQudophgL3Mjo$UUWdmz-sL zIB%uF5~#i~anx_@$PsQw1$tGg-S4V^lxfPmHK2+vlwb@9lAgg-D5hqExHhN1fQImmy%$X(e zup*_yhAZD>-6-fnRS&0<;EnW}iddaa5IQp+yLEi78i9A>Ez&CF%tjfrx^C`x%k2{K z<^}5P4miygDZ64O< zr!qQ{L(5K8ivW9b8t6(@Uw_5op6cv7bG)VZqzc=`tA-4Fo&|k!Z8RbI)dBnwgXqy0GhY zW0u|k@Ap080tJqNUGW|7E@Ff@w&J4RhSG(d|6X z!LTX(11fK zc9~|O#1dq_f!KA9H$^ad%%dJ{(hn)jx}3`$6T)hcAeMf1>CIQb_A3047qHtJvGU_Y zd!fx6RDdO?$!i4=t`fMKjX*wZW0uf%K|^9ScVa^_Q@X|D4;v2qwx}NptKUs>mvh)T zaH6$yQ^=#4!-o7bv!@-1WP4C|3C71DQqzx2hNO%PpO}@)#wE7D$C>(^>uF9*!4)qi zfAr~4hM{1Try0)w z5C3ym9TyR>=@`WsE{Gt*MGD}0S^?e$>2{hTjt#Dnab_a1SpmSda&>9Kozn5Rn#qT20k-2w!I5zN~q3-Pb&n$Yd91jl64`AF40LT@>%@*QC*i-=MBpKlVog( z>v--4+wq79`$`Ly^Z>Lprw`NBYrkbt;B zk}rWn-4?FdeN!uu)PdH4&O{u>lnN&oOL8c|2OvnpvC7R(t>?UQ-L7YB{}<@+1)|t* z0_ucnmad>kIbKh=D28XoMUN$!UucriZ|UhfipHQ57G%`WF}v$BX{Ch|OOrbnqIc7V zr(g@cdkUwW0Hxm6wO(&+H*3XinSx(y%xJ*&&F-=N%x6SU-bB^qmiF0mhqdxxu^eJO z39!)&gu47Y8W$UE5t6(`7;|BHS%XK-tmc+^;CAY$y^oPT($g z=|9>+Wu!TscjK6SabG6CXeD5hjujMbSt)P6=>xBZTNbqc=C;q(8M|f_egbogsoc!o ziopJ^w3ghjM$um4oKcY6%c$ExOfcyu2oM8N9|eLXh@rRC3R)R~$l(_nx7Vqx(=V09 zZdM;{458f=FpNSrKESTcN*^LaAy+1cC6(J6!Na40b-{2oJ%F&ExCPl z45Bkm)Pl}{Gff|%6PzZ^uE?-u7Z&h-Fv`GSo$#qR(6H<+u*u68i#r!~?XxlKv!Mq2 z&npj`aO9Gj+s9XleODciL9+SpP@^EX5i}d~Mg~5D!0;qGeF|2fe*OU0Tq3*(14ZEK z+SA|*FX3^BiY)ii?j=7xhXVeEtIinMs`>M2oEXyX{|4u98&4SQq5=VhC+(F{0<@rf zb=8&yC>p!QpWI}!T0}4)EH|p=z=f37 zO_dObsfm^IrDOtv2zkQW{ss^i5@*rm3-04di+9ZAMbWUph{ui|AfbaJo zKoD-p--}YL$E%cSY(*}`qLoP%0$s z@iqu-pAc&&q&>b_@-7*ldl+Z^#S}9ezsmC06&puLd$I<*72K*@(O~i#nEkj&Br|*@ zM`&Y84_o4|FM1xG9Id2I34j8>_?nll56X+YBm%5GYZj^=?Fe-M!faA5}Mb*xbX zj9cSSPv`=<%Kd&+VqWJ9%4%luElDWyu`KAzYKP9DZ1QT>(zj)C7m zEr_t2uIDWA#I8s2kipUyDQPEOa$THOebuZbr-mP;R1JegnTll?6`-xw+u`nVSjwW# z#_F)KR`2{+8u~0}VOzf46k1V!PiqpUgvWxMvpn5`Cg-}s7*i_)-5uOL99}XFWH5CU zN5;b=7iDE_vT#v-(-i%ZuGPKB+|eml)u9AuY?ja0&VnR^eJ#tfMb2J55e<`OKX_9a z5`MpuuE;-c*B|=D1<-WOUSC9)DJ$feTAokW+FUU&RlbZ4E-9vH6>!jIoWQ?$jqnN93?^tVR!NNxVNwgEUjWQBD=2<*%?kv39 zV%3<5tt0ZQpJs;J)J2n9mz~sQTf5-hpNqA$*kHc0WL8o+0dVqVR-?_KA|`HDIA_Y=UjYCFYlpt_-|(mJDof^ z76(YQy-vc__Nt*y)s$!`mhxvhjC<%d=yvPL9F5&483axs#2FC#U4$j9dh;Ra2^2XxHw( zS9WpQbMDz91c(1FM#`B*=7_qDy5051h9Y~En9nMFBJgYr6t{I8Hr;+mj>QW@@k2=x|Gz#Qr7yqVHcV1y81Dt`;X zgNCWv{r{+%e~K?!dL&v+*ejG?pf{(}sm@oN{~?fDS2S(t6O#3S*y$;bG6P>hZEimV z|8ZPB`|sn298M1Cm^hD^Mqh-tsbIV3lk9xh=#u3z<7ehVcSBQnijs3jae6(;Ez|Rw zS-@o)DV1swNW-|7>m|y0TgK!AK3RcAxJiHedNr3CZWvs@X)nN-e?aNU_J z!*j$r1{{5qFy-Sd@^itFCtrXL$oPdO;!E#SKl1xaP2z}YcdOixWKQmCP7B3g|Ij|mv z6p&ebYbz$*`(Eu{-7bnHu+XhN&$Ok)IrjMu=U+g-nx}t^ly5eO0cI*qa%T6A z4TE-8ZG!4o6lE_JX>~T|K@JsMB?=Kj|H2kLFc(LoG@8w(NsAzgEmq%5$GM#$czSqEHii^ zU8&qNj`!hdu)_RoX>yPi0Gz{HxJtCy283ZsyJ7=m6^Wwk1)(L}DMV#Fr;{zRIao^i zz!{D;)aVkhXJ3d0Q6H9w1~`jQJlGsAZqZ=d|JgYq8XaoPu(}h2-28*}=iZh4Wlu+s zuc0{ObJNlxTf|W^IMG2A3L`mn!P&vK*HuF5YG`sr$B(ocEE8q~07BJ)6Dr)l$$2a9 z79ej@Hz`CaV`h);Bd$MOzrv8;%9#dmO4J%$7hg92!Zog_lwPu~nhMbJXJ*Hmun2U) ztiP&fdXGzsj}o}ZO@baeOu1KTiT{`}8#C%qgmwObId+s-hzutC?aIHub^Yn) z6qhMIAys6u{wkaS0QS;Ye~M-p9`js(Sbo6=d2&9KPc`1^xO*q+3X0w6id?;u3|8Oa zoQ|@-TB}1OmgKpA^_*V?Tz@EfiywQ3wiiQrOupld9i{!bX9$o5zI3)8Qsr;w0IvR7 z4j|YFy-=-s-8Mriw}F8`szb zlTdZG@@I*mam27=wN_b_ZE0n<#Q2BqrUIc{dkB|KJt3+ss|}H60u62UFK@GndMPgq zbQBrAI?4fw2A)N%QRkc|f$eEjI24_nD(4G0{UtCa1`j!xpI_a2xaJKdnp1tLkC-W` zx|QdtQpZ3&0J`B2@LX-}Uq_HyA`Ef)bs%sFA)ykXLOARhm-bLfo&mN53`!deUpoUW zat?*_8~4FfY*;+_BVW6JrqFypFS4SZGLuKz)?ahB6}3td>*H*HTcw6e;A$}+4t1BU zJg9786#nJlR+Oc##AN4n22}EPx!W&-x--*+q023g0y^!o{lD?7Efgurk%n60n(C|G z+Bf`imu@IJBi)`(c^#;|>8mdTDI_#$Pc2&O4KidmAc2c~@Sq#aH|uTh`!uOOv1438 zh69^d1ZQDiH*@+a$In>=Tv~A1zt7z6vrhBr6L2*yjAhypooje-wx?=2o)>ocMA( zRSo0GIH++F`V~^K+Q}W^lV$t0WmRL$94XOtz-_^1(4r2BhrxP~RE~KZwPK@&d%>W- z#u%DxgNvoydQ>I%jcE^DhH$RciqgO8ab;(B%XQ5oc_$Z_n>Z~mP&Vo;HgXT*8l1%6 z2HuC$wg*U41gpgP2l6F1EOi#*A<+i)`MsD5;sVY;Ck3v;CGYY$-WBXElae(u+U9;! zfapOULpExom$i)9efx=HBsg^!d(uaRpU56(!-4RMYmcN5lhhRE>@jqSGpZsHvC76R z0)fqTX9TzdmmxK6x1Qn9tu;J)L|>kNQW>rw*M-c)4@%+uQhCIs3Wrqz?kWjehI`$T zwJb}IkFJ5<`jQ5HE+8lRq8LTr#6A4r0BC()i_}*Yqjw;1ok;PRvanC7U5TPenwJE1 z{r0%8W3^AqDgEJn8Ot~lfekNBEjbh`ep5|B7E7WW(Wo=z=wu$&^T{VP;%9Q^f8Hn+ z&`Vik$3nLn=gLpvte;ep*ts;+AC_0#tcRHsxA{z-SOoW>U4E*l_v0qQLvcUz0HR+Y zIa?}(caffn$Vz|enhdeCF+v5xH0g>hHnoWdjBL&wSS_8|JANuq?Q z-k@5r6vCzt?CPWb4d;%?+7NSWP6KUNcjbEMv`;IBV4pJ#939svV%->$+#r&?DGFJWD;TY@g5iv{tmYrT72->$}@ zFjju9iLc(+Xb&-2n-VOop}q@h4bQ#;w_H!f^;vE-!MHGo*&x6Q1=`O~0Ln(Y0^=s0 z{1y4BGjP|LkSLG&`zNPNxx9R7ZiGws!SuZT%5BxSQ*6!_sM>Al)|P>P+W|TZK(AJU z*TPSFg+C~6eZ^v|Q9W`T1Dr&2U+~v~RGs%fdYIZpc0lv5jMTNAyr-Fy=j52!M&Q)D zWmzd#c|`}oYl7*FfRovfMF^Vith{n*zexIO08 zE9DG#{4t}g;zs^y=2oh&@GDuuVFi`@BDtWfWdT4+LXZBH{*Xy0@L8mwkM?TJfN%zLC87*P- zH)m+j)Z+kCI6cssx{~LBgAAa3GHC-cqZxBN=+f#P_`VkKd}s1)DbV`$iux}-%;$w| z%+(Y#vn%}Qi0hHWQ$1)K*Sj_kEAnay;#a>6PCwM>AwD-X1Z6ufGlA(i&ni+z3|+a$ zfcX%eD0D07n#dD$00TEVN9$WxA&wQQA`=om zn(S1N0LET>vVB>~QW>ir@QX}fF+l|wdt~a|w`WqZO4?#iEWTpIe_!HB!YpmZsWI-B zDpUMofIV)16Y?d`-y!BAx7+-@HM9xp$k){Y&0Ah+z!2T1FB&KgsIMfq{eK_UA; z=FIWDQ!mhnYyfL33CfT08E|ct{1N<>PsgHyjZFvPnEHF4HZL^h$}w;rm@RWU?+NY? z$AYmi_yma>V9F)7YQBZrC+%b}G*co!%XfwpLNn$9Ss^nSIw%x_Ka4Oa$^y2Ny9Gop zP?~sl_~sXs3ve|Cf_S2tza2Gqnov91<`GQNp^oHVQfR(xvkFjedAlv`Kv$Tj_Utal z=MTHo;CNlEkblwtdlfUa=!jN>pWjRe>Z%>(%ki?<;cp#Dm{k{6!_gP|!_VDKhU^(n z9@bPCBOe?LGVQn2g{Gw>+f`wOAm=h>-%s-r_WiWa53v641%FV$=niQY(DL^{B9ebY zf&c~cU|z!FX+FcJK#oay1-wa%k3sCh(XcIsyuc50#UJd&2ln&$F#VpC@C_w$PNn`# zf$7x>Y;yM8_5<8~*TCreG5-mtxYJ@U5MjDtF1yan z4cjm)f=5A;8_Ez-0VOu#Z`~cU@loFWuW;U?qr~aZ5o^&afDMlD=}INT%6Rlg~rgdrs1LnXVc?ZGZPg zAif5dHSm0_uYQ2W{6@RdFL8Rp4!U+jRdDEoa#+yyWhiZR?pF`Z0OY3`?hq$aHXwM_ z18Q-pyQ)R&#xuG?e~M-4Pw?b&U&|$n1RkF}1d9cKx{@n^Zw5UORp{~a>DRxDV3iO8<2)4&4kWo&7zT@EIL*}HKgTKB_UsbpZ zQ>s3UBqT4(a*%QOd@Nl_^LK;;|N6k|0ia^LmBmpfWXchxR$;O|6hWNH0wlfAjsNb( zoZ72ece=D&lQ_fA1DHPWozdJ?NTZPH^U1CXRMupkuZq}k^X+hp;a3XgEv5G|MjFFL z=jibz@{aDCaAsldy27K9D>y(-$(CTtx}ZO4h2HNoD~nnRVtw&y=lkd&Uccn_0bd8% z^9-fE7A;Lt=LFEFA(Z?-Qoli24O+8W?+(?dt4oOx^GF8R-Ou=R%ariC1R#%Jit$1g zqD8GxY{I*ns&53;iekd{QERa7|8am==WhPq6kbmE_09509wWfLWr^Npe$qig%0%SlGS*9LcB$N%GZrzoISbMkLw9U+bX#eLI9eM_`z0zkL2hZAHW z9;z~@{F;*-zqs_iV(If$Ajdl9?st5nUB!WK;ECD$_CQvFqN5JOE$V2PrJWj3;V6f(2sGy($%5SX~P zMb6*0x9H-sXguw@0L*E0R z=3%{Bh({r05DW~^T%_GxsszyKu(*O0mAD)?5?@x*5u`+Aff46C>kTVI4Q=Iy7Ooyc zuRL*YzRLfbg(T%^rM8%u*zhh{CMEQpr`M(EaQ2b7ACejTaxG_5D>6eN6a)F8lUu!_ z4eWP4Ne^JKSW-l#x9aHFwN_VqRIFgfB|KEM!lfw{&+C@U^DET?V+N27R!_RARIsVO zFR0SftE%|lo@5sQmM-X23Ig8X_dBdlJ8MZ2XX-JKTh>Y~J37M}MzCmJ{ZKUAw>>ag zJ*UTA9T;Xex&>DTxA82zc}f}WpXovrpZBfBiK-s^YuZlqhyB8h&GIscV&Td#o4sjz zToZbv%Z;0+RNNGbKml2Ma%LI&fsjdzVuqT|W)*VT?GcaOT07%u&=e9W!tY1R z{hL9MOyMZ$N0Lz;W;8JnfeBT3A3n{Zl7hOysBk8#Jj3%RF*4molx#>NM#906qGFN@ zC&RyA%|sW|jtG^f7Zq?Gcb%|@5_Ek)ZbQpJB_7TLlTr+2T>#z_v!Om*2;n;DLsot@ zr#!c7gaObem=x3QCS(Mfxw=|BXzNW#C6++~g)*nSrE z#2vYgIOa?!#kr3&Nlc3y@lT*b4y&R57A~bCysmV)5+oYg!#BVibac%^UHwp8oi61W z9=OW(X{Ul3Pk_p^{#V05&;t`8^ftn%_>;glO++X*89%|Z>a%_<`tZIWS{ETw{{PnM zeDh`m$pKKUgP`bo!b{!wPv3YXbW>2aEI+|S{4r2^$pG+iXQ9-0LSS@L47PTDLMjB& zlOQmycs}|u5q`;daIct54nM&W-gpVlKK=OpI@mFOb_`QA{MP_kH@_izNi4P$e!?e& zzxZ7zmMg#iCm6L=Guvwu3J9ng4G4%bX>S@YiSZg9kfPybh<4x41iPKpTG zVVrE{K@_Qkh&)Y!>i#&+ zln80;hAZn}ELlPdWyv~}HA|$dW2da4iAYbD^jz6u?5472kR?kIl0?cj#!h34c|<9{ z{H}SPeqQtZ&Ohg#d*AatXU?2I?z!{5pO2eH#g!xHmA2cNL#D-8f0#1}wWAn>x;$0C zA7;pHlhh5f(0RMy>Xmo4AuvFAlz2j8WD-(jpCk^Co>dSR84o7ZUGjd98KrEc`XWXt zwH!;TnWHbt-Bx|=OY+dRwuh<$b)OF2HaovURH*u->tLpDg7qaSy!h*BDfHl!#Idku zxOD`7=*CZV8FtN7<9b|Q^lI~ePO=>pZ&Ht7WYiExdSsp=RUgrm&mVmTrH^E8walEc zyXZ7C=Iq*Cb0dCGff#NIsCb@GcTa?rr`_ylS7*~yvj&LYZ0(c#YW+hyO=Iv^JnOEy zFPhC}cs|H}w27^09<3sK+y4{~I`{TvF59!~mAK>miZB)*B?BWugQNb%HIzv*dFYnv ztHwJ`y)|j0C3c4@Nv3tghv;7-nhtF(%(}}Kb!iiy%IC+gt1Ks$U9C*7s?kAXhvkS8 z+66AAxX8uvM?=>u7-3tn+R6UvXE`51|D6rWMiCz1vjwmyh3-5z!+PPyUiOqvt6MLB zi8G4(^OOaltdRFCtc2xfEnN$Wy$fL(<;#Gh!vgS;V*5M8P$o2Q;JS|VnZUJ@W3*w_1@#CKl z-S(QTCi~2%Z7-HKayL~PxTJnM^SO`L(@JQNIg?;oKFWw{kTvo=-|F3m?qzd2C4z1( z)^fa(nipco^u;|~>5PGqft|m7$nyv9IlbQ?jE#%1^_Gt}qL5>l$>u)I8(Vcw# zMD^DXJ0H3q8@(;_H2B(VWiRu%#Mri3Y`oJd65({!)2X;G2v=M@lS#H2NIJ&dOtw^f z+33Y*j-{wX=ENr6SPCml8@7%-FliMi<7Y#WOS9@6z>jiDx4Z);uR4S28Cm`0LuhUZ z>&W4kBb74|y(JS~a~50-qzCI!C6IT|6y0vh;j_*S`_x1m*U>$}>xl4M-F4Yo=WTj87?MPcFDLGKv9t_b8707;Be~`tqge*Wp{~) zT@JJ;ybvmXo!l1d_9f8o6^DN%<8(|NXp^txFG}yi*rlcXC_VJ(>*%|lI zXSZ`^b?`j*_mfo;t&j)S!h%fY(>s`L$2Sg1+`RmF)WgV+HdZbZ_Zv83IB%#{5}NX2 zp4+OO>&XR+`kx5u_p#&Wnpxs!ZZ&av3}CfVan;5gm+`5--S0~d78q^muPh2gDr&|q zdl~6SYvyk-Sal6UuIklwgDwg3X&*SNpLFA{ahx_~Gz{uj)kCUSwXkgWE!ay8pNpDA z_OhFJn1pn^x;{BJm!V7{&Nw2ktwst-5`5N|n{PhXSbX?AF4(ulKg;e;Pr-Ubml`$) zY-t!a8$-MMMrFsvl4~>Y6)w4j%zxHr{5tk7|Lh%R`zl0E&6rN9bWr~f1a33Z-hZ=< zci{A*os;3RfW|Vire%Q8k~-vw3+B4o5{@~x@YWzPNN~XR0(Q-UPqwU3bgZa{()uXIG!*R$wZ$+zvK)fvGj}b1NZ!Rxc zz2aXPPbu~yo+cNc*UHf+K`#Kwq?^mRejH@#I4l-@v24BDxZZsQ{=!1$NYFQRonkC!>EmdV$%$X2vUm|-?JEoIB0j8HM`8u!DE4nbEojWrv zkq)H9r+B8KtQhG+$YYIUBSTwFQMH5Qfg z2;*SrA`?wG#-2}fKDiN&?To%!6s{0JIC;(#5KX?H=m->;n3|J}ehkcZmA`+eTpcVT zDL8C1^zClf0g>SY942$)8>?Tog>x%4e8Sim6XN~zSpy>F64n)GmRdZ&X!*A;tL-<#2ua%2#HBnHEQ%HS;CBJ;Ax2r*Rxahp2(8aJ z$#HUH`1MS=WK}eO_hBCm3;M`X#`+2-2b+TxVpF{JZ9g5S7%|*jdd9`t+~J?Hw9r$^ zUiL5pPCUB_;26nN>-S8}y2t#9l_1*C2%e?G+=uK{_#!_10?rb^>$XTb*V@IIS66V{ zSI=?GK`cB(GG~rXt|I{>FI;V-y@`l*8|N-VRx~ACT`K%BWm#T;_G4~zye8FVI=`Z6 zF`XWvneQ#P^kHd9bozD7E^ZeFYK;SglVb>a<~!u!P)W#%{4y_SPsG3ySwLA9B)CYF zhV8I`*(@>;DGk$O1%1ZVVL_~5E*k=rW90|Op|iVeP*W2+goD;3e)=jffOHwA&kdSu z0^kbi6s&}YdiZ$`0G%fIVJiUC6ay;(M)3OrT!8%DvlR_(-&&ztQFX|1=XWWJ9tQg- z&I5a%=mk*nl?0^Uf8zH=s4j|*5CI1!q(J9ML4d}Hng;R{r}ow|DFaYVXrV}JkZFWI z4fI-y3Q0|=08}ecD9=lRosLeE1`3j)LfKQY0F5ad4OE~+g&3!0fPJ&8e@DtwfgluQ zeFdpMPQwrGc@Ba3(>$~Ubewo*x9|C0-WC2=`< z7PVl5Aa#U`4}?KIXoRVY{IIbs>Z$b%esFS88ivcEHiegj0Gc-`_TxfByo;kk0T4u+ z1MI-T4sBK9a_+J{D937qTJ_AKse)3NwMo@HF0mjryZL&49g2Btuu$q@({<149 zqaCV5LDY%@Y^nzWl)$7FII#cxW-q&PzZ6BUzXzw^$%DjYI6$*m-DjYl%?BX}fcCEZ O%nF=zbk|6GSN{tyrB9>) delta 35860 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 diff --git a/forge/1.19.3/gradle/wrapper/gradle-wrapper.properties b/forge/1.19.3/gradle/wrapper/gradle-wrapper.properties index 37aef8d3..9355b415 100644 --- a/forge/1.19.3/gradle/wrapper/gradle-wrapper.properties +++ b/forge/1.19.3/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/forge/1.19.3/gradlew b/forge/1.19.3/gradlew index aeb74cbb..f5feea6d 100644 --- a/forge/1.19.3/gradlew +++ b/forge/1.19.3/gradlew @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # @@ -55,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -83,7 +85,9 @@ done # This is normally unused # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -130,10 +134,13 @@ location of your Java installation." fi else JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. @@ -141,7 +148,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -149,7 +156,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -198,11 +205,11 @@ fi # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ diff --git a/forge/1.19.3/gradlew.bat b/forge/1.19.3/gradlew.bat index 93e3f59f..9d21a218 100644 --- a/forge/1.19.3/gradlew.bat +++ b/forge/1.19.3/gradlew.bat @@ -13,6 +13,8 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## @@ -43,11 +45,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -57,11 +59,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail diff --git a/forge/1.20.2/gradle/wrapper/gradle-wrapper.jar b/forge/1.20.2/gradle/wrapper/gradle-wrapper.jar index c1962a79e29d3e0ab67b14947c167a862655af9b..a4b76b9530d66f5e68d973ea569d8e19de379189 100644 GIT binary patch literal 43583 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 yu?e%!_ptzGB|8GrCfu%p?(_ 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 GZ~q4|mN%#X literal 62076 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 diff --git a/forge/1.20.2/gradle/wrapper/gradle-wrapper.properties b/forge/1.20.2/gradle/wrapper/gradle-wrapper.properties index 37aef8d3..9355b415 100644 --- a/forge/1.20.2/gradle/wrapper/gradle-wrapper.properties +++ b/forge/1.20.2/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/forge/1.20.2/gradlew b/forge/1.20.2/gradlew index aeb74cbb..f5feea6d 100644 --- a/forge/1.20.2/gradlew +++ b/forge/1.20.2/gradlew @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # @@ -55,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -83,7 +85,9 @@ done # This is normally unused # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -130,10 +134,13 @@ location of your Java installation." fi else JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. @@ -141,7 +148,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -149,7 +156,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -198,11 +205,11 @@ fi # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ diff --git a/forge/1.20.2/gradlew.bat b/forge/1.20.2/gradlew.bat index 93e3f59f..9d21a218 100644 --- a/forge/1.20.2/gradlew.bat +++ b/forge/1.20.2/gradlew.bat @@ -13,6 +13,8 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## @@ -43,11 +45,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -57,11 +59,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail diff --git a/forge/1.20.6/gradle/wrapper/gradle-wrapper.jar b/forge/1.20.6/gradle/wrapper/gradle-wrapper.jar index e6441136f3d4ba8a0da8d277868979cfbc8ad796..a4b76b9530d66f5e68d973ea569d8e19de379189 100644 GIT binary patch delta 12612 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 HJ4oML2Lo<@i8BwbL^1~GkG`E7C$SEa_ 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 diff --git a/forge/1.20.6/gradle/wrapper/gradle-wrapper.properties b/forge/1.20.6/gradle/wrapper/gradle-wrapper.properties index b82aa23a..9355b415 100644 --- a/forge/1.20.6/gradle/wrapper/gradle-wrapper.properties +++ b/forge/1.20.6/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/forge/1.20.6/gradlew b/forge/1.20.6/gradlew index 1aa94a42..f5feea6d 100644 --- a/forge/1.20.6/gradlew +++ b/forge/1.20.6/gradlew @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # @@ -55,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -84,7 +86,8 @@ done # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum diff --git a/forge/1.20.6/gradlew.bat b/forge/1.20.6/gradlew.bat index 25da30db..9d21a218 100644 --- a/forge/1.20.6/gradlew.bat +++ b/forge/1.20.6/gradlew.bat @@ -13,6 +13,8 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## diff --git a/forge/1.20/gradle/wrapper/gradle-wrapper.jar b/forge/1.20/gradle/wrapper/gradle-wrapper.jar index c1962a79e29d3e0ab67b14947c167a862655af9b..d64cd4917707c1f8861d8cb53dd15194d4248596 100644 GIT binary patch literal 43462 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 literal 62076 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 diff --git a/forge/1.20/gradle/wrapper/gradle-wrapper.properties b/forge/1.20/gradle/wrapper/gradle-wrapper.properties index 37aef8d3..a80b22ce 100644 --- a/forge/1.20/gradle/wrapper/gradle-wrapper.properties +++ b/forge/1.20/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/forge/1.20/gradlew b/forge/1.20/gradlew index aeb74cbb..1aa94a42 100644 --- a/forge/1.20/gradlew +++ b/forge/1.20/gradlew @@ -83,7 +83,8 @@ done # This is normally unused # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -130,10 +131,13 @@ location of your Java installation." fi else JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. @@ -141,7 +145,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -149,7 +153,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -198,11 +202,11 @@ fi # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ diff --git a/forge/1.20/gradlew.bat b/forge/1.20/gradlew.bat index 93e3f59f..25da30db 100644 --- a/forge/1.20/gradlew.bat +++ b/forge/1.20/gradlew.bat @@ -43,11 +43,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -57,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail diff --git a/forge/1.7.10/gradle/wrapper/gradle-wrapper.properties b/forge/1.7.10/gradle/wrapper/gradle-wrapper.properties index bdc9a83b..707e499a 100644 --- a/forge/1.7.10/gradle/wrapper/gradle-wrapper.properties +++ b/forge/1.7.10/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/neoforge/1.20.2/gradle/wrapper/gradle-wrapper.jar b/neoforge/1.20.2/gradle/wrapper/gradle-wrapper.jar index c1962a79e29d3e0ab67b14947c167a862655af9b..a4b76b9530d66f5e68d973ea569d8e19de379189 100644 GIT binary patch literal 43583 zcma&N1CXTcmMvW9vTb(Rwr$&4wr$(C?dmSu>@vG-+vuvg^_??!{yS%8zW-#zn-LkA z5&1^$^{lnmUON?}LBF8_K|(?T0Ra(xUH{($5eN!MR#ZihR#HxkUPe+_R8Cn`RRs(P z_^*#_XlXmGv7!4;*Y%p4nw?{bNp@UZHv1?Um8r6)Fei3p@ClJn0ECfg1hkeuUU@Or zDaPa;U3fE=3L}DooL;8f;P0ipPt0Z~9P0)lbStMS)ag54=uL9ia-Lm3nh|@(Y?B`; zx_#arJIpXH!U{fbCbI^17}6Ri*H<>OLR%c|^mh8+)*h~K8Z!9)DPf zR2h?lbDZQ`p9P;&DQ4F0sur@TMa!Y}S8irn(%d-gi0*WxxCSk*A?3lGh=gcYN?FGl z7D=Js!i~0=u3rox^eO3i@$0=n{K1lPNU zwmfjRVmLOCRfe=seV&P*1Iq=^i`502keY8Uy-WNPwVNNtJFx?IwAyRPZo2Wo1+S(xF37LJZ~%i)kpFQ3Fw=mXfd@>%+)RpYQLnr}B~~zoof(JVm^^&f zxKV^+3D3$A1G;qh4gPVjhrC8e(VYUHv#dy^)(RoUFM?o%W-EHxufuWf(l*@-l+7vt z=l`qmR56K~F|v<^Pd*p~1_y^P0P^aPC##d8+HqX4IR1gu+7w#~TBFphJxF)T$2WEa zxa?H&6=Qe7d(#tha?_1uQys2KtHQ{)Qco)qwGjrdNL7thd^G5i8Os)CHqc>iOidS} z%nFEDdm=GXBw=yXe1W-ShHHFb?Cc70+$W~z_+}nAoHFYI1MV1wZegw*0y^tC*s%3h zhD3tN8b=Gv&rj}!SUM6|ajSPp*58KR7MPpI{oAJCtY~JECm)*m_x>AZEu>DFgUcby z1Qaw8lU4jZpQ_$;*7RME+gq1KySGG#Wql>aL~k9tLrSO()LWn*q&YxHEuzmwd1?aAtI zBJ>P=&$=l1efe1CDU;`Fd+_;&wI07?V0aAIgc(!{a z0Jg6Y=inXc3^n!U0Atk`iCFIQooHqcWhO(qrieUOW8X(x?(RD}iYDLMjSwffH2~tB z)oDgNBLB^AJBM1M^c5HdRx6fBfka`(LD-qrlh5jqH~);#nw|iyp)()xVYak3;Ybik z0j`(+69aK*B>)e_p%=wu8XC&9e{AO4c~O1U`5X9}?0mrd*m$_EUek{R?DNSh(=br# z#Q61gBzEpmy`$pA*6!87 zSDD+=@fTY7<4A?GLqpA?Pb2z$pbCc4B4zL{BeZ?F-8`s$?>*lXXtn*NC61>|*w7J* z$?!iB{6R-0=KFmyp1nnEmLsA-H0a6l+1uaH^g%c(p{iT&YFrbQ$&PRb8Up#X3@Zsk zD^^&LK~111%cqlP%!_gFNa^dTYT?rhkGl}5=fL{a`UViaXWI$k-UcHJwmaH1s=S$4 z%4)PdWJX;hh5UoK?6aWoyLxX&NhNRqKam7tcOkLh{%j3K^4Mgx1@i|Pi&}<^5>hs5 zm8?uOS>%)NzT(%PjVPGa?X%`N2TQCKbeH2l;cTnHiHppPSJ<7y-yEIiC!P*ikl&!B z%+?>VttCOQM@ShFguHVjxX^?mHX^hSaO_;pnyh^v9EumqSZTi+#f&_Vaija0Q-e*| z7ulQj6Fs*bbmsWp{`auM04gGwsYYdNNZcg|ph0OgD>7O}Asn7^Z=eI>`$2*v78;sj-}oMoEj&@)9+ycEOo92xSyY344^ z11Hb8^kdOvbf^GNAK++bYioknrpdN>+u8R?JxG=!2Kd9r=YWCOJYXYuM0cOq^FhEd zBg2puKy__7VT3-r*dG4c62Wgxi52EMCQ`bKgf*#*ou(D4-ZN$+mg&7$u!! z-^+Z%;-3IDwqZ|K=ah85OLwkO zKxNBh+4QHh)u9D?MFtpbl)us}9+V!D%w9jfAMYEb>%$A;u)rrI zuBudh;5PN}_6J_}l55P3l_)&RMlH{m!)ai-i$g)&*M`eN$XQMw{v^r@-125^RRCF0 z^2>|DxhQw(mtNEI2Kj(;KblC7x=JlK$@78`O~>V!`|1Lm-^JR$-5pUANAnb(5}B}JGjBsliK4& zk6y(;$e&h)lh2)L=bvZKbvh@>vLlreBdH8No2>$#%_Wp1U0N7Ank!6$dFSi#xzh|( zRi{Uw%-4W!{IXZ)fWx@XX6;&(m_F%c6~X8hx=BN1&q}*( zoaNjWabE{oUPb!Bt$eyd#$5j9rItB-h*5JiNi(v^e|XKAj*8(k<5-2$&ZBR5fF|JA z9&m4fbzNQnAU}r8ab>fFV%J0z5awe#UZ|bz?Ur)U9bCIKWEzi2%A+5CLqh?}K4JHi z4vtM;+uPsVz{Lfr;78W78gC;z*yTch~4YkLr&m-7%-xc ztw6Mh2d>_iO*$Rd8(-Cr1_V8EO1f*^@wRoSozS) zy1UoC@pruAaC8Z_7~_w4Q6n*&B0AjOmMWa;sIav&gu z|J5&|{=a@vR!~k-OjKEgPFCzcJ>#A1uL&7xTDn;{XBdeM}V=l3B8fE1--DHjSaxoSjNKEM9|U9#m2<3>n{Iuo`r3UZp;>GkT2YBNAh|b z^jTq-hJp(ebZh#Lk8hVBP%qXwv-@vbvoREX$TqRGTgEi$%_F9tZES@z8Bx}$#5eeG zk^UsLBH{bc2VBW)*EdS({yw=?qmevwi?BL6*=12k9zM5gJv1>y#ML4!)iiPzVaH9% zgSImetD@dam~e>{LvVh!phhzpW+iFvWpGT#CVE5TQ40n%F|p(sP5mXxna+Ev7PDwA zamaV4m*^~*xV+&p;W749xhb_X=$|LD;FHuB&JL5?*Y2-oIT(wYY2;73<^#46S~Gx| z^cez%V7x$81}UWqS13Gz80379Rj;6~WdiXWOSsdmzY39L;Hg3MH43o*y8ibNBBH`(av4|u;YPq%{R;IuYow<+GEsf@R?=@tT@!}?#>zIIn0CoyV!hq3mw zHj>OOjfJM3F{RG#6ujzo?y32m^tgSXf@v=J$ELdJ+=5j|=F-~hP$G&}tDZsZE?5rX ztGj`!S>)CFmdkccxM9eGIcGnS2AfK#gXwj%esuIBNJQP1WV~b~+D7PJTmWGTSDrR` zEAu4B8l>NPuhsk5a`rReSya2nfV1EK01+G!x8aBdTs3Io$u5!6n6KX%uv@DxAp3F@{4UYg4SWJtQ-W~0MDb|j-$lwVn znAm*Pl!?Ps&3wO=R115RWKb*JKoexo*)uhhHBncEDMSVa_PyA>k{Zm2(wMQ(5NM3# z)jkza|GoWEQo4^s*wE(gHz?Xsg4`}HUAcs42cM1-qq_=+=!Gk^y710j=66(cSWqUe zklbm8+zB_syQv5A2rj!Vbw8;|$@C!vfNmNV!yJIWDQ>{+2x zKjuFX`~~HKG~^6h5FntRpnnHt=D&rq0>IJ9#F0eM)Y-)GpRjiN7gkA8wvnG#K=q{q z9dBn8_~wm4J<3J_vl|9H{7q6u2A!cW{bp#r*-f{gOV^e=8S{nc1DxMHFwuM$;aVI^ zz6A*}m8N-&x8;aunp1w7_vtB*pa+OYBw=TMc6QK=mbA-|Cf* zvyh8D4LRJImooUaSb7t*fVfih<97Gf@VE0|z>NcBwBQze);Rh!k3K_sfunToZY;f2 z^HmC4KjHRVg+eKYj;PRN^|E0>Gj_zagfRbrki68I^#~6-HaHg3BUW%+clM1xQEdPYt_g<2K+z!$>*$9nQ>; zf9Bei{?zY^-e{q_*|W#2rJG`2fy@{%6u0i_VEWTq$*(ZN37|8lFFFt)nCG({r!q#9 z5VK_kkSJ3?zOH)OezMT{!YkCuSSn!K#-Rhl$uUM(bq*jY? zi1xbMVthJ`E>d>(f3)~fozjg^@eheMF6<)I`oeJYx4*+M&%c9VArn(OM-wp%M<-`x z7sLP1&3^%Nld9Dhm@$3f2}87!quhI@nwd@3~fZl_3LYW-B?Ia>ui`ELg z&Qfe!7m6ze=mZ`Ia9$z|ARSw|IdMpooY4YiPN8K z4B(ts3p%2i(Td=tgEHX z0UQ_>URBtG+-?0E;E7Ld^dyZ;jjw0}XZ(}-QzC6+NN=40oDb2^v!L1g9xRvE#@IBR zO!b-2N7wVfLV;mhEaXQ9XAU+>=XVA6f&T4Z-@AX!leJ8obP^P^wP0aICND?~w&NykJ#54x3_@r7IDMdRNy4Hh;h*!u(Ol(#0bJdwEo$5437-UBjQ+j=Ic>Q2z` zJNDf0yO6@mr6y1#n3)s(W|$iE_i8r@Gd@!DWDqZ7J&~gAm1#~maIGJ1sls^gxL9LLG_NhU!pTGty!TbhzQnu)I*S^54U6Yu%ZeCg`R>Q zhBv$n5j0v%O_j{QYWG!R9W?5_b&67KB$t}&e2LdMvd(PxN6Ir!H4>PNlerpBL>Zvyy!yw z-SOo8caEpDt(}|gKPBd$qND5#a5nju^O>V&;f890?yEOfkSG^HQVmEbM3Ugzu+UtH zC(INPDdraBN?P%kE;*Ae%Wto&sgw(crfZ#Qy(<4nk;S|hD3j{IQRI6Yq|f^basLY; z-HB&Je%Gg}Jt@={_C{L$!RM;$$|iD6vu#3w?v?*;&()uB|I-XqEKqZPS!reW9JkLewLb!70T7n`i!gNtb1%vN- zySZj{8-1>6E%H&=V}LM#xmt`J3XQoaD|@XygXjdZ1+P77-=;=eYpoEQ01B@L*a(uW zrZeZz?HJsw_4g0vhUgkg@VF8<-X$B8pOqCuWAl28uB|@r`19DTUQQsb^pfqB6QtiT z*`_UZ`fT}vtUY#%sq2{rchyfu*pCg;uec2$-$N_xgjZcoumE5vSI{+s@iLWoz^Mf; zuI8kDP{!XY6OP~q5}%1&L}CtfH^N<3o4L@J@zg1-mt{9L`s^z$Vgb|mr{@WiwAqKg zp#t-lhrU>F8o0s1q_9y`gQNf~Vb!F%70f}$>i7o4ho$`uciNf=xgJ>&!gSt0g;M>*x4-`U)ysFW&Vs^Vk6m%?iuWU+o&m(2Jm26Y(3%TL; zA7T)BP{WS!&xmxNw%J=$MPfn(9*^*TV;$JwRy8Zl*yUZi8jWYF>==j~&S|Xinsb%c z2?B+kpet*muEW7@AzjBA^wAJBY8i|#C{WtO_or&Nj2{=6JTTX05}|H>N2B|Wf!*3_ z7hW*j6p3TvpghEc6-wufFiY!%-GvOx*bZrhZu+7?iSrZL5q9}igiF^*R3%DE4aCHZ zqu>xS8LkW+Auv%z-<1Xs92u23R$nk@Pk}MU5!gT|c7vGlEA%G^2th&Q*zfg%-D^=f z&J_}jskj|Q;73NP4<4k*Y%pXPU2Thoqr+5uH1yEYM|VtBPW6lXaetokD0u z9qVek6Q&wk)tFbQ8(^HGf3Wp16gKmr>G;#G(HRBx?F`9AIRboK+;OfHaLJ(P>IP0w zyTbTkx_THEOs%Q&aPrxbZrJlio+hCC_HK<4%f3ZoSAyG7Dn`=X=&h@m*|UYO-4Hq0 z-Bq&+Ie!S##4A6OGoC~>ZW`Y5J)*ouaFl_e9GA*VSL!O_@xGiBw!AF}1{tB)z(w%c zS1Hmrb9OC8>0a_$BzeiN?rkPLc9%&;1CZW*4}CDDNr2gcl_3z+WC15&H1Zc2{o~i) z)LLW=WQ{?ricmC`G1GfJ0Yp4Dy~Ba;j6ZV4r{8xRs`13{dD!xXmr^Aga|C=iSmor% z8hi|pTXH)5Yf&v~exp3o+sY4B^^b*eYkkCYl*T{*=-0HniSA_1F53eCb{x~1k3*`W zr~};p1A`k{1DV9=UPnLDgz{aJH=-LQo<5%+Em!DNN252xwIf*wF_zS^!(XSm(9eoj z=*dXG&n0>)_)N5oc6v!>-bd(2ragD8O=M|wGW z!xJQS<)u70m&6OmrF0WSsr@I%T*c#Qo#Ha4d3COcX+9}hM5!7JIGF>7<~C(Ear^Sn zm^ZFkV6~Ula6+8S?oOROOA6$C&q&dp`>oR-2Ym3(HT@O7Sd5c~+kjrmM)YmgPH*tL zX+znN>`tv;5eOfX?h{AuX^LK~V#gPCu=)Tigtq9&?7Xh$qN|%A$?V*v=&-2F$zTUv z`C#WyIrChS5|Kgm_GeudCFf;)!WH7FI60j^0o#65o6`w*S7R@)88n$1nrgU(oU0M9 zx+EuMkC>(4j1;m6NoGqEkpJYJ?vc|B zOlwT3t&UgL!pX_P*6g36`ZXQ; z9~Cv}ANFnJGp(;ZhS(@FT;3e)0)Kp;h^x;$*xZn*k0U6-&FwI=uOGaODdrsp-!K$Ac32^c{+FhI-HkYd5v=`PGsg%6I`4d9Jy)uW0y%) zm&j^9WBAp*P8#kGJUhB!L?a%h$hJgQrx!6KCB_TRo%9{t0J7KW8!o1B!NC)VGLM5! zpZy5Jc{`r{1e(jd%jsG7k%I+m#CGS*BPA65ZVW~fLYw0dA-H_}O zrkGFL&P1PG9p2(%QiEWm6x;U-U&I#;Em$nx-_I^wtgw3xUPVVu zqSuKnx&dIT-XT+T10p;yjo1Y)z(x1fb8Dzfn8e yu?e%!_ptzGB|8GrCfu%p?(_ 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 GZ~q4|mN%#X literal 62076 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 diff --git a/neoforge/1.20.2/gradle/wrapper/gradle-wrapper.properties b/neoforge/1.20.2/gradle/wrapper/gradle-wrapper.properties index 37aef8d3..9355b415 100644 --- a/neoforge/1.20.2/gradle/wrapper/gradle-wrapper.properties +++ b/neoforge/1.20.2/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/neoforge/1.20.2/gradlew b/neoforge/1.20.2/gradlew index aeb74cbb..f5feea6d 100644 --- a/neoforge/1.20.2/gradlew +++ b/neoforge/1.20.2/gradlew @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # @@ -55,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -83,7 +85,9 @@ done # This is normally unused # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -130,10 +134,13 @@ location of your Java installation." fi else JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. @@ -141,7 +148,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -149,7 +156,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -198,11 +205,11 @@ fi # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ diff --git a/neoforge/1.20.2/gradlew.bat b/neoforge/1.20.2/gradlew.bat index 93e3f59f..9d21a218 100644 --- a/neoforge/1.20.2/gradlew.bat +++ b/neoforge/1.20.2/gradlew.bat @@ -13,6 +13,8 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## @@ -43,11 +45,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -57,11 +59,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail diff --git a/neoforge/1.20.4/gradle/wrapper/gradle-wrapper.jar b/neoforge/1.20.4/gradle/wrapper/gradle-wrapper.jar index c1962a79e29d3e0ab67b14947c167a862655af9b..a4b76b9530d66f5e68d973ea569d8e19de379189 100644 GIT binary patch literal 43583 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 yu?e%!_ptzGB|8GrCfu%p?(_ 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 GZ~q4|mN%#X literal 62076 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 diff --git a/neoforge/1.20.4/gradle/wrapper/gradle-wrapper.properties b/neoforge/1.20.4/gradle/wrapper/gradle-wrapper.properties index 37aef8d3..9355b415 100644 --- a/neoforge/1.20.4/gradle/wrapper/gradle-wrapper.properties +++ b/neoforge/1.20.4/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/neoforge/1.20.4/gradlew b/neoforge/1.20.4/gradlew index aeb74cbb..f5feea6d 100644 --- a/neoforge/1.20.4/gradlew +++ b/neoforge/1.20.4/gradlew @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # @@ -55,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -83,7 +85,9 @@ done # This is normally unused # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -130,10 +134,13 @@ location of your Java installation." fi else JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. @@ -141,7 +148,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -149,7 +156,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -198,11 +205,11 @@ fi # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ diff --git a/neoforge/1.20.4/gradlew.bat b/neoforge/1.20.4/gradlew.bat index 93e3f59f..9d21a218 100644 --- a/neoforge/1.20.4/gradlew.bat +++ b/neoforge/1.20.4/gradlew.bat @@ -13,6 +13,8 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## @@ -43,11 +45,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -57,11 +59,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail diff --git a/neoforge/1.20.6/gradle/wrapper/gradle-wrapper.jar b/neoforge/1.20.6/gradle/wrapper/gradle-wrapper.jar index e6441136f3d4ba8a0da8d277868979cfbc8ad796..a4b76b9530d66f5e68d973ea569d8e19de379189 100644 GIT binary patch delta 12612 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 HJ4oML2Lo<@i8BwbL^1~GkG`E7C$SEa_ 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 diff --git a/neoforge/1.20.6/gradle/wrapper/gradle-wrapper.properties b/neoforge/1.20.6/gradle/wrapper/gradle-wrapper.properties index b82aa23a..9355b415 100644 --- a/neoforge/1.20.6/gradle/wrapper/gradle-wrapper.properties +++ b/neoforge/1.20.6/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/neoforge/1.20.6/gradlew b/neoforge/1.20.6/gradlew index 1aa94a42..f5feea6d 100644 --- a/neoforge/1.20.6/gradlew +++ b/neoforge/1.20.6/gradlew @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # @@ -55,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -84,7 +86,8 @@ done # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum diff --git a/neoforge/1.20.6/gradlew.bat b/neoforge/1.20.6/gradlew.bat index 25da30db..9d21a218 100644 --- a/neoforge/1.20.6/gradlew.bat +++ b/neoforge/1.20.6/gradlew.bat @@ -13,6 +13,8 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## diff --git a/neoforge/1.21/gradle/wrapper/gradle-wrapper.jar b/neoforge/1.21/gradle/wrapper/gradle-wrapper.jar index e6441136f3d4ba8a0da8d277868979cfbc8ad796..a4b76b9530d66f5e68d973ea569d8e19de379189 100644 GIT binary patch delta 12612 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 HJ4oML2Lo<@i8BwbL^1~GkG`E7C$SEa_ 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 diff --git a/neoforge/1.21/gradle/wrapper/gradle-wrapper.properties b/neoforge/1.21/gradle/wrapper/gradle-wrapper.properties index b82aa23a..9355b415 100644 --- a/neoforge/1.21/gradle/wrapper/gradle-wrapper.properties +++ b/neoforge/1.21/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/neoforge/1.21/gradlew b/neoforge/1.21/gradlew index 1aa94a42..f5feea6d 100644 --- a/neoforge/1.21/gradlew +++ b/neoforge/1.21/gradlew @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # @@ -55,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -84,7 +86,8 @@ done # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum diff --git a/neoforge/1.21/gradlew.bat b/neoforge/1.21/gradlew.bat index 25da30db..9d21a218 100644 --- a/neoforge/1.21/gradlew.bat +++ b/neoforge/1.21/gradlew.bat @@ -13,6 +13,8 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## diff --git a/spigot/1.21/gradle/wrapper/gradle-wrapper.jar b/spigot/1.21/gradle/wrapper/gradle-wrapper.jar index e6441136f3d4ba8a0da8d277868979cfbc8ad796..a4b76b9530d66f5e68d973ea569d8e19de379189 100644 GIT binary patch delta 12612 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 HJ4oML2Lo<@i8BwbL^1~GkG`E7C$SEa_ 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 diff --git a/spigot/1.21/gradle/wrapper/gradle-wrapper.properties b/spigot/1.21/gradle/wrapper/gradle-wrapper.properties index b82aa23a..9355b415 100644 --- a/spigot/1.21/gradle/wrapper/gradle-wrapper.properties +++ b/spigot/1.21/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/spigot/1.21/gradlew b/spigot/1.21/gradlew index 1aa94a42..f5feea6d 100644 --- a/spigot/1.21/gradlew +++ b/spigot/1.21/gradlew @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # @@ -55,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -84,7 +86,8 @@ done # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum diff --git a/spigot/1.21/gradlew.bat b/spigot/1.21/gradlew.bat index 25da30db..9d21a218 100644 --- a/spigot/1.21/gradlew.bat +++ b/spigot/1.21/gradlew.bat @@ -13,6 +13,8 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## From 26625f503a743fe4ba2aefb1cf98cbf6dab5085a Mon Sep 17 00:00:00 2001 From: HoldYourWaffle Date: Tue, 3 Sep 2024 08:39:12 +0200 Subject: [PATCH 559/580] Rewire corelib dependency --- fabric/1.18/build.gradle | 8 +++++--- fabric/1.19.2/build.gradle | 8 +++++--- fabric/1.19.3/build.gradle | 8 +++++--- fabric/1.20.2/build.gradle | 8 +++++--- fabric/1.20.6/build.gradle | 8 +++++--- fabric/1.20/build.gradle | 8 +++++--- fabric/1.21/build.gradle | 8 +++++--- forge/1.12/build.gradle | 13 ++++++++----- forge/1.16/build.gradle | 19 +++++++++++-------- forge/1.18/build.gradle | 9 +++++---- forge/1.19.2/build.gradle | 8 ++++---- forge/1.19.3/build.gradle | 8 ++++---- forge/1.20.2/build.gradle | 6 ++++-- forge/1.20.6/build.gradle | 6 ++++-- forge/1.20/build.gradle | 6 ++++-- forge/1.7.10/build.gradle.kts | 12 ++++++------ global.properties | 3 +++ neoforge/1.20.2/build.gradle | 8 +++++--- neoforge/1.20.4/build.gradle | 11 ++++++----- neoforge/1.20.6/build.gradle | 11 ++++++----- neoforge/1.21/build.gradle | 11 ++++++----- spigot/1.21/build.gradle | 9 ++++++--- 22 files changed, 117 insertions(+), 79 deletions(-) create mode 100644 global.properties diff --git a/fabric/1.18/build.gradle b/fabric/1.18/build.gradle index d51c2539..c94ccef4 100644 --- a/fabric/1.18/build.gradle +++ b/fabric/1.18/build.gradle @@ -3,6 +3,8 @@ plugins { id 'maven-publish' } +apply from: '../../global.properties' + group = project.maven_group archivesBaseName = 'AdvancedBackups-' + modloaderName + "-" + minecraftVersion @@ -35,8 +37,8 @@ dependencies { // modImplementation "net.fabricmc.fabric-api:fabric-api-deprecated:${project.fabric_version}" - implementation files ('advancedbackups-corelib.jar') - extraLibs files ('advancedbackups-corelib.jar') + implementation files(abCoreLibPath) + extraLibs files(abCoreLibPath) } processResources { @@ -94,4 +96,4 @@ publishing { // The repositories here will be used for publishing your artifact, not for // retrieving dependencies. } -} \ No newline at end of file +} diff --git a/fabric/1.19.2/build.gradle b/fabric/1.19.2/build.gradle index 922c32ce..756d668e 100644 --- a/fabric/1.19.2/build.gradle +++ b/fabric/1.19.2/build.gradle @@ -3,6 +3,8 @@ plugins { id 'maven-publish' } +apply from: '../../global.properties' + group = project.maven_group archivesBaseName = 'AdvancedBackups-' + modloaderName + "-" + minecraftVersion @@ -35,8 +37,8 @@ dependencies { // modImplementation "net.fabricmc.fabric-api:fabric-api-deprecated:${project.fabric_version}" - implementation files ('advancedbackups-corelib.jar') - extraLibs files ('advancedbackups-corelib.jar') + implementation files(abCoreLibPath) + extraLibs files(abCoreLibPath) } processResources { @@ -94,4 +96,4 @@ publishing { // The repositories here will be used for publishing your artifact, not for // retrieving dependencies. } -} \ No newline at end of file +} diff --git a/fabric/1.19.3/build.gradle b/fabric/1.19.3/build.gradle index 6753fb87..57b73e9a 100644 --- a/fabric/1.19.3/build.gradle +++ b/fabric/1.19.3/build.gradle @@ -3,6 +3,8 @@ plugins { id 'maven-publish' } +apply from: '../../global.properties' + group = project.maven_group archivesBaseName = 'AdvancedBackups-' + modloaderName + "-" + minecraftVersion @@ -38,8 +40,8 @@ dependencies { // modImplementation "net.fabricmc.fabric-api:fabric-api-deprecated:${project.fabric_version}" - implementation files ('advancedbackups-corelib.jar') - extraLibs files ('advancedbackups-corelib.jar') + implementation files(abCoreLibPath) + extraLibs files(abCoreLibPath) } processResources { @@ -97,4 +99,4 @@ publishing { // The repositories here will be used for publishing your artifact, not for // retrieving dependencies. } -} \ No newline at end of file +} diff --git a/fabric/1.20.2/build.gradle b/fabric/1.20.2/build.gradle index 6a2e5cd3..4b591d83 100644 --- a/fabric/1.20.2/build.gradle +++ b/fabric/1.20.2/build.gradle @@ -3,6 +3,8 @@ plugins { id 'maven-publish' } +apply from: '../../global.properties' + group = project.maven_group archivesBaseName = 'AdvancedBackups-' + modloaderName + "-" + minecraftVersion @@ -38,8 +40,8 @@ dependencies { // modImplementation "net.fabricmc.fabric-api:fabric-api-deprecated:${project.fabric_version}" - implementation files ('advancedbackups-corelib.jar') - extraLibs files ('advancedbackups-corelib.jar') + implementation files(abCoreLibPath) + extraLibs files(abCoreLibPath) } processResources { @@ -97,4 +99,4 @@ publishing { // The repositories here will be used for publishing your artifact, not for // retrieving dependencies. } -} \ No newline at end of file +} diff --git a/fabric/1.20.6/build.gradle b/fabric/1.20.6/build.gradle index 94581d29..fb682fa5 100644 --- a/fabric/1.20.6/build.gradle +++ b/fabric/1.20.6/build.gradle @@ -3,6 +3,8 @@ plugins { id 'maven-publish' } +apply from: '../../global.properties' + group = project.maven_group archivesBaseName = 'AdvancedBackups-' + modloaderName + "-" + minecraftVersion @@ -38,8 +40,8 @@ dependencies { // modImplementation "net.fabricmc.fabric-api:fabric-api-deprecated:${project.fabric_version}" - implementation files ('advancedbackups-corelib.jar') - extraLibs files ('advancedbackups-corelib.jar') + implementation files(abCoreLibPath) + extraLibs files(abCoreLibPath) } processResources { @@ -97,4 +99,4 @@ publishing { // The repositories here will be used for publishing your artifact, not for // retrieving dependencies. } -} \ No newline at end of file +} diff --git a/fabric/1.20/build.gradle b/fabric/1.20/build.gradle index 38c95c1a..c69976b0 100644 --- a/fabric/1.20/build.gradle +++ b/fabric/1.20/build.gradle @@ -3,6 +3,8 @@ plugins { id 'maven-publish' } +apply from: '../../global.properties' + group = project.maven_group archivesBaseName = 'AdvancedBackups-' + modloaderName + "-" + minecraftVersion @@ -37,8 +39,8 @@ dependencies { // modImplementation "net.fabricmc.fabric-api:fabric-api-deprecated:${project.fabric_version}" - implementation files ('advancedbackups-corelib.jar') - extraLibs files ('advancedbackups-corelib.jar') + implementation files(abCoreLibPath) + extraLibs files(abCoreLibPath) } processResources { @@ -96,4 +98,4 @@ publishing { // The repositories here will be used for publishing your artifact, not for // retrieving dependencies. } -} \ No newline at end of file +} diff --git a/fabric/1.21/build.gradle b/fabric/1.21/build.gradle index 7444c4b9..62db7add 100644 --- a/fabric/1.21/build.gradle +++ b/fabric/1.21/build.gradle @@ -3,6 +3,8 @@ plugins { id 'maven-publish' } +apply from: '../../global.properties' + group = project.maven_group archivesBaseName = 'AdvancedBackups-' + modloaderName + "-" + minecraftVersion @@ -38,8 +40,8 @@ dependencies { // modImplementation "net.fabricmc.fabric-api:fabric-api-deprecated:${project.fabric_version}" - implementation files ('advancedbackups-corelib.jar') - extraLibs files ('advancedbackups-corelib.jar') + implementation files(abCoreLibPath) + extraLibs files(abCoreLibPath) } processResources { @@ -97,4 +99,4 @@ publishing { // The repositories here will be used for publishing your artifact, not for // retrieving dependencies. } -} \ No newline at end of file +} diff --git a/forge/1.12/build.gradle b/forge/1.12/build.gradle index f824bfe5..c907ea2c 100644 --- a/forge/1.12/build.gradle +++ b/forge/1.12/build.gradle @@ -4,6 +4,7 @@ plugins { id 'net.minecraftforge.gradle' version '5.1.+' } +apply from: '../../global.properties' group = 'co.uk.mommyheather.advancedbackups' // http://maven.apache.org/guides/mini/guide-naming-conventions.html archivesBaseName = 'AdvancedBackups-' + modloaderName + "-" + minecraftVersion @@ -31,7 +32,7 @@ minecraft { //mappings channel: 'snapshot', version: '20171003-1.12' mappings channel: 'snapshot', version: '20171003-1.12' // makeObfSourceJar = false // an Srg named sources jar is made by default. uncomment this to disable. - + // accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg') // Default run configurations. @@ -68,8 +69,9 @@ dependencies { // that the dep is a ForgeGradle 'patcher' dependency. And it's patches will be applied. // The userdev artifact is a special name and will get all sorts of transformations applied to it. minecraft 'net.minecraftforge:forge:1.12.2-14.23.5.2855' - implementation files ('advancedbackups-corelib.jar') - extraLibs files ('advancedbackups-corelib.jar') + + implementation files(abCoreLibPath) + extraLibs files(abCoreLibPath) // You may put jars on which you depend on in ./libs or you may define them like so.. // compile "some.group:artifact:version:classifier" @@ -116,14 +118,15 @@ jar { "Implementation-Vendor" : "mommyheather", "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ") ]) - } + } from { configurations.extraLibs.collect { it.isDirectory() ? it : zipTree(it) } } } + // Example configuration to allow publishing using the maven-publish task // This is the preferred method to reobfuscate your jar file -jar.finalizedBy('reobfJar') +jar.finalizedBy('reobfJar') // However if you are in a multi-project build, dev time needs unobfed jar files, so you can delay the obfuscation until publishing by doing //publish.dependsOn('reobfJar') diff --git a/forge/1.16/build.gradle b/forge/1.16/build.gradle index 1ceab533..e30b7a5b 100644 --- a/forge/1.16/build.gradle +++ b/forge/1.16/build.gradle @@ -12,6 +12,8 @@ apply plugin: 'net.minecraftforge.gradle' apply plugin: 'eclipse' apply plugin: 'maven-publish' +apply from: '../../global.properties' + group = 'co.uk.mommyheather.advancedbackups' // http://maven.apache.org/guides/mini/guide-naming-conventions.html archivesBaseName = 'AdvancedBackups-' + modloaderName + "-" + minecraftVersion @@ -32,7 +34,7 @@ minecraft { // Simply re-run your setup task after changing the mappings to update your workspace. mappings channel: 'official', version: '1.16.5' // makeObfSourceJar = false // an Srg named sources jar is made by default. uncomment this to disable. - + accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg') // Default run configurations. @@ -42,7 +44,7 @@ minecraft { workingDirectory project.file('run') // Recommended logging data for a userdev environment - // The markers can be changed as needed. + // The markers can be changed as needed. // "SCAN": For mods scan. // "REGISTRIES": For firing of registry events. // "REGISTRYDUMP": For getting the contents of all registries. @@ -64,7 +66,7 @@ minecraft { workingDirectory project.file('run') // Recommended logging data for a userdev environment - // The markers can be changed as needed. + // The markers can be changed as needed. // "SCAN": For mods scan. // "REGISTRIES": For firing of registry events. // "REGISTRYDUMP": For getting the contents of all registries. @@ -86,7 +88,7 @@ minecraft { workingDirectory project.file('run') // Recommended logging data for a userdev environment - // The markers can be changed as needed. + // The markers can be changed as needed. // "SCAN": For mods scan. // "REGISTRIES": For firing of registry events. // "REGISTRYDUMP": For getting the contents of all registries. @@ -123,8 +125,9 @@ dependencies { // The userdev artifact is a special name and will get all sorts of transformations applied to it. minecraft 'net.minecraftforge:forge:1.16.5-36.1.0' - implementation files ('advancedbackups-corelib.jar') - extraLibs files ('advancedbackups-corelib.jar') + implementation files(abCoreLibPath) + extraLibs files(abCoreLibPath) + // You may put jars on which you depend on in ./libs or you may define them like so.. // compile "some.group:artifact:version:classifier" // compile "some.group:artifact:version" @@ -170,7 +173,7 @@ jar { "Implementation-Vendor" : "mommyheather", "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ") ]) - } + } from { configurations.extraLibs.collect { it.isDirectory() ? it : zipTree(it) } } @@ -178,7 +181,7 @@ jar { // Example configuration to allow publishing using the maven-publish task // This is the preferred method to reobfuscate your jar file -jar.finalizedBy('reobfJar') +jar.finalizedBy('reobfJar') // However if you are in a multi-project build, dev time needs unobfed jar files, so you can delay the obfuscation until publishing by doing //publish.dependsOn('reobfJar') diff --git a/forge/1.18/build.gradle b/forge/1.18/build.gradle index d46d927e..7d21f1bc 100644 --- a/forge/1.18/build.gradle +++ b/forge/1.18/build.gradle @@ -15,6 +15,7 @@ plugins { } apply plugin: 'net.minecraftforge.gradle' +apply from: '../../global.properties' group = 'co.uk.mommyheather.advancedbackups' // http://maven.apache.org/guides/mini/guide-naming-conventions.html archivesBaseName = 'AdvancedBackups-' + modloaderName + "-" + minecraftVersion @@ -158,9 +159,9 @@ dependencies { minecraft 'net.minecraftforge:forge:1.18.2-40.2.1' //extraLibs 'com.sun.jna.platform:5.13.0' - minecraftLibrary files ('advancedbackups-corelib.jar') - extraLibs files ('advancedbackups-corelib.jar') - + minecraftLibrary files(abCoreLibPath) + extraLibs files(abCoreLibPath) + // Real mod deobf dependency examples - these get remapped to your current mappings // compileOnly fg.deobf("mezz.jei:jei-${mc_version}:${jei_version}:api") // Adds JEI API as a compile dependency // runtimeOnly fg.deobf("mezz.jei:jei-${mc_version}:${jei_version}") // Adds the full JEI mod as a runtime dependency @@ -198,7 +199,7 @@ jar { "Implementation-Vendor" : "mommyheather", "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ") ]) - } + } from { configurations.extraLibs.collect { it.isDirectory() ? it : zipTree(it) } } diff --git a/forge/1.19.2/build.gradle b/forge/1.19.2/build.gradle index 3044bcd3..c6937412 100644 --- a/forge/1.19.2/build.gradle +++ b/forge/1.19.2/build.gradle @@ -4,7 +4,7 @@ plugins { id 'net.minecraftforge.gradle' version '5.1.+' } - +apply from: '../../global.properties' group = 'co.uk.mommyheather.advancedbackups' // http://maven.apache.org/guides/mini/guide-naming-conventions.html archivesBaseName = 'AdvancedBackups-' + modloaderName + "-" + minecraftVersion @@ -121,8 +121,8 @@ dependencies { //implementation files('dependencies/jansi-2.4.0.jar') //extraLibs files('dependencies/jansi-2.4.0.jar') - minecraftLibrary files ('advancedbackups-corelib.jar') - extraLibs files ('advancedbackups-corelib.jar') + minecraftLibrary files(abCoreLibPath) + extraLibs files(abCoreLibPath) // Real mod deobf dependency examples - these get remapped to your current mappings // compileOnly fg.deobf("mezz.jei:jei-${mc_version}:${jei_version}:api") // Adds JEI API as a compile dependency @@ -161,7 +161,7 @@ jar { "Implementation-Vendor" : "mommyheather", "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ") ]) - } + } from { configurations.extraLibs.collect { it.isDirectory() ? it : zipTree(it) } } diff --git a/forge/1.19.3/build.gradle b/forge/1.19.3/build.gradle index 5b88d3da..40fb4ba5 100644 --- a/forge/1.19.3/build.gradle +++ b/forge/1.19.3/build.gradle @@ -4,7 +4,7 @@ plugins { id 'net.minecraftforge.gradle' version '[6.0,6.2)' } - +apply from: '../../global.properties' group = 'co.uk.mommyheather.advancedbackups' // http://maven.apache.org/guides/mini/guide-naming-conventions.html archivesBaseName = 'AdvancedBackups-' + modloaderName + "-" + minecraftVersion @@ -122,8 +122,8 @@ dependencies { //implementation files('dependencies/jansi-2.4.0.jar') //extraLibs files('dependencies/jansi-2.4.0.jar') - minecraftLibrary files ('advancedbackups-corelib.jar') - extraLibs files ('advancedbackups-corelib.jar') + minecraftLibrary files(abCoreLibPath) + extraLibs files(abCoreLibPath) // Real mod deobf dependency examples - these get remapped to your current mappings // compileOnly fg.deobf("mezz.jei:jei-${mc_version}:${jei_version}:api") // Adds JEI API as a compile dependency @@ -162,7 +162,7 @@ jar { "Implementation-Vendor" : "mommyheather", "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ") ]) - } + } from { configurations.extraLibs.collect { it.isDirectory() ? it : zipTree(it) } } diff --git a/forge/1.20.2/build.gradle b/forge/1.20.2/build.gradle index ea8bfb6f..48b6e51b 100644 --- a/forge/1.20.2/build.gradle +++ b/forge/1.20.2/build.gradle @@ -6,6 +6,8 @@ plugins { id 'org.spongepowered.mixin' version '0.7.+' } +apply from: '../../global.properties' + group = mod_group_id base { @@ -152,8 +154,8 @@ dependencies { // The group id is ignored when searching -- in this case, it is "blank" // implementation fg.deobf("blank:coolmod-${mc_version}:${coolmod_version}") - minecraftLibrary files ('advancedbackups-corelib.jar') - extraLibs files ('advancedbackups-corelib.jar') + minecraftLibrary files(abCoreLibPath) + extraLibs files(abCoreLibPath) // For more info: // http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html diff --git a/forge/1.20.6/build.gradle b/forge/1.20.6/build.gradle index 5824b12b..524c4787 100644 --- a/forge/1.20.6/build.gradle +++ b/forge/1.20.6/build.gradle @@ -5,6 +5,8 @@ plugins { id 'net.minecraftforge.gradle' version '[6.0.24,6.2)' } +apply from: '../../global.properties' + group = mod_group_id base { @@ -147,8 +149,8 @@ dependencies { // The group id is ignored when searching -- in this case, it is "blank" // implementation fg.deobf("blank:coolmod-${mc_version}:${coolmod_version}") - minecraftLibrary files ('advancedbackups-corelib.jar') - extraLibs files ('advancedbackups-corelib.jar') + minecraftLibrary files(abCoreLibPath) + extraLibs files(abCoreLibPath) // For more info: // http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html diff --git a/forge/1.20/build.gradle b/forge/1.20/build.gradle index 3d786f0e..bc753939 100644 --- a/forge/1.20/build.gradle +++ b/forge/1.20/build.gradle @@ -6,6 +6,8 @@ plugins { id 'org.spongepowered.mixin' version '0.7.+' } +apply from: '../../global.properties' + group = mod_group_id base { @@ -155,8 +157,8 @@ dependencies { // The group id is ignored when searching -- in this case, it is "blank" // implementation fg.deobf("blank:coolmod-${mc_version}:${coolmod_version}") - minecraftLibrary files ('advancedbackups-corelib.jar') - extraLibs files ('advancedbackups-corelib.jar') + minecraftLibrary files(abCoreLibPath) + extraLibs files(abCoreLibPath) implementation fg.deobf('curse.maven:jei-322036:4680512') diff --git a/forge/1.7.10/build.gradle.kts b/forge/1.7.10/build.gradle.kts index d9b1685f..075d5166 100644 --- a/forge/1.7.10/build.gradle.kts +++ b/forge/1.7.10/build.gradle.kts @@ -7,8 +7,7 @@ plugins { id("com.gtnewhorizons.retrofuturagradle") version "1.2.5" } - - +apply from: '../../global.properties' //version = "2.0" group = "co.uk.mommyheather.advancedbackups" // http://maven.apache.org/guides/mini/guide-naming-conventions.html @@ -105,9 +104,10 @@ val extraLibs by configurations.creating dependencies { // Adds NotEnoughItems and its dependencies (CCL&CCC) to runClient/runServer runtimeOnlyNonPublishable("com.github.GTNewHorizons:NotEnoughItems:2.3.39-GTNH:dev") - - implementation (files("advancedbackups-corelib.jar")) - extraLibs (files("advancedbackups-corelib.jar")) + + implementation files(abCoreLibPath) + extraLibs files(abCoreLibPath) + // Example: grab the ic2 jar from curse maven and deobfuscate // api(rfg.deobf("curse.maven:ic2-242638:2353971")) // Example: grab the ic2 jar from libs/ in the workspace and deobfuscate @@ -144,7 +144,7 @@ tasks.withType { manifest { attributes["Main-Class"] = "co.uk.mommyheather.advancedbackups.cli.AdvancedBackupsCLI" attributes["Implementation-Version"] = "${version}" - } + } } diff --git a/global.properties b/global.properties new file mode 100644 index 00000000..b841890a --- /dev/null +++ b/global.properties @@ -0,0 +1,3 @@ +ext { + abCoreLibPath = "$projectDir/../../core/build/libs/advancedbackups-corelib.jar" +} diff --git a/neoforge/1.20.2/build.gradle b/neoforge/1.20.2/build.gradle index bf29a17a..25548f4e 100644 --- a/neoforge/1.20.2/build.gradle +++ b/neoforge/1.20.2/build.gradle @@ -6,6 +6,8 @@ plugins { id 'net.neoforged.gradle.userdev' version '7.0.26' } +apply from: '../../global.properties' + group = mod_group_id version = "${version != 'unspecified' ? version : '0.1-dev'}" //debuggins sake @@ -96,8 +98,8 @@ dependencies { implementation "net.neoforged:neoforge:${neo_version}" - implementation files ('advancedbackups-corelib.jar') - extraLibs files ('advancedbackups-corelib.jar') + implementation files(abCoreLibPath) + extraLibs files(abCoreLibPath) // Example mod dependency with JEI // The JEI API is declared for compile time use, while the full JEI artifact is used at runtime @@ -175,4 +177,4 @@ publishing { tasks.withType(JavaCompile).configureEach { options.encoding = 'UTF-8' // Use the UTF-8 charset for Java compilation -} \ No newline at end of file +} diff --git a/neoforge/1.20.4/build.gradle b/neoforge/1.20.4/build.gradle index 3bcb5f36..2d565791 100644 --- a/neoforge/1.20.4/build.gradle +++ b/neoforge/1.20.4/build.gradle @@ -6,6 +6,8 @@ plugins { id 'net.neoforged.gradle.userdev' version '7.0.80' } +apply from: '../../global.properties' + group = mod_group_id version = "${version != 'unspecified' ? version : '0.1-dev'}" //debuggins sake @@ -95,9 +97,8 @@ dependencies { // For all intends and purposes: You can treat this dependency as if it is a normal library you would use. implementation "net.neoforged:neoforge:${neo_version}" - - implementation files ('advancedbackups-corelib.jar') - extraLibs files ('advancedbackups-corelib.jar') + implementation files(abCoreLibPath) + extraLibs files(abCoreLibPath) // Example mod dependency with JEI // The JEI API is declared for compile time use, while the full JEI artifact is used at runtime @@ -153,7 +154,7 @@ tasks.named('jar', Jar).configure { "Implementation-Vendor" : "mommyheather", "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ") ]) - } + } from { configurations.extraLibs.collect { it.isDirectory() ? it : zipTree(it) } } @@ -175,4 +176,4 @@ publishing { tasks.withType(JavaCompile).configureEach { options.encoding = 'UTF-8' // Use the UTF-8 charset for Java compilation -} \ No newline at end of file +} diff --git a/neoforge/1.20.6/build.gradle b/neoforge/1.20.6/build.gradle index 50316297..dce59bf8 100644 --- a/neoforge/1.20.6/build.gradle +++ b/neoforge/1.20.6/build.gradle @@ -6,6 +6,8 @@ plugins { id 'net.neoforged.gradle.userdev' version '7.0.109' } +apply from: '../../global.properties' + group = mod_group_id version = "${version != 'unspecified' ? version : '0.1-dev'}" //debuggins sake @@ -95,9 +97,8 @@ dependencies { // For all intends and purposes: You can treat this dependency as if it is a normal library you would use. implementation "net.neoforged:neoforge:${neo_version}" - - implementation files ('advancedbackups-corelib.jar') - extraLibs files ('advancedbackups-corelib.jar') + implementation files(abCoreLibPath) + extraLibs files(abCoreLibPath) // Example mod dependency with JEI // The JEI API is declared for compile time use, while the full JEI artifact is used at runtime @@ -153,7 +154,7 @@ tasks.named('jar', Jar).configure { "Implementation-Vendor" : "mommyheather", "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ") ]) - } + } from { configurations.extraLibs.collect { it.isDirectory() ? it : zipTree(it) } } @@ -175,4 +176,4 @@ publishing { tasks.withType(JavaCompile).configureEach { options.encoding = 'UTF-8' // Use the UTF-8 charset for Java compilation -} \ No newline at end of file +} diff --git a/neoforge/1.21/build.gradle b/neoforge/1.21/build.gradle index 5d352477..2609be96 100644 --- a/neoforge/1.21/build.gradle +++ b/neoforge/1.21/build.gradle @@ -16,6 +16,8 @@ tasks.named('wrapper', Wrapper).configure { distributionType = Wrapper.DistributionType.BIN } +apply from: '../../global.properties' + group = mod_group_id version = "${version != 'unspecified' ? version : '0.1-dev'}" //debuggins sake @@ -106,9 +108,8 @@ dependencies { // For all intends and purposes: You can treat this dependency as if it is a normal library you would use. implementation "net.neoforged:neoforge:${neo_version}" - - implementation files ('advancedbackups-corelib.jar') - extraLibs files ('advancedbackups-corelib.jar') + implementation files(abCoreLibPath) + extraLibs files(abCoreLibPath) // Example mod dependency with JEI // The JEI API is declared for compile time use, while the full JEI artifact is used at runtime @@ -164,7 +165,7 @@ tasks.named('jar', Jar).configure { "Implementation-Vendor" : "mommyheather", "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ") ]) - } + } from { configurations.extraLibs.collect { it.isDirectory() ? it : zipTree(it) } } @@ -186,4 +187,4 @@ publishing { tasks.withType(JavaCompile).configureEach { options.encoding = 'UTF-8' // Use the UTF-8 charset for Java compilation -} \ No newline at end of file +} diff --git a/spigot/1.21/build.gradle b/spigot/1.21/build.gradle index e4616b75..dc905915 100644 --- a/spigot/1.21/build.gradle +++ b/spigot/1.21/build.gradle @@ -7,6 +7,9 @@ plugins { id 'maven-publish' id 'io.github.patrick.remapper' version "1.4.2" } + +apply from: '../../global.properties' + group = 'computer.heather.AdvancedBackups' description = 'AdvancedBackups' java.sourceCompatibility = JavaVersion.VERSION_21 @@ -35,8 +38,8 @@ configurations { dependencies { compileOnly("org.spigotmc:spigot:1.21.1-R0.1-SNAPSHOT:remapped-mojang") - implementation files ('advancedbackups-corelib.jar') - extraLibs files ('advancedbackups-corelib.jar') + implementation files(abCoreLibPath) + extraLibs files(abCoreLibPath) } @@ -65,7 +68,7 @@ tasks.named('jar', Jar).configure { "Implementation-Vendor" : "mommyheather", "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ") ]) - } + } from { configurations.extraLibs.collect { it.isDirectory() ? it : zipTree(it) } } From 3b0259fe038b239122b7e5fb08980b7d26eb7c4d Mon Sep 17 00:00:00 2001 From: HoldYourWaffle Date: Tue, 3 Sep 2024 08:39:44 +0200 Subject: [PATCH 560/580] Add script that builds all modules --- build-all.sh | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 build-all.sh diff --git a/build-all.sh b/build-all.sh new file mode 100644 index 00000000..d3fcefdb --- /dev/null +++ b/build-all.sh @@ -0,0 +1,15 @@ +#!/bin/sh + +root=$(pwd) + +# This will fail silently (but deadly) if there's ever a modloader that's lexicographically before "core" +find . -maxdepth 3 -type f -name 'build.gradle' | sed -r 's|/[^/]+$||' | sort \ +| while read -r folder; do + echo -e "\n\e[1;104m Building $folder... \e[0m" + cd "$folder" || exit 1 + + # Older Gradle versions are naughty and consume stdin for some reason + ./gradlew build < /dev/null + + cd "$root" || exit 1 +done From 8384eee6d6586b4a816f3ce06330dec449b0351b Mon Sep 17 00:00:00 2001 From: Heather White <66441550+HeatherComputer@users.noreply.github.com> Date: Sat, 2 Nov 2024 13:34:49 +0000 Subject: [PATCH 561/580] add version arg to build-all script (...script isn't even usable though, because of JAVA_HOME issues) --- build-all.sh | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/build-all.sh b/build-all.sh index d3fcefdb..75ce3c24 100644 --- a/build-all.sh +++ b/build-all.sh @@ -1,5 +1,10 @@ #!/bin/sh +if [ "$#" -ne 1 ]; then + echo "Usage: $0 " + exit 1 +fi + root=$(pwd) # This will fail silently (but deadly) if there's ever a modloader that's lexicographically before "core" @@ -9,7 +14,7 @@ find . -maxdepth 3 -type f -name 'build.gradle' | sed -r 's|/[^/]+$||' | sort \ cd "$folder" || exit 1 # Older Gradle versions are naughty and consume stdin for some reason - ./gradlew build < /dev/null + ./gradlew -Pversion=$1 build < /dev/null cd "$root" || exit 1 done From e19dd1660b1f439efb8c54cf91bdb11122516ce5 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+HeatherComputer@users.noreply.github.com> Date: Sat, 2 Nov 2024 13:46:39 +0000 Subject: [PATCH 562/580] test to see if core + forge 1.7.10 can build. --- .github/workflows/build.yml | 37 +++++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c93d9ee6..472c80af 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -26,13 +26,15 @@ jobs: distribution: 'temurin' - name: Build Core - run: ./gradlew shadowJar + run: | + cd core + ./gradlew shadowJar - name: Upload Core uses: actions/upload-artifact@v3 with: name: advancedbackups-corelib.jar - path: build/libs/advancedbackups-corelib.jar + path: core/build/libs/advancedbackups-corelib.jar forge-1-7-10: @@ -42,13 +44,12 @@ jobs: steps: - uses: actions/checkout@v3 - with: - ref: forge-1.7.10 - name: Download corelib uses: actions/download-artifact@v3 with: name: advancedbackups-corelib.jar + path: core/build/libs/advancedbackups-corelib.jar - name: Set up JDK 8 uses: actions/setup-java@v3 @@ -57,7 +58,9 @@ jobs: distribution: 'temurin' - name: Build Mod - run: ./gradlew -Pversion=${{ inputs.version }} build + run: | + cd forge/1.7.10 + ./gradlew -Pversion=${{ inputs.version }} build #run: ls -la advancedbackups-corelib.jar @@ -65,7 +68,7 @@ jobs: uses: actions/upload-artifact@v3 with: name: AdvancedBackups-forge-1.7.10-${{ inputs.version }}.jar - path: build/libs/AdvancedBackups-forge-1.7.10-${{ inputs.version }}.jar + path: forge/1.7.10/build/libs/AdvancedBackups-forge-1.7.10-${{ inputs.version }}.jar forge-1-12-2: @@ -82,6 +85,7 @@ jobs: uses: actions/download-artifact@v3 with: name: advancedbackups-corelib.jar + path: core/build/libs/advancedbackups-corelib.jar - name: Set up JDK 8 uses: actions/setup-java@v3 @@ -115,6 +119,7 @@ jobs: uses: actions/download-artifact@v3 with: name: advancedbackups-corelib.jar + path: core/build/libs/advancedbackups-corelib.jar - name: Set up JDK 8 uses: actions/setup-java@v3 @@ -148,6 +153,7 @@ jobs: uses: actions/download-artifact@v3 with: name: advancedbackups-corelib.jar + path: core/build/libs/advancedbackups-corelib.jar - name: Set up JDK 17 uses: actions/setup-java@v3 @@ -181,6 +187,7 @@ jobs: uses: actions/download-artifact@v3 with: name: advancedbackups-corelib.jar + path: core/build/libs/advancedbackups-corelib.jar - name: Set up JDK 17 uses: actions/setup-java@v3 @@ -214,6 +221,7 @@ jobs: uses: actions/download-artifact@v3 with: name: advancedbackups-corelib.jar + path: core/build/libs/advancedbackups-corelib.jar - name: Set up JDK 17 uses: actions/setup-java@v3 @@ -246,6 +254,7 @@ jobs: uses: actions/download-artifact@v3 with: name: advancedbackups-corelib.jar + path: core/build/libs/advancedbackups-corelib.jar - name: Set up JDK 17 uses: actions/setup-java@v3 @@ -278,6 +287,7 @@ jobs: uses: actions/download-artifact@v3 with: name: advancedbackups-corelib.jar + path: core/build/libs/advancedbackups-corelib.jar - name: Set up JDK 17 uses: actions/setup-java@v3 @@ -310,6 +320,7 @@ jobs: uses: actions/download-artifact@v3 with: name: advancedbackups-corelib.jar + path: core/build/libs/advancedbackups-corelib.jar - name: Set up JDK 17 uses: actions/setup-java@v3 @@ -342,6 +353,7 @@ jobs: uses: actions/download-artifact@v3 with: name: advancedbackups-corelib.jar + path: core/build/libs/advancedbackups-corelib.jar - name: Set up JDK 17 uses: actions/setup-java@v3 @@ -374,6 +386,7 @@ jobs: uses: actions/download-artifact@v3 with: name: advancedbackups-corelib.jar + path: core/build/libs/advancedbackups-corelib.jar - name: Set up JDK 17 uses: actions/setup-java@v3 @@ -406,6 +419,7 @@ jobs: uses: actions/download-artifact@v3 with: name: advancedbackups-corelib.jar + path: core/build/libs/advancedbackups-corelib.jar - name: Set up JDK 17 uses: actions/setup-java@v3 @@ -439,6 +453,7 @@ jobs: uses: actions/download-artifact@v3 with: name: advancedbackups-corelib.jar + path: core/build/libs/advancedbackups-corelib.jar - name: Set up JDK 21 uses: actions/setup-java@v3 @@ -472,6 +487,7 @@ jobs: uses: actions/download-artifact@v3 with: name: advancedbackups-corelib.jar + path: core/build/libs/advancedbackups-corelib.jar - name: Set up JDK 17 uses: actions/setup-java@v3 @@ -505,6 +521,7 @@ jobs: uses: actions/download-artifact@v3 with: name: advancedbackups-corelib.jar + path: core/build/libs/advancedbackups-corelib.jar - name: Set up JDK 17 uses: actions/setup-java@v3 @@ -538,6 +555,7 @@ jobs: uses: actions/download-artifact@v3 with: name: advancedbackups-corelib.jar + path: core/build/libs/advancedbackups-corelib.jar - name: Set up JDK 17 uses: actions/setup-java@v3 @@ -571,6 +589,7 @@ jobs: uses: actions/download-artifact@v3 with: name: advancedbackups-corelib.jar + path: core/build/libs/advancedbackups-corelib.jar - name: Set up JDK 21 uses: actions/setup-java@v3 @@ -604,6 +623,7 @@ jobs: uses: actions/download-artifact@v3 with: name: advancedbackups-corelib.jar + path: core/build/libs/advancedbackups-corelib.jar - name: Set up JDK 21 uses: actions/setup-java@v3 @@ -637,6 +657,7 @@ jobs: uses: actions/download-artifact@v3 with: name: advancedbackups-corelib.jar + path: core/build/libs/advancedbackups-corelib.jar - name: Set up JDK 17 uses: actions/setup-java@v3 @@ -670,6 +691,7 @@ jobs: uses: actions/download-artifact@v3 with: name: advancedbackups-corelib.jar + path: core/build/libs/advancedbackups-corelib.jar - name: Set up JDK 17 uses: actions/setup-java@v3 @@ -704,6 +726,7 @@ jobs: uses: actions/download-artifact@v3 with: name: advancedbackups-corelib.jar + path: core/build/libs/advancedbackups-corelib.jar - name: Set up JDK 21 uses: actions/setup-java@v3 @@ -738,6 +761,7 @@ jobs: uses: actions/download-artifact@v3 with: name: advancedbackups-corelib.jar + path: core/build/libs/advancedbackups-corelib.jar - name: Set up JDK 21 uses: actions/setup-java@v3 @@ -772,6 +796,7 @@ jobs: uses: actions/download-artifact@v3 with: name: advancedbackups-corelib.jar + path: core/build/libs/advancedbackups-corelib.jar - name: Set up JDK 21 uses: actions/setup-java@v3 From c51779671f16f9db0e7d0950e48a948359ba7e12 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+HeatherComputer@users.noreply.github.com> Date: Sat, 2 Nov 2024 13:49:32 +0000 Subject: [PATCH 563/580] TEMPORARY, REMOVE BEFORE MERGING - gotta checkout the right branch --- .github/workflows/build.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 472c80af..c9b2c327 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -18,6 +18,8 @@ jobs: steps: - uses: actions/checkout@v3 + with: + ref: HoldYourWaffle-uberbranch - name: Set up JDK 8 uses: actions/setup-java@v3 @@ -44,6 +46,8 @@ jobs: steps: - uses: actions/checkout@v3 + with: + ref: HoldYourWaffle-uberbranch - name: Download corelib uses: actions/download-artifact@v3 From 5615c58935d293c6b42fe1314b01cab1dae5738e Mon Sep 17 00:00:00 2001 From: Heather White <66441550+HeatherComputer@users.noreply.github.com> Date: Sat, 2 Nov 2024 13:56:36 +0000 Subject: [PATCH 564/580] Core's gradlew script wasn't executable. I hope this isn't required for all of them... --- core/gradlew | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 core/gradlew diff --git a/core/gradlew b/core/gradlew old mode 100644 new mode 100755 From 346da9a632b49d0e637bfef9f5617657340191da Mon Sep 17 00:00:00 2001 From: Heather White <66441550+HeatherComputer@users.noreply.github.com> Date: Sat, 2 Nov 2024 14:01:17 +0000 Subject: [PATCH 565/580] yep, has to be done to them all... --- fabric/1.18/gradlew | 0 fabric/1.19.2/gradlew | 0 fabric/1.19.3/gradlew | 0 fabric/1.20.2/gradlew | 0 fabric/1.20.6/gradlew | 0 fabric/1.20/gradlew | 0 fabric/1.21/gradlew | 0 forge/1.12/gradlew | 0 forge/1.16/gradlew | 0 forge/1.18/gradlew | 0 forge/1.19.2/gradlew | 0 forge/1.19.3/gradlew | 0 forge/1.20.2/gradlew | 0 forge/1.20.6/gradlew | 0 forge/1.20/gradlew | 0 forge/1.7.10/gradlew | 0 neoforge/1.20.2/gradlew | 0 neoforge/1.20.4/gradlew | 0 neoforge/1.20.6/gradlew | 0 neoforge/1.21/gradlew | 0 spigot/1.21/gradlew | 0 21 files changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 fabric/1.18/gradlew mode change 100644 => 100755 fabric/1.19.2/gradlew mode change 100644 => 100755 fabric/1.19.3/gradlew mode change 100644 => 100755 fabric/1.20.2/gradlew mode change 100644 => 100755 fabric/1.20.6/gradlew mode change 100644 => 100755 fabric/1.20/gradlew mode change 100644 => 100755 fabric/1.21/gradlew mode change 100644 => 100755 forge/1.12/gradlew mode change 100644 => 100755 forge/1.16/gradlew mode change 100644 => 100755 forge/1.18/gradlew mode change 100644 => 100755 forge/1.19.2/gradlew mode change 100644 => 100755 forge/1.19.3/gradlew mode change 100644 => 100755 forge/1.20.2/gradlew mode change 100644 => 100755 forge/1.20.6/gradlew mode change 100644 => 100755 forge/1.20/gradlew mode change 100644 => 100755 forge/1.7.10/gradlew mode change 100644 => 100755 neoforge/1.20.2/gradlew mode change 100644 => 100755 neoforge/1.20.4/gradlew mode change 100644 => 100755 neoforge/1.20.6/gradlew mode change 100644 => 100755 neoforge/1.21/gradlew mode change 100644 => 100755 spigot/1.21/gradlew diff --git a/fabric/1.18/gradlew b/fabric/1.18/gradlew old mode 100644 new mode 100755 diff --git a/fabric/1.19.2/gradlew b/fabric/1.19.2/gradlew old mode 100644 new mode 100755 diff --git a/fabric/1.19.3/gradlew b/fabric/1.19.3/gradlew old mode 100644 new mode 100755 diff --git a/fabric/1.20.2/gradlew b/fabric/1.20.2/gradlew old mode 100644 new mode 100755 diff --git a/fabric/1.20.6/gradlew b/fabric/1.20.6/gradlew old mode 100644 new mode 100755 diff --git a/fabric/1.20/gradlew b/fabric/1.20/gradlew old mode 100644 new mode 100755 diff --git a/fabric/1.21/gradlew b/fabric/1.21/gradlew old mode 100644 new mode 100755 diff --git a/forge/1.12/gradlew b/forge/1.12/gradlew old mode 100644 new mode 100755 diff --git a/forge/1.16/gradlew b/forge/1.16/gradlew old mode 100644 new mode 100755 diff --git a/forge/1.18/gradlew b/forge/1.18/gradlew old mode 100644 new mode 100755 diff --git a/forge/1.19.2/gradlew b/forge/1.19.2/gradlew old mode 100644 new mode 100755 diff --git a/forge/1.19.3/gradlew b/forge/1.19.3/gradlew old mode 100644 new mode 100755 diff --git a/forge/1.20.2/gradlew b/forge/1.20.2/gradlew old mode 100644 new mode 100755 diff --git a/forge/1.20.6/gradlew b/forge/1.20.6/gradlew old mode 100644 new mode 100755 diff --git a/forge/1.20/gradlew b/forge/1.20/gradlew old mode 100644 new mode 100755 diff --git a/forge/1.7.10/gradlew b/forge/1.7.10/gradlew old mode 100644 new mode 100755 diff --git a/neoforge/1.20.2/gradlew b/neoforge/1.20.2/gradlew old mode 100644 new mode 100755 diff --git a/neoforge/1.20.4/gradlew b/neoforge/1.20.4/gradlew old mode 100644 new mode 100755 diff --git a/neoforge/1.20.6/gradlew b/neoforge/1.20.6/gradlew old mode 100644 new mode 100755 diff --git a/neoforge/1.21/gradlew b/neoforge/1.21/gradlew old mode 100644 new mode 100755 diff --git a/spigot/1.21/gradlew b/spigot/1.21/gradlew old mode 100644 new mode 100755 From c6fa6c8cb2e0a2083b2c8e957a18865d565896ac Mon Sep 17 00:00:00 2001 From: Heather White <66441550+HeatherComputer@users.noreply.github.com> Date: Thu, 5 Dec 2024 21:23:13 +0000 Subject: [PATCH 566/580] These let forge 1.7.10 resolve the wrapper path. gotta test this with the rest --- forge/1.7.10/build.gradle.kts | 12 +++++++----- .../1.7.10/gradle/wrapper/gradle-wrapper.properties | 2 +- global.properties | 2 +- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/forge/1.7.10/build.gradle.kts b/forge/1.7.10/build.gradle.kts index 075d5166..9ff43297 100644 --- a/forge/1.7.10/build.gradle.kts +++ b/forge/1.7.10/build.gradle.kts @@ -7,8 +7,10 @@ plugins { id("com.gtnewhorizons.retrofuturagradle") version "1.2.5" } -apply from: '../../global.properties' - +apply { + from ("../../global.properties") +} +val abCoreLibPath: String by project //version = "2.0" group = "co.uk.mommyheather.advancedbackups" // http://maven.apache.org/guides/mini/guide-naming-conventions.html //archivesBaseName = "AdvancedBackups-forge-1.7.10" @@ -105,8 +107,8 @@ dependencies { // Adds NotEnoughItems and its dependencies (CCL&CCC) to runClient/runServer runtimeOnlyNonPublishable("com.github.GTNewHorizons:NotEnoughItems:2.3.39-GTNH:dev") - implementation files(abCoreLibPath) - extraLibs files(abCoreLibPath) + implementation (files(abCoreLibPath)) + extraLibs (files(abCoreLibPath)) // Example: grab the ic2 jar from curse maven and deobfuscate // api(rfg.deobf("curse.maven:ic2-242638:2353971")) @@ -135,7 +137,7 @@ publishing { } tasks.withType { - from(zipTree("advancedbackups-corelib.jar")) + from(zipTree(abCoreLibPath)) into("/") duplicatesStrategy = DuplicatesStrategy.EXCLUDE //from(zipTree("dependencies/jna-platform-5.13.0.jar")) diff --git a/forge/1.7.10/gradle/wrapper/gradle-wrapper.properties b/forge/1.7.10/gradle/wrapper/gradle-wrapper.properties index 707e499a..bdc9a83b 100644 --- a/forge/1.7.10/gradle/wrapper/gradle-wrapper.properties +++ b/forge/1.7.10/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.2-bin.zip networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/global.properties b/global.properties index b841890a..d5a4535f 100644 --- a/global.properties +++ b/global.properties @@ -1,3 +1,3 @@ ext { - abCoreLibPath = "$projectDir/../../core/build/libs/advancedbackups-corelib.jar" + abCoreLibPath = "../../core/build/libs/advancedbackups-corelib.jar" } From dc735af2760d37e3a9e3340d30eefc4ef403de95 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+HeatherComputer@users.noreply.github.com> Date: Thu, 5 Dec 2024 21:38:07 +0000 Subject: [PATCH 567/580] This removed line never should've existed, it breaks the jar filename --- forge/1.7.10/settings.gradle.kts | 2 -- 1 file changed, 2 deletions(-) diff --git a/forge/1.7.10/settings.gradle.kts b/forge/1.7.10/settings.gradle.kts index 456eead8..6456ce87 100644 --- a/forge/1.7.10/settings.gradle.kts +++ b/forge/1.7.10/settings.gradle.kts @@ -22,5 +22,3 @@ plugins { // Automatic toolchain provisioning id("org.gradle.toolchains.foojay-resolver-convention") version "0.4.0" } - -rootProject.name = "forge-1.7.10" From 44beef3b5d4b50720259f366460beb88608a1822 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+HeatherComputer@users.noreply.github.com> Date: Thu, 5 Dec 2024 21:51:31 +0000 Subject: [PATCH 568/580] revert prior commit - keeping the rootProject name in line with the others makes sense, so we need a better way to set the output jar name --- forge/1.7.10/settings.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/forge/1.7.10/settings.gradle.kts b/forge/1.7.10/settings.gradle.kts index 6456ce87..0a2a8960 100644 --- a/forge/1.7.10/settings.gradle.kts +++ b/forge/1.7.10/settings.gradle.kts @@ -1,4 +1,4 @@ -rootProject.name = "AdvancedBackups-forge-1.7.10" +rootProject.name = "forge-1.7.10" pluginManagement { repositories { @@ -21,4 +21,4 @@ pluginManagement { plugins { // Automatic toolchain provisioning id("org.gradle.toolchains.foojay-resolver-convention") version "0.4.0" -} +} \ No newline at end of file From 3aa0fd13bb4a9cc26b4dc5b683db5c04fad05820 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+HeatherComputer@users.noreply.github.com> Date: Thu, 5 Dec 2024 21:59:47 +0000 Subject: [PATCH 569/580] aand here's the solution! --- forge/1.7.10/build.gradle.kts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/forge/1.7.10/build.gradle.kts b/forge/1.7.10/build.gradle.kts index 9ff43297..6d360f54 100644 --- a/forge/1.7.10/build.gradle.kts +++ b/forge/1.7.10/build.gradle.kts @@ -149,7 +149,9 @@ tasks.withType { } } - +tasks.jar { + archiveBaseName.set("AdvancedBackups-forge-1.7.10") +} From 9f3e1ee0c973b96230f7d753d466289618c9900d Mon Sep 17 00:00:00 2001 From: Heather White <66441550+HeatherComputer@users.noreply.github.com> Date: Tue, 24 Dec 2024 07:52:26 +0000 Subject: [PATCH 570/580] this was strangely absent from git --- forge/1.7.10/gradlew.bat | 92 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 forge/1.7.10/gradlew.bat diff --git a/forge/1.7.10/gradlew.bat b/forge/1.7.10/gradlew.bat new file mode 100644 index 00000000..93e3f59f --- /dev/null +++ b/forge/1.7.10/gradlew.bat @@ -0,0 +1,92 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega From 013957df663bd5a95778ade6c05bfe93bb750a4f Mon Sep 17 00:00:00 2001 From: Heather White <66441550+HeatherComputer@users.noreply.github.com> Date: Tue, 24 Dec 2024 08:24:35 +0000 Subject: [PATCH 571/580] update workflows... hmm --- .github/workflows/build.yml | 142 ++++++++++++++++++------------------ 1 file changed, 71 insertions(+), 71 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c9b2c327..58b9fdd2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -33,7 +33,7 @@ jobs: ./gradlew shadowJar - name: Upload Core - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: advancedbackups-corelib.jar path: core/build/libs/advancedbackups-corelib.jar @@ -50,7 +50,7 @@ jobs: ref: HoldYourWaffle-uberbranch - name: Download corelib - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: advancedbackups-corelib.jar path: core/build/libs/advancedbackups-corelib.jar @@ -69,7 +69,7 @@ jobs: - name: Upload Mod - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: AdvancedBackups-forge-1.7.10-${{ inputs.version }}.jar path: forge/1.7.10/build/libs/AdvancedBackups-forge-1.7.10-${{ inputs.version }}.jar @@ -86,7 +86,7 @@ jobs: ref: forge-1.12 - name: Download corelib - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: advancedbackups-corelib.jar path: core/build/libs/advancedbackups-corelib.jar @@ -103,7 +103,7 @@ jobs: - name: Upload Mod - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: AdvancedBackups-forge-1.12-${{ inputs.version }}.jar path: build/libs/AdvancedBackups-forge-1.12-${{ inputs.version }}.jar @@ -120,7 +120,7 @@ jobs: ref: forge-1.16 - name: Download corelib - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: advancedbackups-corelib.jar path: core/build/libs/advancedbackups-corelib.jar @@ -137,7 +137,7 @@ jobs: - name: Upload Mod - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: AdvancedBackups-forge-1.16-${{ inputs.version }}.jar path: build/libs/AdvancedBackups-forge-1.16-${{ inputs.version }}.jar @@ -154,7 +154,7 @@ jobs: ref: forge-1.18 - name: Download corelib - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: advancedbackups-corelib.jar path: core/build/libs/advancedbackups-corelib.jar @@ -171,7 +171,7 @@ jobs: - name: Upload Mod - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: AdvancedBackups-forge-1.18-${{ inputs.version }}.jar path: build/libs/AdvancedBackups-forge-1.18-${{ inputs.version }}.jar @@ -188,7 +188,7 @@ jobs: ref: fabric-1.18 - name: Download corelib - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: advancedbackups-corelib.jar path: core/build/libs/advancedbackups-corelib.jar @@ -205,7 +205,7 @@ jobs: - name: Upload Mod - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: AdvancedBackups-fabric-1.18-${{ inputs.version }}.jar path: build/libs/AdvancedBackups-fabric-1.18-${{ inputs.version }}.jar @@ -222,7 +222,7 @@ jobs: ref: forge-1.19.2 - name: Download corelib - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: advancedbackups-corelib.jar path: core/build/libs/advancedbackups-corelib.jar @@ -238,7 +238,7 @@ jobs: - name: Upload Mod - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: AdvancedBackups-forge-1.19.2-${{ inputs.version }}.jar path: build/libs/AdvancedBackups-forge-1.19.2-${{ inputs.version }}.jar @@ -255,7 +255,7 @@ jobs: ref: forge-1.19.3 - name: Download corelib - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: advancedbackups-corelib.jar path: core/build/libs/advancedbackups-corelib.jar @@ -271,7 +271,7 @@ jobs: - name: Upload Mod - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: AdvancedBackups-forge-1.19.3-${{ inputs.version }}.jar path: build/libs/AdvancedBackups-forge-1.19.3-${{ inputs.version }}.jar @@ -288,7 +288,7 @@ jobs: ref: fabric-1.19.2 - name: Download corelib - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: advancedbackups-corelib.jar path: core/build/libs/advancedbackups-corelib.jar @@ -304,7 +304,7 @@ jobs: - name: Upload Mod - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: AdvancedBackups-fabric-1.19.2-${{ inputs.version }}.jar path: build/libs/AdvancedBackups-fabric-1.19.2-${{ inputs.version }}.jar @@ -321,7 +321,7 @@ jobs: ref: fabric-1.19.3 - name: Download corelib - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: advancedbackups-corelib.jar path: core/build/libs/advancedbackups-corelib.jar @@ -337,7 +337,7 @@ jobs: - name: Upload Mod - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: AdvancedBackups-fabric-1.19.3-${{ inputs.version }}.jar path: build/libs/AdvancedBackups-fabric-1.19.3-${{ inputs.version }}.jar @@ -354,7 +354,7 @@ jobs: ref: forge-1.20 - name: Download corelib - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: advancedbackups-corelib.jar path: core/build/libs/advancedbackups-corelib.jar @@ -370,7 +370,7 @@ jobs: - name: Upload Mod - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: AdvancedBackups-forge-1.20-${{ inputs.version }}.jar path: build/libs/AdvancedBackups-forge-1.20-${{ inputs.version }}.jar @@ -387,7 +387,7 @@ jobs: ref: forge-1.20.2 - name: Download corelib - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: advancedbackups-corelib.jar path: core/build/libs/advancedbackups-corelib.jar @@ -403,7 +403,7 @@ jobs: - name: Upload Mod - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: AdvancedBackups-forge-1.20.2-${{ inputs.version }}.jar path: build/libs/AdvancedBackups-forge-1.20.2-${{ inputs.version }}.jar @@ -420,7 +420,7 @@ jobs: ref: forge-1.20.2 - name: Download corelib - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: advancedbackups-corelib.jar path: core/build/libs/advancedbackups-corelib.jar @@ -437,7 +437,7 @@ jobs: - name: Upload Mod - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: AdvancedBackups-forge-1.20.4-${{ inputs.version }}.jar path: build/libs/AdvancedBackups-forge-1.20.4-${{ inputs.version }}.jar @@ -454,7 +454,7 @@ jobs: ref: forge-1.20.6 - name: Download corelib - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: advancedbackups-corelib.jar path: core/build/libs/advancedbackups-corelib.jar @@ -471,7 +471,7 @@ jobs: - name: Upload Mod - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: AdvancedBackups-forge-1.20.6-${{ inputs.version }}.jar path: build/libs/AdvancedBackups-forge-1.20.6-${{ inputs.version }}.jar @@ -488,7 +488,7 @@ jobs: ref: fabric-1.20 - name: Download corelib - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: advancedbackups-corelib.jar path: core/build/libs/advancedbackups-corelib.jar @@ -505,7 +505,7 @@ jobs: - name: Upload Mod - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: AdvancedBackups-fabric-1.20-${{ inputs.version }}.jar path: build/libs/AdvancedBackups-fabric-1.20-${{ inputs.version }}.jar @@ -522,7 +522,7 @@ jobs: ref: fabric-1.20.2 - name: Download corelib - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: advancedbackups-corelib.jar path: core/build/libs/advancedbackups-corelib.jar @@ -539,7 +539,7 @@ jobs: - name: Upload Mod - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: AdvancedBackups-fabric-1.20.2-${{ inputs.version }}.jar path: build/libs/AdvancedBackups-fabric-1.20.2-${{ inputs.version }}.jar @@ -556,7 +556,7 @@ jobs: ref: fabric-1.20.2 - name: Download corelib - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: advancedbackups-corelib.jar path: core/build/libs/advancedbackups-corelib.jar @@ -573,7 +573,7 @@ jobs: - name: Upload Mod - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: AdvancedBackups-fabric-1.20.4-${{ inputs.version }}.jar path: build/libs/AdvancedBackups-fabric-1.20.4-${{ inputs.version }}.jar @@ -590,7 +590,7 @@ jobs: ref: fabric-1.20.6 - name: Download corelib - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: advancedbackups-corelib.jar path: core/build/libs/advancedbackups-corelib.jar @@ -607,7 +607,7 @@ jobs: - name: Upload Mod - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: AdvancedBackups-fabric-1.20.6-${{ inputs.version }}.jar path: build/libs/AdvancedBackups-fabric-1.20.6-${{ inputs.version }}.jar @@ -624,7 +624,7 @@ jobs: ref: fabric-1.21 - name: Download corelib - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: advancedbackups-corelib.jar path: core/build/libs/advancedbackups-corelib.jar @@ -641,7 +641,7 @@ jobs: - name: Upload Mod - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: AdvancedBackups-fabric-1.21-${{ inputs.version }}.jar path: build/libs/AdvancedBackups-fabric-1.21-${{ inputs.version }}.jar @@ -658,7 +658,7 @@ jobs: ref: neoforge-1.20.2 - name: Download corelib - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: advancedbackups-corelib.jar path: core/build/libs/advancedbackups-corelib.jar @@ -675,7 +675,7 @@ jobs: - name: Upload Mod - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: AdvancedBackups-neoforge-1.20.2-${{ inputs.version }}.jar path: build/libs/AdvancedBackups-neoforge-1.20.2-${{ inputs.version }}.jar @@ -692,7 +692,7 @@ jobs: ref: neoforge-1.20.4 - name: Download corelib - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: advancedbackups-corelib.jar path: core/build/libs/advancedbackups-corelib.jar @@ -709,7 +709,7 @@ jobs: - name: Upload Mod - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: AdvancedBackups-neoforge-1.20.4-${{ inputs.version }}.jar path: build/libs/AdvancedBackups-neoforge-1.20.4-${{ inputs.version }}.jar @@ -727,7 +727,7 @@ jobs: ref: neoforge-1.20.6 - name: Download corelib - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: advancedbackups-corelib.jar path: core/build/libs/advancedbackups-corelib.jar @@ -744,7 +744,7 @@ jobs: - name: Upload Mod - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: AdvancedBackups-neoforge-1.20.6-${{ inputs.version }}.jar path: build/libs/AdvancedBackups-neoforge-1.20.6-${{ inputs.version }}.jar @@ -762,7 +762,7 @@ jobs: ref: neoforge-1.21 - name: Download corelib - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: advancedbackups-corelib.jar path: core/build/libs/advancedbackups-corelib.jar @@ -779,7 +779,7 @@ jobs: - name: Upload Mod - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: AdvancedBackups-neoforge-1.21-${{ inputs.version }}.jar path: build/libs/AdvancedBackups-neoforge-1.21-${{ inputs.version }}.jar @@ -797,7 +797,7 @@ jobs: ref: spigot-1.21 - name: Download corelib - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: advancedbackups-corelib.jar path: core/build/libs/advancedbackups-corelib.jar @@ -819,7 +819,7 @@ jobs: - name: Upload Mod - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: AdvancedBackups-spigot-1.21-${{ inputs.version }}.jar path: build/libs/AdvancedBackups-spigot-1.21-${{ inputs.version }}.jar @@ -835,139 +835,139 @@ jobs: - name: Download Forge-1-7-10 - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: AdvancedBackups-forge-1.7.10-${{ inputs.version }}.jar path: archives/ - name: Download Forge-1-12 - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: AdvancedBackups-forge-1.12-${{ inputs.version }}.jar path: archives/ - name: Download Forge-1-16 - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: AdvancedBackups-forge-1.16-${{ inputs.version }}.jar path: archives/ - name: Download Forge-1-18 - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: AdvancedBackups-forge-1.18-${{ inputs.version }}.jar path: archives/ - name: Download Fabric-1-18 - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: AdvancedBackups-fabric-1.18-${{ inputs.version }}.jar path: archives/ - name: Download Forge-1-19-2 - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: AdvancedBackups-forge-1.19.2-${{ inputs.version }}.jar path: archives/ - name: Download Forge-1-19-3 - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: AdvancedBackups-forge-1.19.3-${{ inputs.version }}.jar path: archives/ - name: Download Fabric-1-19-2 - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: AdvancedBackups-fabric-1.19.2-${{ inputs.version }}.jar path: archives/ - name: Download Fabric-1-19-3 - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: AdvancedBackups-fabric-1.19.3-${{ inputs.version }}.jar path: archives/ - name: Download Forge-1-20 - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: AdvancedBackups-forge-1.20-${{ inputs.version }}.jar path: archives/ - name: Download Forge-1-20-2 - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: AdvancedBackups-forge-1.20.2-${{ inputs.version }}.jar path: archives/ - name: Download Fabric-1-20 - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: AdvancedBackups-fabric-1.20-${{ inputs.version }}.jar path: archives/ - name: Download Forge-1-20-4 - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: AdvancedBackups-forge-1.20.4-${{ inputs.version }}.jar path: archives/ - name: Download Forge-1-20-6 - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: AdvancedBackups-forge-1.20.6-${{ inputs.version }}.jar path: archives/ - name: Download Fabric-1-20-2 - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: AdvancedBackups-fabric-1.20.2-${{ inputs.version }}.jar path: archives/ - name: Download Fabric-1-20-4 - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: AdvancedBackups-fabric-1.20.4-${{ inputs.version }}.jar path: archives/ - name: Download Fabric-1-20-6 - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: AdvancedBackups-fabric-1.20.6-${{ inputs.version }}.jar path: archives/ - name: Download Fabric-1-21 - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: AdvancedBackups-fabric-1.21-${{ inputs.version }}.jar path: archives/ - name: Download Neoforge-1-20-2 - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: AdvancedBackups-neoforge-1.20.2-${{ inputs.version }}.jar path: archives/ - name: Download Neoforge-1-20-4 - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: AdvancedBackups-neoforge-1.20.4-${{ inputs.version }}.jar path: archives/ - name: Download Neoforge-1-20-6 - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: AdvancedBackups-neoforge-1.20.6-${{ inputs.version }}.jar path: archives/ - name: Download Neoforge-1-21 - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: AdvancedBackups-neoforge-1.21-${{ inputs.version }}.jar path: archives/ - name: Download Spigot-1-21 - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: AdvancedBackups-spigot-1.21-${{ inputs.version }}.jar path: archives/ @@ -987,7 +987,7 @@ jobs: - name: Upload Archives - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: ${{ steps.bundle.conclusion != 'failure' }} with: name: AdvancedBackups-ALL_JARS-${{ inputs.version }}.zip From de1fb97e22c537157e94a777704ad0ac0338d502 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+HeatherComputer@users.noreply.github.com> Date: Tue, 24 Dec 2024 08:24:58 +0000 Subject: [PATCH 572/580] add debug print --- .github/workflows/build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 58b9fdd2..ebfd4ce5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -63,6 +63,7 @@ jobs: - name: Build Mod run: | + ls core/build/libs cd forge/1.7.10 ./gradlew -Pversion=${{ inputs.version }} build #run: ls -la advancedbackups-corelib.jar From 9529588828f8953d5148ad1419377aee3792fe09 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+HeatherComputer@users.noreply.github.com> Date: Tue, 24 Dec 2024 08:52:22 +0000 Subject: [PATCH 573/580] more testing... --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ebfd4ce5..93633b79 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -63,8 +63,8 @@ jobs: - name: Build Mod run: | - ls core/build/libs cd forge/1.7.10 + ls ../../core/build/libs ./gradlew -Pversion=${{ inputs.version }} build #run: ls -la advancedbackups-corelib.jar From 4a534e616dbe10c332f252fcace1aa7f7df88518 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+HeatherComputer@users.noreply.github.com> Date: Tue, 24 Dec 2024 08:57:18 +0000 Subject: [PATCH 574/580] debug --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 93633b79..4f4ec4ce 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -64,7 +64,7 @@ jobs: - name: Build Mod run: | cd forge/1.7.10 - ls ../../core/build/libs + ls -l ../../core/build/libs ./gradlew -Pversion=${{ inputs.version }} build #run: ls -la advancedbackups-corelib.jar From 73c8caff31e598a8fc4ee5be5a8d7d24714e2472 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+HeatherComputer@users.noreply.github.com> Date: Tue, 24 Dec 2024 09:02:16 +0000 Subject: [PATCH 575/580] is this really it... --- .github/workflows/build.yml | 69 +++++++++++++------------------------ 1 file changed, 23 insertions(+), 46 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4f4ec4ce..3f8a6a0a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -52,8 +52,7 @@ jobs: - name: Download corelib uses: actions/download-artifact@v4 with: - name: advancedbackups-corelib.jar - path: core/build/libs/advancedbackups-corelib.jar +advancedbackups-corelib.jar - name: Set up JDK 8 uses: actions/setup-java@v3 @@ -89,8 +88,7 @@ jobs: - name: Download corelib uses: actions/download-artifact@v4 with: - name: advancedbackups-corelib.jar - path: core/build/libs/advancedbackups-corelib.jar +advancedbackups-corelib.jar - name: Set up JDK 8 uses: actions/setup-java@v3 @@ -123,8 +121,7 @@ jobs: - name: Download corelib uses: actions/download-artifact@v4 with: - name: advancedbackups-corelib.jar - path: core/build/libs/advancedbackups-corelib.jar +advancedbackups-corelib.jar - name: Set up JDK 8 uses: actions/setup-java@v3 @@ -157,8 +154,7 @@ jobs: - name: Download corelib uses: actions/download-artifact@v4 with: - name: advancedbackups-corelib.jar - path: core/build/libs/advancedbackups-corelib.jar +advancedbackups-corelib.jar - name: Set up JDK 17 uses: actions/setup-java@v3 @@ -191,8 +187,7 @@ jobs: - name: Download corelib uses: actions/download-artifact@v4 with: - name: advancedbackups-corelib.jar - path: core/build/libs/advancedbackups-corelib.jar +advancedbackups-corelib.jar - name: Set up JDK 17 uses: actions/setup-java@v3 @@ -225,8 +220,7 @@ jobs: - name: Download corelib uses: actions/download-artifact@v4 with: - name: advancedbackups-corelib.jar - path: core/build/libs/advancedbackups-corelib.jar +advancedbackups-corelib.jar - name: Set up JDK 17 uses: actions/setup-java@v3 @@ -258,8 +252,7 @@ jobs: - name: Download corelib uses: actions/download-artifact@v4 with: - name: advancedbackups-corelib.jar - path: core/build/libs/advancedbackups-corelib.jar +advancedbackups-corelib.jar - name: Set up JDK 17 uses: actions/setup-java@v3 @@ -291,8 +284,7 @@ jobs: - name: Download corelib uses: actions/download-artifact@v4 with: - name: advancedbackups-corelib.jar - path: core/build/libs/advancedbackups-corelib.jar +advancedbackups-corelib.jar - name: Set up JDK 17 uses: actions/setup-java@v3 @@ -324,8 +316,7 @@ jobs: - name: Download corelib uses: actions/download-artifact@v4 with: - name: advancedbackups-corelib.jar - path: core/build/libs/advancedbackups-corelib.jar +advancedbackups-corelib.jar - name: Set up JDK 17 uses: actions/setup-java@v3 @@ -357,8 +348,7 @@ jobs: - name: Download corelib uses: actions/download-artifact@v4 with: - name: advancedbackups-corelib.jar - path: core/build/libs/advancedbackups-corelib.jar +advancedbackups-corelib.jar - name: Set up JDK 17 uses: actions/setup-java@v3 @@ -390,8 +380,7 @@ jobs: - name: Download corelib uses: actions/download-artifact@v4 with: - name: advancedbackups-corelib.jar - path: core/build/libs/advancedbackups-corelib.jar +advancedbackups-corelib.jar - name: Set up JDK 17 uses: actions/setup-java@v3 @@ -423,8 +412,7 @@ jobs: - name: Download corelib uses: actions/download-artifact@v4 with: - name: advancedbackups-corelib.jar - path: core/build/libs/advancedbackups-corelib.jar +advancedbackups-corelib.jar - name: Set up JDK 17 uses: actions/setup-java@v3 @@ -457,8 +445,7 @@ jobs: - name: Download corelib uses: actions/download-artifact@v4 with: - name: advancedbackups-corelib.jar - path: core/build/libs/advancedbackups-corelib.jar +advancedbackups-corelib.jar - name: Set up JDK 21 uses: actions/setup-java@v3 @@ -491,8 +478,7 @@ jobs: - name: Download corelib uses: actions/download-artifact@v4 with: - name: advancedbackups-corelib.jar - path: core/build/libs/advancedbackups-corelib.jar +advancedbackups-corelib.jar - name: Set up JDK 17 uses: actions/setup-java@v3 @@ -525,8 +511,7 @@ jobs: - name: Download corelib uses: actions/download-artifact@v4 with: - name: advancedbackups-corelib.jar - path: core/build/libs/advancedbackups-corelib.jar +advancedbackups-corelib.jar - name: Set up JDK 17 uses: actions/setup-java@v3 @@ -559,8 +544,7 @@ jobs: - name: Download corelib uses: actions/download-artifact@v4 with: - name: advancedbackups-corelib.jar - path: core/build/libs/advancedbackups-corelib.jar +advancedbackups-corelib.jar - name: Set up JDK 17 uses: actions/setup-java@v3 @@ -593,8 +577,7 @@ jobs: - name: Download corelib uses: actions/download-artifact@v4 with: - name: advancedbackups-corelib.jar - path: core/build/libs/advancedbackups-corelib.jar +advancedbackups-corelib.jar - name: Set up JDK 21 uses: actions/setup-java@v3 @@ -627,8 +610,7 @@ jobs: - name: Download corelib uses: actions/download-artifact@v4 with: - name: advancedbackups-corelib.jar - path: core/build/libs/advancedbackups-corelib.jar +advancedbackups-corelib.jar - name: Set up JDK 21 uses: actions/setup-java@v3 @@ -661,8 +643,7 @@ jobs: - name: Download corelib uses: actions/download-artifact@v4 with: - name: advancedbackups-corelib.jar - path: core/build/libs/advancedbackups-corelib.jar +advancedbackups-corelib.jar - name: Set up JDK 17 uses: actions/setup-java@v3 @@ -695,8 +676,7 @@ jobs: - name: Download corelib uses: actions/download-artifact@v4 with: - name: advancedbackups-corelib.jar - path: core/build/libs/advancedbackups-corelib.jar +advancedbackups-corelib.jar - name: Set up JDK 17 uses: actions/setup-java@v3 @@ -730,8 +710,7 @@ jobs: - name: Download corelib uses: actions/download-artifact@v4 with: - name: advancedbackups-corelib.jar - path: core/build/libs/advancedbackups-corelib.jar +advancedbackups-corelib.jar - name: Set up JDK 21 uses: actions/setup-java@v3 @@ -765,8 +744,7 @@ jobs: - name: Download corelib uses: actions/download-artifact@v4 with: - name: advancedbackups-corelib.jar - path: core/build/libs/advancedbackups-corelib.jar +advancedbackups-corelib.jar - name: Set up JDK 21 uses: actions/setup-java@v3 @@ -800,8 +778,7 @@ jobs: - name: Download corelib uses: actions/download-artifact@v4 with: - name: advancedbackups-corelib.jar - path: core/build/libs/advancedbackups-corelib.jar +advancedbackups-corelib.jar - name: Set up JDK 21 uses: actions/setup-java@v3 From d6e8b165260bb78600aba960491c7174e0c065b8 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+HeatherComputer@users.noreply.github.com> Date: Tue, 24 Dec 2024 09:03:35 +0000 Subject: [PATCH 576/580] fix --- .github/workflows/build.yml | 69 ++++++++++++++++++++++++------------- 1 file changed, 46 insertions(+), 23 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3f8a6a0a..1bfb2844 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -52,7 +52,8 @@ jobs: - name: Download corelib uses: actions/download-artifact@v4 with: -advancedbackups-corelib.jar + name: advancedbackups-corelib.jar + path: core/build/libs/ - name: Set up JDK 8 uses: actions/setup-java@v3 @@ -88,7 +89,8 @@ advancedbackups-corelib.jar - name: Download corelib uses: actions/download-artifact@v4 with: -advancedbackups-corelib.jar + name: advancedbackups-corelib.jar + path: core/build/libs/ - name: Set up JDK 8 uses: actions/setup-java@v3 @@ -121,7 +123,8 @@ advancedbackups-corelib.jar - name: Download corelib uses: actions/download-artifact@v4 with: -advancedbackups-corelib.jar + name: advancedbackups-corelib.jar + path: core/build/libs/ - name: Set up JDK 8 uses: actions/setup-java@v3 @@ -154,7 +157,8 @@ advancedbackups-corelib.jar - name: Download corelib uses: actions/download-artifact@v4 with: -advancedbackups-corelib.jar + name: advancedbackups-corelib.jar + path: core/build/libs/ - name: Set up JDK 17 uses: actions/setup-java@v3 @@ -187,7 +191,8 @@ advancedbackups-corelib.jar - name: Download corelib uses: actions/download-artifact@v4 with: -advancedbackups-corelib.jar + name: advancedbackups-corelib.jar + path: core/build/libs/ - name: Set up JDK 17 uses: actions/setup-java@v3 @@ -220,7 +225,8 @@ advancedbackups-corelib.jar - name: Download corelib uses: actions/download-artifact@v4 with: -advancedbackups-corelib.jar + name: advancedbackups-corelib.jar + path: core/build/libs/ - name: Set up JDK 17 uses: actions/setup-java@v3 @@ -252,7 +258,8 @@ advancedbackups-corelib.jar - name: Download corelib uses: actions/download-artifact@v4 with: -advancedbackups-corelib.jar + name: advancedbackups-corelib.jar + path: core/build/libs/ - name: Set up JDK 17 uses: actions/setup-java@v3 @@ -284,7 +291,8 @@ advancedbackups-corelib.jar - name: Download corelib uses: actions/download-artifact@v4 with: -advancedbackups-corelib.jar + name: advancedbackups-corelib.jar + path: core/build/libs/ - name: Set up JDK 17 uses: actions/setup-java@v3 @@ -316,7 +324,8 @@ advancedbackups-corelib.jar - name: Download corelib uses: actions/download-artifact@v4 with: -advancedbackups-corelib.jar + name: advancedbackups-corelib.jar + path: core/build/libs/ - name: Set up JDK 17 uses: actions/setup-java@v3 @@ -348,7 +357,8 @@ advancedbackups-corelib.jar - name: Download corelib uses: actions/download-artifact@v4 with: -advancedbackups-corelib.jar + name: advancedbackups-corelib.jar + path: core/build/libs/ - name: Set up JDK 17 uses: actions/setup-java@v3 @@ -380,7 +390,8 @@ advancedbackups-corelib.jar - name: Download corelib uses: actions/download-artifact@v4 with: -advancedbackups-corelib.jar + name: advancedbackups-corelib.jar + path: core/build/libs/ - name: Set up JDK 17 uses: actions/setup-java@v3 @@ -412,7 +423,8 @@ advancedbackups-corelib.jar - name: Download corelib uses: actions/download-artifact@v4 with: -advancedbackups-corelib.jar + name: advancedbackups-corelib.jar + path: core/build/libs/ - name: Set up JDK 17 uses: actions/setup-java@v3 @@ -445,7 +457,8 @@ advancedbackups-corelib.jar - name: Download corelib uses: actions/download-artifact@v4 with: -advancedbackups-corelib.jar + name: advancedbackups-corelib.jar + path: core/build/libs/ - name: Set up JDK 21 uses: actions/setup-java@v3 @@ -478,7 +491,8 @@ advancedbackups-corelib.jar - name: Download corelib uses: actions/download-artifact@v4 with: -advancedbackups-corelib.jar + name: advancedbackups-corelib.jar + path: core/build/libs/ - name: Set up JDK 17 uses: actions/setup-java@v3 @@ -511,7 +525,8 @@ advancedbackups-corelib.jar - name: Download corelib uses: actions/download-artifact@v4 with: -advancedbackups-corelib.jar + name: advancedbackups-corelib.jar + path: core/build/libs/ - name: Set up JDK 17 uses: actions/setup-java@v3 @@ -544,7 +559,8 @@ advancedbackups-corelib.jar - name: Download corelib uses: actions/download-artifact@v4 with: -advancedbackups-corelib.jar + name: advancedbackups-corelib.jar + path: core/build/libs/ - name: Set up JDK 17 uses: actions/setup-java@v3 @@ -577,7 +593,8 @@ advancedbackups-corelib.jar - name: Download corelib uses: actions/download-artifact@v4 with: -advancedbackups-corelib.jar + name: advancedbackups-corelib.jar + path: core/build/libs/ - name: Set up JDK 21 uses: actions/setup-java@v3 @@ -610,7 +627,8 @@ advancedbackups-corelib.jar - name: Download corelib uses: actions/download-artifact@v4 with: -advancedbackups-corelib.jar + name: advancedbackups-corelib.jar + path: core/build/libs/ - name: Set up JDK 21 uses: actions/setup-java@v3 @@ -643,7 +661,8 @@ advancedbackups-corelib.jar - name: Download corelib uses: actions/download-artifact@v4 with: -advancedbackups-corelib.jar + name: advancedbackups-corelib.jar + path: core/build/libs/ - name: Set up JDK 17 uses: actions/setup-java@v3 @@ -676,7 +695,8 @@ advancedbackups-corelib.jar - name: Download corelib uses: actions/download-artifact@v4 with: -advancedbackups-corelib.jar + name: advancedbackups-corelib.jar + path: core/build/libs/ - name: Set up JDK 17 uses: actions/setup-java@v3 @@ -710,7 +730,8 @@ advancedbackups-corelib.jar - name: Download corelib uses: actions/download-artifact@v4 with: -advancedbackups-corelib.jar + name: advancedbackups-corelib.jar + path: core/build/libs/ - name: Set up JDK 21 uses: actions/setup-java@v3 @@ -744,7 +765,8 @@ advancedbackups-corelib.jar - name: Download corelib uses: actions/download-artifact@v4 with: -advancedbackups-corelib.jar + name: advancedbackups-corelib.jar + path: core/build/libs/ - name: Set up JDK 21 uses: actions/setup-java@v3 @@ -778,7 +800,8 @@ advancedbackups-corelib.jar - name: Download corelib uses: actions/download-artifact@v4 with: -advancedbackups-corelib.jar + name: advancedbackups-corelib.jar + path: core/build/libs/ - name: Set up JDK 21 uses: actions/setup-java@v3 From cfd7d626f1f6a46a52b1398f1e7764a1fd92579f Mon Sep 17 00:00:00 2001 From: Heather White <66441550+HeatherComputer@users.noreply.github.com> Date: Tue, 24 Dec 2024 09:13:28 +0000 Subject: [PATCH 577/580] remove debug. it works... (well, forge 1.7.10 but the rest are easy now) --- .github/workflows/build.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1bfb2844..21ef8fc6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -64,7 +64,6 @@ jobs: - name: Build Mod run: | cd forge/1.7.10 - ls -l ../../core/build/libs ./gradlew -Pversion=${{ inputs.version }} build #run: ls -la advancedbackups-corelib.jar From bec24d9ce9fcb483e5c7860b92f0795b468c214e Mon Sep 17 00:00:00 2001 From: Heather White <66441550+HeatherComputer@users.noreply.github.com> Date: Wed, 25 Dec 2024 00:54:23 +0000 Subject: [PATCH 578/580] should now build ALL versions well --- .github/workflows/build.yml | 44 ++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 21ef8fc6..ae74975e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -106,7 +106,7 @@ jobs: uses: actions/upload-artifact@v4 with: name: AdvancedBackups-forge-1.12-${{ inputs.version }}.jar - path: build/libs/AdvancedBackups-forge-1.12-${{ inputs.version }}.jar + path: forge/1.12/build/libs/AdvancedBackups-forge-1.12-${{ inputs.version }}.jar forge-1-16: @@ -140,7 +140,7 @@ jobs: uses: actions/upload-artifact@v4 with: name: AdvancedBackups-forge-1.16-${{ inputs.version }}.jar - path: build/libs/AdvancedBackups-forge-1.16-${{ inputs.version }}.jar + path: forge/1.16/build/libs/AdvancedBackups-forge-1.16-${{ inputs.version }}.jar forge-1-18: @@ -174,7 +174,7 @@ jobs: uses: actions/upload-artifact@v4 with: name: AdvancedBackups-forge-1.18-${{ inputs.version }}.jar - path: build/libs/AdvancedBackups-forge-1.18-${{ inputs.version }}.jar + path: forge/1.18/build/libs/AdvancedBackups-forge-1.18-${{ inputs.version }}.jar fabric-1-18: @@ -208,7 +208,7 @@ jobs: uses: actions/upload-artifact@v4 with: name: AdvancedBackups-fabric-1.18-${{ inputs.version }}.jar - path: build/libs/AdvancedBackups-fabric-1.18-${{ inputs.version }}.jar + path: fabric/1.18/build/libs/AdvancedBackups-fabric-1.18-${{ inputs.version }}.jar forge-1-19-2: @@ -241,7 +241,7 @@ jobs: uses: actions/upload-artifact@v4 with: name: AdvancedBackups-forge-1.19.2-${{ inputs.version }}.jar - path: build/libs/AdvancedBackups-forge-1.19.2-${{ inputs.version }}.jar + path: forge/1.19.2/build/libs/AdvancedBackups-forge-1.19.2-${{ inputs.version }}.jar forge-1-19-3: @@ -274,7 +274,7 @@ jobs: uses: actions/upload-artifact@v4 with: name: AdvancedBackups-forge-1.19.3-${{ inputs.version }}.jar - path: build/libs/AdvancedBackups-forge-1.19.3-${{ inputs.version }}.jar + path: forge/1.19.3/build/libs/AdvancedBackups-forge-1.19.3-${{ inputs.version }}.jar fabric-1-19-2: @@ -307,7 +307,7 @@ jobs: uses: actions/upload-artifact@v4 with: name: AdvancedBackups-fabric-1.19.2-${{ inputs.version }}.jar - path: build/libs/AdvancedBackups-fabric-1.19.2-${{ inputs.version }}.jar + path: fabric/1.19.2/build/libs/AdvancedBackups-fabric-1.19.2-${{ inputs.version }}.jar fabric-1-19-3: @@ -340,7 +340,7 @@ jobs: uses: actions/upload-artifact@v4 with: name: AdvancedBackups-fabric-1.19.3-${{ inputs.version }}.jar - path: build/libs/AdvancedBackups-fabric-1.19.3-${{ inputs.version }}.jar + path: fabric/1.19.3/build/libs/AdvancedBackups-fabric-1.19.3-${{ inputs.version }}.jar forge-1-20: @@ -373,7 +373,7 @@ jobs: uses: actions/upload-artifact@v4 with: name: AdvancedBackups-forge-1.20-${{ inputs.version }}.jar - path: build/libs/AdvancedBackups-forge-1.20-${{ inputs.version }}.jar + path: forge/1.20/build/libs/AdvancedBackups-forge-1.20-${{ inputs.version }}.jar forge-1-20-2: @@ -406,7 +406,7 @@ jobs: uses: actions/upload-artifact@v4 with: name: AdvancedBackups-forge-1.20.2-${{ inputs.version }}.jar - path: build/libs/AdvancedBackups-forge-1.20.2-${{ inputs.version }}.jar + path: forge/1.20.2/build/libs/AdvancedBackups-forge-1.20.2-${{ inputs.version }}.jar forge-1-20-4: @@ -440,7 +440,7 @@ jobs: uses: actions/upload-artifact@v4 with: name: AdvancedBackups-forge-1.20.4-${{ inputs.version }}.jar - path: build/libs/AdvancedBackups-forge-1.20.4-${{ inputs.version }}.jar + path: forge/1.20.2/build/libs/AdvancedBackups-forge-1.20.4-${{ inputs.version }}.jar forge-1-20-6: @@ -474,7 +474,7 @@ jobs: uses: actions/upload-artifact@v4 with: name: AdvancedBackups-forge-1.20.6-${{ inputs.version }}.jar - path: build/libs/AdvancedBackups-forge-1.20.6-${{ inputs.version }}.jar + path: forge/1.20.6/build/libs/AdvancedBackups-forge-1.20.6-${{ inputs.version }}.jar fabric-1-20: @@ -508,7 +508,7 @@ jobs: uses: actions/upload-artifact@v4 with: name: AdvancedBackups-fabric-1.20-${{ inputs.version }}.jar - path: build/libs/AdvancedBackups-fabric-1.20-${{ inputs.version }}.jar + path: fabric/1.20/build/libs/AdvancedBackups-fabric-1.20-${{ inputs.version }}.jar fabric-1-20-2: @@ -542,7 +542,7 @@ jobs: uses: actions/upload-artifact@v4 with: name: AdvancedBackups-fabric-1.20.2-${{ inputs.version }}.jar - path: build/libs/AdvancedBackups-fabric-1.20.2-${{ inputs.version }}.jar + path: fabric/1.20.2/build/libs/AdvancedBackups-fabric-1.20.2-${{ inputs.version }}.jar fabric-1-20-4: @@ -576,7 +576,7 @@ jobs: uses: actions/upload-artifact@v4 with: name: AdvancedBackups-fabric-1.20.4-${{ inputs.version }}.jar - path: build/libs/AdvancedBackups-fabric-1.20.4-${{ inputs.version }}.jar + path: fabric/1.20.2/build/libs/AdvancedBackups-fabric-1.20.4-${{ inputs.version }}.jar fabric-1-20-6: @@ -610,7 +610,7 @@ jobs: uses: actions/upload-artifact@v4 with: name: AdvancedBackups-fabric-1.20.6-${{ inputs.version }}.jar - path: build/libs/AdvancedBackups-fabric-1.20.6-${{ inputs.version }}.jar + path: fabric/1.20.6/build/libs/AdvancedBackups-fabric-1.20.6-${{ inputs.version }}.jar fabric-1-21: @@ -644,7 +644,7 @@ jobs: uses: actions/upload-artifact@v4 with: name: AdvancedBackups-fabric-1.21-${{ inputs.version }}.jar - path: build/libs/AdvancedBackups-fabric-1.21-${{ inputs.version }}.jar + path: fabric/1.21/build/libs/AdvancedBackups-fabric-1.21-${{ inputs.version }}.jar neoforge-1-20-2: @@ -678,7 +678,7 @@ jobs: uses: actions/upload-artifact@v4 with: name: AdvancedBackups-neoforge-1.20.2-${{ inputs.version }}.jar - path: build/libs/AdvancedBackups-neoforge-1.20.2-${{ inputs.version }}.jar + path: neoforge/1.20.2/build/libs/AdvancedBackups-neoforge-1.20.2-${{ inputs.version }}.jar neoforge-1-20-4: @@ -712,7 +712,7 @@ jobs: uses: actions/upload-artifact@v4 with: name: AdvancedBackups-neoforge-1.20.4-${{ inputs.version }}.jar - path: build/libs/AdvancedBackups-neoforge-1.20.4-${{ inputs.version }}.jar + path: neoforge/1.20.4/build/libs/AdvancedBackups-neoforge-1.20.4-${{ inputs.version }}.jar @@ -747,7 +747,7 @@ jobs: uses: actions/upload-artifact@v4 with: name: AdvancedBackups-neoforge-1.20.6-${{ inputs.version }}.jar - path: build/libs/AdvancedBackups-neoforge-1.20.6-${{ inputs.version }}.jar + path: neoforge/1.20.6/build/libs/AdvancedBackups-neoforge-1.20.6-${{ inputs.version }}.jar @@ -782,7 +782,7 @@ jobs: uses: actions/upload-artifact@v4 with: name: AdvancedBackups-neoforge-1.21-${{ inputs.version }}.jar - path: build/libs/AdvancedBackups-neoforge-1.21-${{ inputs.version }}.jar + path: neoforge/1.21/build/libs/AdvancedBackups-neoforge-1.21-${{ inputs.version }}.jar @@ -822,7 +822,7 @@ jobs: uses: actions/upload-artifact@v4 with: name: AdvancedBackups-spigot-1.21-${{ inputs.version }}.jar - path: build/libs/AdvancedBackups-spigot-1.21-${{ inputs.version }}.jar + path: spigot/1.21/build/libs/AdvancedBackups-spigot-1.21-${{ inputs.version }}.jar bundle-archives: runs-on: ubuntu-latest From 6f2d019a2ed64e7151a4374a725bd0627a0d50e7 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+HeatherComputer@users.noreply.github.com> Date: Wed, 25 Dec 2024 01:12:13 +0000 Subject: [PATCH 579/580] checkout the right branch, heather --- .github/workflows/build.yml | 44 ++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ae74975e..116cc06c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -83,7 +83,7 @@ jobs: - uses: actions/checkout@v3 with: - ref: forge-1.12 + ref: HoldYourWaffle-uberbranch - name: Download corelib uses: actions/download-artifact@v4 @@ -117,7 +117,7 @@ jobs: - uses: actions/checkout@v3 with: - ref: forge-1.16 + ref: HoldYourWaffle-uberbranch - name: Download corelib uses: actions/download-artifact@v4 @@ -151,7 +151,7 @@ jobs: - uses: actions/checkout@v3 with: - ref: forge-1.18 + ref: HoldYourWaffle-uberbranch - name: Download corelib uses: actions/download-artifact@v4 @@ -185,7 +185,7 @@ jobs: - uses: actions/checkout@v3 with: - ref: fabric-1.18 + ref: HoldYourWaffle-uberbranch - name: Download corelib uses: actions/download-artifact@v4 @@ -219,7 +219,7 @@ jobs: - uses: actions/checkout@v3 with: - ref: forge-1.19.2 + ref: HoldYourWaffle-uberbranch - name: Download corelib uses: actions/download-artifact@v4 @@ -252,7 +252,7 @@ jobs: - uses: actions/checkout@v3 with: - ref: forge-1.19.3 + ref: HoldYourWaffle-uberbranch - name: Download corelib uses: actions/download-artifact@v4 @@ -285,7 +285,7 @@ jobs: - uses: actions/checkout@v3 with: - ref: fabric-1.19.2 + ref: HoldYourWaffle-uberbranch - name: Download corelib uses: actions/download-artifact@v4 @@ -318,7 +318,7 @@ jobs: - uses: actions/checkout@v3 with: - ref: fabric-1.19.3 + ref: HoldYourWaffle-uberbranch - name: Download corelib uses: actions/download-artifact@v4 @@ -351,7 +351,7 @@ jobs: - uses: actions/checkout@v3 with: - ref: forge-1.20 + ref: HoldYourWaffle-uberbranch - name: Download corelib uses: actions/download-artifact@v4 @@ -384,7 +384,7 @@ jobs: - uses: actions/checkout@v3 with: - ref: forge-1.20.2 + ref: HoldYourWaffle-uberbranch - name: Download corelib uses: actions/download-artifact@v4 @@ -417,7 +417,7 @@ jobs: - uses: actions/checkout@v3 with: - ref: forge-1.20.2 + ref: HoldYourWaffle-uberbranch - name: Download corelib uses: actions/download-artifact@v4 @@ -451,7 +451,7 @@ jobs: - uses: actions/checkout@v3 with: - ref: forge-1.20.6 + ref: HoldYourWaffle-uberbranch - name: Download corelib uses: actions/download-artifact@v4 @@ -485,7 +485,7 @@ jobs: - uses: actions/checkout@v3 with: - ref: fabric-1.20 + ref: HoldYourWaffle-uberbranch - name: Download corelib uses: actions/download-artifact@v4 @@ -519,7 +519,7 @@ jobs: - uses: actions/checkout@v3 with: - ref: fabric-1.20.2 + ref: HoldYourWaffle-uberbranch - name: Download corelib uses: actions/download-artifact@v4 @@ -553,7 +553,7 @@ jobs: - uses: actions/checkout@v3 with: - ref: fabric-1.20.2 + ref: HoldYourWaffle-uberbranch - name: Download corelib uses: actions/download-artifact@v4 @@ -587,7 +587,7 @@ jobs: - uses: actions/checkout@v3 with: - ref: fabric-1.20.6 + ref: HoldYourWaffle-uberbranch - name: Download corelib uses: actions/download-artifact@v4 @@ -621,7 +621,7 @@ jobs: - uses: actions/checkout@v3 with: - ref: fabric-1.21 + ref: HoldYourWaffle-uberbranch - name: Download corelib uses: actions/download-artifact@v4 @@ -655,7 +655,7 @@ jobs: - uses: actions/checkout@v3 with: - ref: neoforge-1.20.2 + ref: HoldYourWaffle-uberbranch - name: Download corelib uses: actions/download-artifact@v4 @@ -689,7 +689,7 @@ jobs: - uses: actions/checkout@v3 with: - ref: neoforge-1.20.4 + ref: HoldYourWaffle-uberbranch - name: Download corelib uses: actions/download-artifact@v4 @@ -724,7 +724,7 @@ jobs: - uses: actions/checkout@v3 with: - ref: neoforge-1.20.6 + ref: HoldYourWaffle-uberbranch - name: Download corelib uses: actions/download-artifact@v4 @@ -759,7 +759,7 @@ jobs: - uses: actions/checkout@v3 with: - ref: neoforge-1.21 + ref: HoldYourWaffle-uberbranch - name: Download corelib uses: actions/download-artifact@v4 @@ -794,7 +794,7 @@ jobs: - uses: actions/checkout@v3 with: - ref: spigot-1.21 + ref: HoldYourWaffle-uberbranch - name: Download corelib uses: actions/download-artifact@v4 From d4a9532bccbe60efb790ff2550d8721057830c67 Mon Sep 17 00:00:00 2001 From: Heather White <66441550+HeatherComputer@users.noreply.github.com> Date: Wed, 25 Dec 2024 01:31:51 +0000 Subject: [PATCH 580/580] don't forget to cd lol --- .github/workflows/build.yml | 89 +++++++++++++++++++++++++++---------- 1 file changed, 66 insertions(+), 23 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 116cc06c..fecaf346 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -98,7 +98,9 @@ jobs: distribution: 'temurin' - name: Build Mod - run: ./gradlew -Pversion=${{ inputs.version }} build + run: | + cd forge/1.12 + ./gradlew -Pversion=${{ inputs.version }} build #run: ls -la advancedbackups-corelib.jar @@ -132,7 +134,9 @@ jobs: distribution: 'temurin' - name: Build Mod - run: ./gradlew -Pversion=${{ inputs.version }} build + run: | + cd forge/1.16 + ./gradlew -Pversion=${{ inputs.version }} build #run: ls -la advancedbackups-corelib.jar @@ -166,7 +170,9 @@ jobs: distribution: 'temurin' - name: Build Mod - run: ./gradlew -Pversion=${{ inputs.version }} build + run: | + cd forge/1.18 + ./gradlew -Pversion=${{ inputs.version }} build #run: ls -la advancedbackups-corelib.jar @@ -200,7 +206,9 @@ jobs: distribution: 'temurin' - name: Build Mod - run: ./gradlew -Pversion=${{ inputs.version }} build + run: | + cd fabric/1.18 + ./gradlew -Pversion=${{ inputs.version }} build #run: ls -la advancedbackups-corelib.jar @@ -234,7 +242,9 @@ jobs: distribution: 'temurin' - name: Build Mod - run: ./gradlew -Pversion=${{ inputs.version }} build + run: | + cd forge/1.19.2 + ./gradlew -Pversion=${{ inputs.version }} build - name: Upload Mod @@ -267,7 +277,9 @@ jobs: distribution: 'temurin' - name: Build Mod - run: ./gradlew -Pversion=${{ inputs.version }} build + run: | + cd forge/1.19.3 + ./gradlew -Pversion=${{ inputs.version }} build - name: Upload Mod @@ -300,7 +312,9 @@ jobs: distribution: 'temurin' - name: Build Mod - run: ./gradlew -Pversion=${{ inputs.version }} build + run: | + cd fabric/1.19.2 + ./gradlew -Pversion=${{ inputs.version }} build - name: Upload Mod @@ -333,7 +347,9 @@ jobs: distribution: 'temurin' - name: Build Mod - run: ./gradlew -Pversion=${{ inputs.version }} build + run: | + cd fabric/1.19.3 + ./gradlew -Pversion=${{ inputs.version }} build - name: Upload Mod @@ -366,7 +382,9 @@ jobs: distribution: 'temurin' - name: Build Mod - run: ./gradlew -Pversion=${{ inputs.version }} build + run: | + cd forge/1.20 + ./gradlew -Pversion=${{ inputs.version }} build - name: Upload Mod @@ -399,7 +417,9 @@ jobs: distribution: 'temurin' - name: Build Mod - run: ./gradlew -Pversion=${{ inputs.version }} build + run: | + cd forge/1.20.2 + ./gradlew -Pversion=${{ inputs.version }} build - name: Upload Mod @@ -433,7 +453,9 @@ jobs: - name: Build Mod #Here, we have a little override for the minecraft version. Stops us needing a branch whilst still producing a separate jar. - run: ./gradlew -Pversion=${{ inputs.version }} build -PminecraftVersion=1.20.4 -Pminecraft_version=1.20.4 -Pforge_version=49.1.4 -Pmapping_version=1.20.4 build + run: | + cd forge/1.20.2 + ./gradlew -Pversion=${{ inputs.version }} build -PminecraftVersion=1.20.4 -Pminecraft_version=1.20.4 -Pforge_version=49.1.4 -Pmapping_version=1.20.4 build - name: Upload Mod @@ -466,8 +488,9 @@ jobs: distribution: 'temurin' - name: Build Mod - #Here, we have a little override for the minecraft version. Stops us needing a branch whilst still producing a separate jar. - run: ./gradlew -Pversion=${{ inputs.version }} build + run: | + cd forge/1.20.6 + ./gradlew -Pversion=${{ inputs.version }} build - name: Upload Mod @@ -500,7 +523,9 @@ jobs: distribution: 'temurin' - name: Build Mod - run: ./gradlew -Pversion=${{ inputs.version }} build + run: | + cd fabric/1.20 + ./gradlew -Pversion=${{ inputs.version }} build #run: ls -la advancedbackups-corelib.jar @@ -534,7 +559,9 @@ jobs: distribution: 'temurin' - name: Build Mod - run: ./gradlew -Pversion=${{ inputs.version }} build + run: | + cd fabric/1.20.2 + ./gradlew -Pversion=${{ inputs.version }} build #run: ls -la advancedbackups-corelib.jar @@ -569,7 +596,9 @@ jobs: - name: Build Mod #Here, we have a little override for the minecraft version. Stops us needing a branch whilst still producing a separate jar. - run: ./gradlew -Pversion=${{ inputs.version }} -PminecraftVersion=1.20.4 -Pminecraft_version=1.20.4 -Pyarn_mappings=1.20.4+build.3 -Ploader_version=0.16.2 -Pfabric_version-0.97.1+1.20.4 build + run: | + cd fabric/1.20.2 + ./gradlew -Pversion=${{ inputs.version }} -PminecraftVersion=1.20.4 -Pminecraft_version=1.20.4 -Pyarn_mappings=1.20.4+build.3 -Ploader_version=0.16.2 -Pfabric_version-0.97.1+1.20.4 build - name: Upload Mod @@ -602,7 +631,9 @@ jobs: distribution: 'temurin' - name: Build Mod - run: ./gradlew -Pversion=${{ inputs.version }} build + run: | + cd fabric/1.20.6 + ./gradlew -Pversion=${{ inputs.version }} build #run: ls -la advancedbackups-corelib.jar @@ -636,7 +667,9 @@ jobs: distribution: 'temurin' - name: Build Mod - run: ./gradlew -Pversion=${{ inputs.version }} build + run: | + cd fabric/1.21 + ./gradlew -Pversion=${{ inputs.version }} build #run: ls -la advancedbackups-corelib.jar @@ -670,7 +703,9 @@ jobs: distribution: 'temurin' - name: Build Mod - run: ./gradlew -Pversion=${{ inputs.version }} build + run: | + cd neoforge/1.20.2 + ./gradlew -Pversion=${{ inputs.version }} build #run: ls -la advancedbackups-corelib.jar @@ -704,7 +739,9 @@ jobs: distribution: 'temurin' - name: Build Mod - run: ./gradlew -Pversion=${{ inputs.version }} build + run: | + cd neoforge/1.20.4 + ./gradlew -Pversion=${{ inputs.version }} build #run: ls -la advancedbackups-corelib.jar @@ -739,7 +776,9 @@ jobs: distribution: 'temurin' - name: Build Mod - run: ./gradlew -Pversion=${{ inputs.version }} build + run: | + cd neoforge/1.20.6 + ./gradlew -Pversion=${{ inputs.version }} build #run: ls -la advancedbackups-corelib.jar @@ -774,7 +813,9 @@ jobs: distribution: 'temurin' - name: Build Mod - run: ./gradlew -Pversion=${{ inputs.version }} build + run: | + cd neoforge/1.21 + ./gradlew -Pversion=${{ inputs.version }} build #run: ls -la advancedbackups-corelib.jar @@ -814,7 +855,9 @@ jobs: java -jar BuildTools.jar --nogui --rev 1.21.1 --remapped - name: Build Mod - run: ./gradlew -Pversion=${{ inputs.version }} build + run: | + cd spigot/1.21 + ./gradlew -Pversion=${{ inputs.version }} build #run: ls -la advancedbackups-corelib.jar

K7UpUK$>l@ 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 E2O(~oYXATM literal 54413 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 diff --git a/forge/1.16/gradle/wrapper/gradle-wrapper.properties b/forge/1.16/gradle/wrapper/gradle-wrapper.properties index 1c4bcc29..53b9e380 100644 --- a/forge/1.16/gradle/wrapper/gradle-wrapper.properties +++ b/forge/1.16/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.9.4-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/forge/1.16/gradlew b/forge/1.16/gradlew index cccdd3d5..c53aefaa 100644 --- a/forge/1.16/gradlew +++ b/forge/1.16/gradlew @@ -1,78 +1,129 @@ -#!/usr/bin/env sh +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ############################################################################## -## -## Gradle start up script for UN*X -## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# ############################################################################## # Attempt to set APP_HOME + # Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` +APP_BASE_NAME=${0##*/} # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -81,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" + JAVACMD=java which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the @@ -89,84 +140,95 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=$((i+1)) + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=$(save "$@") - -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" - -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" -fi +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' exec "$JAVACMD" "$@" diff --git a/forge/1.16/gradlew.bat b/forge/1.16/gradlew.bat new file mode 100644 index 00000000..107acd32 --- /dev/null +++ b/forge/1.16/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/forge/1.18/gradle/wrapper/gradle-wrapper.jar b/forge/1.18/gradle/wrapper/gradle-wrapper.jar index 249e5832f090a2944b7473328c07c9755baa3196..afba109285af78dbd2a1d187e33ac4f87c76e392 100644 GIT binary patch delta 36621 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%0A;APSd3WM%p;X}YQ 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 O%nF=zbk|6GSN{tyrB9>) delta 35860 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%0A;APSd3WM%p;X}YQ z_l^I}#dN^i^EY{*M9rzRiDU#5HXb)Z8b{}B2E)#MG`cF4@`I><s*TzV;S1HvrWxlyO7oO14DFcLQgh*so92D&+67+aAtniim2ga9rPhDQ zk{QUeGX$XlQb=R}32^3-jQKdXDM+133PbX}J2D_#)W^8m9ZJF7tAc&Ab{ugStrHOnwtx3Fg8i1c|lre!Dq#SVt=9oBWO3ZoP`HZ?ns)JfQp_u z_q22vtfGHIL#?2!v&dv|evtlGrfU#J2_XOD6$k+W!uEd`4@P3>00XB*V~hYrS`2tM zKcK?N7>Y|sqsmV1fHm2|aHzc;OV|1iJV%Y3kKJES$)9BIzt#s~!u`Y+0!~v@_!QE~ z&wh`*b3U^^Tf2aOZ!qV;v{;TRF18BGyJ1O0CB{qb3UoGR!83_^n9ARWp~jxUg>u?g zzZV6&ab66bL>~QT0V$mWzh0?DefaVyW=^N!VLQwUMYW#DP+i!53}v-E{7}Q0`s_Wx zIb9`X5&YM1U-On=N6knhI>l7Avgw@A;mqzzZ(K`?isKWpr3ZC;e3^t`$FNX*C{WTu^$ASE{eH?gvpn`p%of@2g2}xHv<0W7wj2nc~r>oI>8zMLat{$ z1^5|(XXTa#rFA_^E~2Yl&$#!KYZ5X7hCWYGk2~kJEJ~>X_818co+TqE3)B#ueIt5s ze;t-bxL?2#K;lr^dYKoX|8+DDG&>(Rw}j30@&p}ZOQYYMl4ew#vJF-yyBa}ZhoQ80 z=<|1oC3%^S5(%urWvUDGaHt&+AANU->IC+sewp(y<0gButt>@FRA)W~nL3Pl9WS}j zGHOcg_oCMCMeopBU=7+K@gdiiLdok4m!^C+eOu!I*>g}hb`t>fe^J>={R!In4;4FT z5D?-2i%PSE7HloP5j?l!_9=EVx@097T+w^)wGkQ!$Qf-ii5_OMGAC-X@DUUsSI5U# zeWl~ae`0!jVg^!_q@QMLoNOb626Ye*i&GX14`PT+F)7=8oCV#IN_4v-*rRe}wKmv; zwzjOz7Lqei<=pN<)vmftsJ2(rXzRsKPOH`dQ|F!kKjYCdDLV4Y?3(u_=f>|u4{*Zo zWhnIhXad51TuIP!sC0g3_4Epej{EIburEgF=vQ!9|0;cQyUX!uFeL1HM|vnT7*-rDb}4) zmyM(<33E8a9wA}LTX~xS@snxcc%MLZw zbp~xN7Ee_gQ%ry=^w+fitUscP(->$mOqJ%9ZOukDlydd`j$l+&z4Z|T86xt<3OjJZ zl8H*>ws7#fSsG6LG+zF>07S^aT1>8xjw$km)u>hL0$y`Xj<8@%*qt=!p)$tHZO9{D zHWWCCwpFP1%o$iW*c1yXokQI3gXxM&I=-UStwm#oc^m+njrd%*F%OOr$v6{(sXH)D zJWGL6*sJPdd)r!4i&j+R`(9d&q=gR!vFc^Gfc`HQ#mPiIX`O>T+{LxB;J`-M1=P9T za(+l_4R0(m?-AEik18QF7nuJ>8x=b)A3kI={8EMODKq8kd>cDM5PBMB4rfJ@8uT!4 zhxfEIyBQ!muF?cWJSnjZ;hdxw0=AB80aqVi<}#O1nLv`ia**cql({=ZDhFe^HY~D+ zo>;#}eq_`fN?c2djV6cT8s&g4Fd|V$jbE)_w`#&7_*l$Ph=N-2Tn<%KoGj3EWxqEx zQu!e4`<#J4V5WI8p=H`PCR?Yn$7A`g;HN?*}hRffnY)o z-O-1o>}bZ3yXy~HI<#o+_Oe6xp~_S5v?Dwlsaq9ijiv z(h#5oH;bD3$ey6Z3lSNcA zvyzK;odts8GqzbSdorE}&Its4;LOr%rU7(LYZ9{vid6IYOVu(fp|i54we8PqaM>Z2 z;Gm^~$cPqnwk#iOb80p7cvDirC!;8$d85L-h|)L8I}C}>Vz?T)RR0KAf|R?CjP=*9 zTkKJ7+wV9XdB`}7IOOVO}PH@rE74bU%yG)s~s4lRdCtQM8YDH}}qNmsM zI{QSV40o3)C)FBH4cDjC!gr0er*_9+iov9$`InB3e-GKAiE3aqjckbr+oCFZCZ{+eXZ zeT4PaMA~IuPWs<}1+iW-BhDkPk*dC3sNp8k_9;S!8Ukb0kx@6?00T@;g?A0-QIx5o z-iuJStK4&!bW)?_u4GxN2KH@7E^4rN9bWN&U(BrGmuZ5yRq9g3K}=!O2$2BQz96Fm z2eIqKYzUU43)lLBm8y9$RzUa6;{(i{l*uIo=n8cRU6d(@j*ZY-;t z95pgMC)&FGq9!YVyP=^lRXBJCSh}(hqoIcA5V@CkrEP*;Sr)c9H z6yD8nr>M|F(BF(G=hpC{m5LneM^3iI5m^k-3zXYawp@zLKhw(%L-NV~;g?#$G0ggX zw^dJsTAC5#FXtYWh8v@ZBNE{Pq)LkwA(D*I9}*#Gh`&|x*=eGacQzuDbY{7K4@}Pi zkn!NQ^N;NMYYGdW1LFbUViIxR`7jWr`6px?DQ1)p526zjXN0QEeaJX9Qwhf}Cb*ci zQ;y~5+#%CoOZ%CWwrFbadx_SEu)~)fHn>m9Mcwpx+HJly!MXHfm{_?r2M@U=f7QAF zG|pnX&$b{JlHh&9@w~P^BiOZn2B|g_z?InxQHk}GFfWhPFrome+1p2InQ3Y+^-V4; z+)WbId~(`(=T|DOw->zc-?fxamA&gUjF8&g?|IIp5*{I7ZJ}^ZjkJsod3Tq~J~N7E zTf}RyFjjf6riRpc$}1aIMZy5b!I!U)7T%`p7UmanlQE>*>mU9#^TGR;ZrPokT@|Xa zu2!+lww;hdns@*>EdGvv57)WbJh7(O74UV`#uhX#Ly0dklY&imqvVx#o`uDyLwYkj z^yNZ#9$n{fnQ-L-r0m;xPR)ZUP~)+o7i9Y-;13LwC3sUQejBxLx{6*=g5~|Q|0bsQ zY+@z(_*WrTgx=0{>U(7>c(R4ORjJ9Eh^;A<1np*rW~u;Ug>%2K$|4jYRlVL5anI}k zq$-n-@wzi@|Y4`MA}bay!!@R-|;8~|6h z4R%ryUp+-PQF+(BV6xy) z*_gpA-j z5 z^y;xJisDk*8|880MAaWRjvUkb!g(;o}eTMw(dg`AKlJ;`@Z6sqJ@oSX5O>fN;d zVI0vUYg~@l+m3LTruWItnO9P4pVOutd+@uJd<@5THYPMlcLF2d9Od!lnIuZ|n6d#X zYyN(cI>@s${@YO~m`WcilP6&~5z#DRk;<_eJjB=!9eAKMCa(IyOdQ7it8AF7tky>)vpUw66+LJ#Rli7NgnGA*(ixf z?&B-#WZdL*$fQ*9w_mjOsaErp%zFShAI!D!n??hnexx^;wW)HTNZesr4MSO3)Rz=X zlBmc3|O{U45Dpt1Qp=0u$f**Y6a6>|iZ=zTwUab!E%Z$up z)GZnjS*|4RWvij>GifL9Kao~}Sf}O_&5e|4q37p46U%L$H}Kw&8#eCpaVG%HN%3^w zSkjrJihsP|agfhAe;gVjFP^9Mx)(+>N6dXbr~jo2Mw1r;r=RU9pKN5D@c^piAvF)< z1&qLDnMDVp`o{(!IG}Og8cPa8)q13^Ji*}8TNqZ*xkW$$75kK84Edewu+`P)A3* zd1(d+Xn#bpggu|MM;Tmif`HPXGpD;6*w~@|%X}SuJn@KTjm_-9mI&kyaiH|~A~iEZ z^zTXQ)w<7|Ja+{%bnnS*$(=&bPjKLfdFSm2zVG%I zbh@5i4)j0Uq=4~vV?vvr`Y~Pew2H*79L^Euik$YaS#zbPJyvooWMOC&r3{taggGv$ zNOQ;0t1FtmX0;*MmIokA2(u2FW#hyHtXzyIV!D&H(y7yU?=dpM@9(D@@`1p$D5@>S z7IuQ&-CuCVA3r3ZAFt3C3e&jeBfDSSXYl9oGkvjGE?288fU;6bBAoI}d__*W3KNJq zu0bGfP@3IXlvaZSEFo_-FKrqp)wgDBhv04H_#s^>%SEn;3tqpo1oT_40&lKfNdtzh1Blh` z1gzYEyAa*R3$-N}J1L_>{s{1_oY$_jhQsk1LQ`840wy;WpP_}hS2iq;h^?@l`6QmpwIzah%eMB+`l!|IEhl;)+c1LQzwqf`5* zk4&(H+^#0cGfL;Rw214`k2j_41?}fhdv zsm=_i(xjFk%n~<9vic{~b-jG{=FiK{_S)zN3BbRc!39{-_IMk7DXSG^H)v?j$ml#% zT{xjBe%79ZFJ7?BWpkWGYQC4wWs6WNpWYv)ZI13$ ze@hckYdO5tg`QARXZb}flc}SDW5aY zr~zP%;5Ujs?h}VtT?}T4&bP=|6T}Mx&v2^&s3Qqvn$4~|gY*U|4l!5yZ7yxO_RQ2> zwf60eSEjyUa$~9X^#>o?ZCcGe;a8rnM6=KE_VpINx%BY->(>-tPxgJ*q{rFb5EID{ zO3g5OO2|lfM*iFJ|6N*({kNB52T5l5M*uK!w^nyG@w9MtGqD%5wlK4^aAh*HH*s@I zRhRSK62}lk-$=Bl_pb=0vVkS@r_hXC#!?**NjfM~c3uihPH8b=bt!Ap)nOy&C8g*3 zjC@6II0MrLzU_fOf6@qDk2{`YHUEnC+4eojb2ECsxH0+xaVFe7N(@UM5>4KJO57X+~&A#46^X(v)Drirvz_DtT}Rl&i{9d zdrh};0@XXOVu@pTFDBeEQ80tSjmuVQt;LeV@KLDk!08#Pf5HzcQ{$?BJV2G++xZfj zS#mvwV91-qSx@!mNYbr&0G&rnB?<@^xLx&DHA?qW8qa_(?W_>ObWI$Hc{3|?ukIEJ zV46$GzZJZO6sYk@6@NEzXnb`-1r4w4;gsf9mGOQ$6a0Ib$bUSBzhBK$9O6vGmQyWh zGWf;PdnKo$K<3jh`SOXU^hskr{&oj0ydC>|$RTH*UoXz6gX!fL#x6u7sRh{2;E8XS zpDq|@c|v=2MEQe<>^PxYO*&|P+*M`mnYeu>ch_i(XWBm=~$Btu=2))jQmUFwK6KdeGmdz;k9YAP#v!RY&ucAeYzT zu*TU~*phYOxO84>y7q+gNCWW1EQ(V=M|M^jTcc{bogXGosOb)GMO0x47ppC+&!(wt(vg0tHE7i{bG^w97k@Y%6 zHqb3fvWf$@e3z8INEF3G3YF0(vSPAC=|by7vclXwD>TBn=*DKY$^j&UVH9*yAEIgA z+uX=sT;K=8{2Vtr70mEuS+T1!ojxt>lpc8@U-A*8-3k}ZbOa#^)f=27*lH~&&Y;-7 z@$CiWoiZmdVi7nWh?{At6Q6OH|A(t@3eJTG*R5A=+qP}nwr%TcyK39E+g01PZQJJg z_r5!OCYjtPGjHBJO6rMfEaMmMN8XHrX+ep;!W_JAsm7vc!P==Ga+)N3B8`rFuAwEm zH{&h}l^KBb)YY)bY51Qr-qB{dbG5KHCWUV!+~hxTZceB01d?pt;M{j4tm}2A4=^$C zDPjZ+3(7kv-4e~(c?SEIxN%*ABqM7(y9{o@Y2mmjgi+IK6|fa?b)OT>GM@U4rnnhG4tK+iD$f%m|9EyFsGsc0Ew8$(|i645ue~9oh214jbGDq=?h?$gk ztuCiYvcJJi@S=54f-C1V4Y<;*a^z&Len9^Rl};)+!EP+E6M+OLoJ37wPP%r}0KjF* zNs0&;%zM#Z`agrL)gCd}|O7?Ju(0i~=*Y`*y5tJS)%Ta}}i&xLBQ z?Ia>`b>6kmkfIxw#KKE!NCnxW=qfF;+LwuxDW z&*Mph98E-_4*NCuV&l;7iSb;WmRo49l>emd+K*8NR&0s-u4y!~@cT?OpnXF%8(B9eM>$%_MPk~3sXn#GkcZ#mP65_#QCnki+7`s{5nVrXN0Nmm5cb)K z8|XEseLiRogna&FpB5}il@S~PR=UWzpuh~~(^glF(M}&6t)(U^AUEz@6Cr=vQMh)) z^=Z95^iYS!ca;h;jn&t9PvyTVie+#8mQD03P$^&ddS{;I@W`Aqvq#g!@i!42?Sl8o zsvyj|vjdi7T0GHmNnbw#u)ZgsaSHLmML)S+$mGm0NAsS0tXgruBHP(-;h=Q981fys zi9<>0rO14cp38{}C^Hdge$PCul?jVS-*lNuFQiIFd#pVx5EgohZ!lI`?}+7Od0Mbb z2fGgm3O>W^_(3kTvV;xqDPWTPvCk&;iTt5k><~6#ZiGt3+7cvWX#yrIvL$?z6n~Dl z3zL4)i2R15d&6V;5|RWUr9 zXE8%HflO#A*UiFN3a%S)MsXx%+z&Ac9Rz0}j(dnQs}vLO*|kegtEAqwlAQT#ExbS2 z=aE;hH_9^s$^?6`OfaQO4vxx>@)bIB5$;{TOvJ#n=E~GL2O>?eRRTmEOBMFSFHZ?z z1jCrorO~U15So}wD?#?9Cc$Ei6WUV3s9flSs8KRhr{TKMV-`~7k+|Kf;&-LAvi=(S z`jN)Y(AEC$3E>?JPfp1kSKu5L5P_OM zt|#%oYoBNa8*{J?5bFX_2#q)_ft0QB7-FwG6dWsqgi4&gU(KXL5Xvf~Vo8 zYjXCmT4T*T%c$tu?Ob~mkx1u)lUuG@oR;OvfxC%T;slc0h&w4T%b0!bljE&k#fcd9OX+fSm{G)l5MJ*zRDQV5k%#A5|Wzgu>*!U#9O{3f8$Z)P*XA zqWsCniuP&+oMb#imZZmC+nT9C;MVPPjxs&bRE#l&VBt05<{8DB;KOjEbEP`!jl#v6 zZJD0g%zi0PH^?j;YW7p(rEbgR9J-i!Mjf)>Fb-|PVZmE$dV(Lj2(od4t*ADUk4lkZ zHT>2QV8-6$&b2VjB}j!TN-GhR*=HshESsi8qqEZhBA3|tmbX;t!bo-ERkM#K_b}n7 zXQsC_%{iYN{Id#4D=|(Zo0f3VY7iqiE@8JX3a{9mZsB{Hr{g>fBQ6+ZRn)7-=Xu#I zU;fh`Z~9HQUg2&dJP%L?i`a`R`^4?w$Q3;=Z9i`3ltwmlmQ*S!i|RHGW;Ay$Jn7)F zr-p+9cIm2N90neT$oXU|o}>da{qr2vq0h-+7kIWL9N3~pm+6S9z~uC(FOF8FctkSA z8xycTfVItG3LK;s83j!+i~>eI|BB;}LCEjXWe!$0;^6;~(aE~dsYtx>;C?`$OX<0t z4Ntw!;S)X}&L7iZinzH_aKgC_`41Vv_2ydutlu=EuR)_)2TCRUMKlh^ot7`jw|+6oegiA zq7gsQb%`L8WH}W}DhDrNSCpRrLN=W;x;@$c{(#2)<;1mSWR!v+8rCqkgt7fksnv=k z0#_!DU20t~h%LlkE=*rPbtp%9OH{dqxo(9@|2<5Cs!veL@Y4H#{JvrJsvq0`(ar%> zKtM!5Nd;#lfN59F#k(jC>k1&!ZabZEagy!17eElKN7*OG$9uKTcs8I!?Ms;D*ULBfKh=a01`KrfS z2TQgoe$cb`bG-cHgD&r;2zaMn#_0@mU&frnB6hx&17%cQeIij_1!3s-#0cGkQN!*T zm=kJ%+PgU&U8+!OCe^3{aoA>j?<|GaJ7j(8P!?4E(uWLu?U_kE(jPPwv^!}1^8$`{ z+LTLP-Px+4f@P2f?R|)l*%w6;9#wt`-_`H}rDO7Yy(;I%H}r5E9aMdaH9dwQ40oIxwGtWz(w2cbD3+9sUPd zUflyYv;n2yrdp4rnO;E}>dyW?|Bc2vq6aJ`Z~0yPgiwk{WtYrx{KR0;Xnj7ul9%Xl zlv->huFAS9SM7tnlVjX~58BRXadYUPcoS9esIhpo)sMD`U|iT#a{}MKqUh}|Y78tu zJVvvc4wD6rkl71(qtiid3zvDoyk3EW1W5k!d~I#My~O16}Fo`wryeYX|gn|93|CtHG(!8PDQEYyu0b1E`>2$AON56Jij(Ek2<`;j8Uy{W5hwIntGC)Pp$ zPvk&oI|cIgG9E5Fu@g#R9dzhlb5IqNb<~EuvFGEgjBL3Ce~~+USRB0jeLV3don0j6 z;0O{wZ_7q}xX5NW*Gv&1N$&^M36NR2UxOKKaGS;t;{9z!d&9(1j5IS!mTn~j{&5ic zHYe1;J?oYpmPRIYNya-~60B7~+DQ*yWf%&fFPM0$^GggVnrhzVkF1Wz&6?Fy#&Z(U zz)A?P%I#)|%L97|gW4N&2!n;S08^mCT19R8f*?SaG#hdlN*$@i?`d|d56W7q-s?C| zMS&R-|8r6!`N)Mn$c>OQT$STr&{*^(C5ohV?=-G-!u9-^eKVh4&C4*LU(!y7(NuDq z#v9O!2t>t*gJxE^8=lc$@8_ZPq6OyixWjKEYJ1@5lxS|V##(5^7Yurzj-r@Dd>yao1E{ym};f$--w(%qkYB3MPXGsMx*ucMzA2gTKO4v;< z7oZ|wm%34I*r$sirF+Ul=r3VH25Q$d|M8uUACuA@))sI4B;WyvOoOESy&xmkc-~Yxo7+tk_V&p5F z=W|tron70~UaeU*5ouGl#a(!V=uz6wV*O#=t-h!8tr`L3?Qf=+o>HD-@6NPZeQA9t z9`X!b$^YPD&r=P}ovD9Bi?_}uyp0v&Yy2|h2&>5 z%_LzXA%2B+vG&E-joBj2|Hq2?ksJANbYg(mDY5Uv))Uv8fB*dzFoGb=^8^xO{Uq{{ zFoJMDDESK*$6caishH2psECJVVR1c4Z8N|O?=8PC`brnSUGTyF4&@Jy0UummU|{<} zCYXDh{6dTAr4Ai^hl(3htf!QT$Wsp&`?u-ZcP+t#5Xl0G3&L$sEdtNMVm5=1w_^MpnwN z*b#v}0$~8(Hr+A}+Yiz&Ck%s^t9Pt-{}IMqH=9qG2pdn({!eCeM@5#WGpp7t$+-zh zTVIo=ji?D}E;okhhaPf`?kb;EDU$whh26 z0h=dE^Sp!=r)|8JeV_zTc;87}YxZ8gZij&~t-mg2oY{;kFOn=-JyNNMKh@CJK}$hF z7rjg${XU64a&Zhe#!`vdJ6d6@$S`jki=!|dn5Dfe3k@wRSP9;r7Y)pzJTzwDC|Iq|`Rp#TaX4 zqcu2JAwDae@wU&r0AQ$zX)$f&JQyJ#brA?9mEI-VsO_cH4}dOYcvo11H;1klDY}^0 zZ4o^>Uqq2s!*wMWsohRK*U|$)gpr2Is~AutB3@h8U=J@YP`umMYXGX>U|+aGtVjU* zYOZ1T;icL{>0;%KcSf6hhcUzw$$noyQgiJ_Im);fS&S9*inFaYqDV*JQaU9+N6nsE zarrSemoM(8Uw2u@YjMxBf;BJ#sY?5*;p%F*fw_!{#6IuI$HvGo2jvRIVyDlA(NgE{=+<*E8WRw1Z7<9 z;D>hyQFBki$($V4rGkl{%g6`%L*y#;iT=G|%I@Yh!%p@?6aa($PJrS5b^v=;aViR^ zGwf#AlR$lQOitdnOik5U?b&F8M>bZ;nV$~954h-$K_QEyE!K9NR!E3E!rb47IS22v0O88b@Ga-_{ckya(7%~Ra*#A=EEJB*W%S%~sb zT6tyT3=sgL>w$RvH>FI@ud#^>>IsC;kjE^|8hAu;dk$RW;Ia$}D@s~^!O$7Vs=?!| zr5blVyn>m{Ku?fpJeHGz_Zrj)2l8b{?Wzx&3e+`)Ax)X=%Ajs@>xlq?a)x5DCoykX z=eCF*(LZ-;R(yV18z(dmp}aVkRecRFHv>C|Yc>GlQ;8$BGpLYU+%jip>ZjypWyvC5 zEJPqzqR8$uUrB5hR1FloT7zul(3)!@9S2!*lfXicJ8`fx|Ic(NRq~ujnF8CBl3( zbROUlak~1h9Ue&|TFJ`6Y?*SJTeOkJyaOQtVa#PAo1xG*nl8TwzVSIeKgE0wVrW)e zTh>lh?z#z#9a*`iwY;QQJ2TPRO1iRysv@b$&>o*yB0A?kf4`P5wJlM(M<%`0xq z{?TJ1rV8dGM&b~zPXW|@*se?4-%H(;Fe{-T^p*BeOQl;(x*PEQ1|{m-yLJ>+rBgt4 z`4bVa>VU7BTjcC{%?lM&aO7OG@(mqje6ox=fnSg9hqR9pzKI zuXWJOnO<(*E1{ladMer3lux;1bn2_OM)bl&Q3*K9pVu;TA*0EfPOUC%@eQV}pUx>AGZWG}XMd8|D?l@tvTwUj&nPK+Oyqk`wi-oqr9LU4s@OJ?CI28ksBlRU$}|>cO}#OEMYMX0Ks4RO zrSm2OpZLGG7AV558oXeZTKI%8nl-$h!LILKxb*XXz_9Stb^yTt@Li3!FYn;NfvR29 zSzi7^ZD^e$H=}3u>r0e)XaorhuDv6}5e$uob8;p6Eu0?duDQuu)kcZ^1b06eKFO8C z8C?k5c#-v_#!}~F3BM~TA()d$tqT4$<_EeUG3y~ZK~{W92cM}y$`{l<76h*Mz0rKw zY$=MA&F>nXfB{U|k^6T0gGA>3fpxO|}AOGVI-*_xJ684Kvo(-)HVOA$qu`jl6Z&LuzJ zh21iHnr(Q`4kLXQn($C`6DWkJx*Rxhh;OCMqx$EQ$wOMznN-~}ew=G7^im3zFzGjL zmZMV3AXTI1>}O?t{i3g4EiKVM5-nKQmxpy0(h2Up&99NKao-NwZEcp{x~3N*Q~{4$ zI*Cx42?U_Y)DLrYF!aZL@kCL2LYE%hbOlD1?a=BNTp44P{9#xac#PlrRkJR}20z;^ z7FS<1|L|C+Z7xFlM3~ZTv*7xsFuyTQ`HA}3WVfa3Ato*nwF=!rZeuK(cA9q}+voit z;QC>pMkNC0+8=lelaaZHXoIE~K-jGcEa1ugE*I$jD9}$9*1mKDT>s zZ(nzEKW{}4Ks7@EGeR)5_{zLp>3_1qSP^2Q)lErp6OaY~^}$8Vrly`w(Y^L?`((Vm z$sYP6gOgsIGlO=_iJl?R_Fai#o2Ps5U6H-|bcbwhNm4h7P8|9;1DEMf&qQ5;X5C67 zS$F0;UNU4i{W=+Uc3r+cWX7HnWCxxU2qZ*Xlbf&Oo)|lHMR_%n2YkF;8Uvrgo&ZP! z$o;=WzLMeq6#l6{1V&aAq`s;n+FJ}sVFXEcPEZtNzQXw*;nuWl)#=t(t1289q2!FM zE{c4G;%+n(mvA5{vM8&I@}2fDQ?qrp-2#VasqLfeIgr$?|wB{LM&!Qvh z8S;i&Wo8tGP&zR<+OBKrDpb?4FWxRXL{#@-GRsc@*z&5C>g#b*aBE((P;2r+K2byR zaH2EVv-1)faP+jr1*1~DWyW;-BKwOO^FSVA79{jP1zXg&mt;I_+ZSd&;9qv?*@gUd zDjdzVvJD1}9#!AjVVUysllsdmUOAgjjcFj#VOEKrB64MH+WKsNDP*$7tpubBY1JfB zQ^+*{^L!00z;x`S`$@G|6**C)bPS#G$-(3D%xn=P2HE?>XEy!C3$Zzyu_H~Y^rOzo z&0(yYBz4Sebh-Aep>l)DheK_7^{MIzHrFMZD!4Su6?pTo10-Aq*HUFJBpXsqq-`yn zuA|EDcgtyW_O$S$<_9$wPD^WZ@NCBol5fd?U=?J1LK_M>1sP5{M=$<#dvT8!1Z$=h zzA_1g^va}vQroHLVBipnZbQs1H5u|vF+pP&6Kf=|npixgUP2S6r4i$hteaEmMkP?v zJggRdkuq;hL4TMk4RP#M>yffhZBO>S+JySiZPn&N-N82#$h1N#QKOC0`UaH4?WfNG z;<}A!(TCANVUDQ}8>VnnZ?JW(hmFwqBf&wl_jg`9pCCQudophgL3Mjo$UUWdmz-sL zIB%uF5~#i~anx_@$PsQw1$tGg-S4V^lxfPmHK2+vlwb@9lAgg-D5hqExHhN1fQImmy%$X(e zup*_yhAZD>-6-fnRS&0<;EnW}iddaa5IQp+yLEi78i9A>Ez&CF%tjfrx^C`x%k2{K z<^}5P4miygDZ64O< zr!qQ{L(5K8ivW9b8t6(@Uw_5op6cv7bG)VZqzc=`tA-4Fo&|k!Z8RbI)dBnwgXqy0GhY zW0u|k@Ap080tJqNUGW|7E@Ff@w&J4RhSG(d|6X z!LTX(11fK zc9~|O#1dq_f!KA9H$^ad%%dJ{(hn)jx}3`$6T)hcAeMf1>CIQb_A3047qHtJvGU_Y zd!fx6RDdO?$!i4=t`fMKjX*wZW0uf%K|^9ScVa^_Q@X|D4;v2qwx}NptKUs>mvh)T zaH6$yQ^=#4!-o7bv!@-1WP4C|3C71DQqzx2hNO%PpO}@)#wE7D$C>(^>uF9*!4)qi zfAr~4hM{1Try0)w z5C3ym9TyR>=@`WsE{Gt*MGD}0S^?e$>2{hTjt#Dnab_a1SpmSda&>9Kozn5Rn#qT20k-2w!I5zN~q3-Pb&n$Yd91jl64`AF40LT@>%@*QC*i-=MBpKlVog( z>v--4+wq79`$`Ly^Z>Lprw`NBYrkbt;B zk}rWn-4?FdeN!uu)PdH4&O{u>lnN&oOL8c|2OvnpvC7R(t>?UQ-L7YB{}<@+1)|t* z0_ucnmad>kIbKh=D28XoMUN$!UucriZ|UhfipHQ57G%`WF}v$BX{Ch|OOrbnqIc7V zr(g@cdkUwW0Hxm6wO(&+H*3XinSx(y%xJ*&&F-=N%x6SU-bB^qmiF0mhqdxxu^eJO z39!)&gu47Y8W$UE5t6(`7;|BHS%XK-tmc+^;CAY$y^oPT($g z=|9>+Wu!TscjK6SabG6CXeD5hjujMbSt)P6=>xBZTNbqc=C;q(8M|f_egbogsoc!o ziopJ^w3ghjM$um4oKcY6%c$ExOfcyu2oM8N9|eLXh@rRC3R)R~$l(_nx7Vqx(=V09 zZdM;{458f=FpNSrKESTcN*^LaAy+1cC6(J6!Na40b-{2oJ%F&ExCPl z45Bkm)Pl}{Gff|%6PzZ^uE?-u7Z&h-Fv`GSo$#qR(6H<+u*u68i#r!~?XxlKv!Mq2 z&npj`aO9Gj+s9XleODciL9+SpP@^EX5i}d~Mg~5D!0;qGeF|2fe*OU0Tq3*(14ZEK z+SA|*FX3^BiY)ii?j=7xhXVeEtIinMs`>M2oEXyX{|4u98&4SQq5=VhC+(F{0<@rf zb=8&yC>p!QpWI}!T0}4)EH|p=z=f37 zO_dObsfm^IrDOtv2zkQW{ss^i5@*rm3-04di+9ZAMbWUph{ui|AfbaJo zKoD-p--}YL$E%cSY(*}`qLoP%0$s z@iqu-pAc&&q&>b_@-7*ldl+Z^#S}9ezsmC06&puLd$I<*72K*@(O~i#nEkj&Br|*@ zM`&Y84_o4|FM1xG9Id2I34j8>_?nll56X+YBm%5GYZj^=?Fe-M!faA5}Mb*xbX zj9cSSPv`=<%Kd&+VqWJ9%4%luElDWyu`KAzYKP9DZ1QT>(zj)C7m zEr_t2uIDWA#I8s2kipUyDQPEOa$THOebuZbr-mP;R1JegnTll?6`-xw+u`nVSjwW# z#_F)KR`2{+8u~0}VOzf46k1V!PiqpUgvWxMvpn5`Cg-}s7*i_)-5uOL99}XFWH5CU zN5;b=7iDE_vT#v-(-i%ZuGPKB+|eml)u9AuY?ja0&VnR^eJ#tfMb2J55e<`OKX_9a z5`MpuuE;-c*B|=D1<-WOUSC9)DJ$feTAokW+FUU&RlbZ4E-9vH6>!jIoWQ?$jqnN93?^tVR!NNxVNwgEUjWQBD=2<*%?kv39 zV%3<5tt0ZQpJs;J)J2n9mz~sQTf5-hpNqA$*kHc0WL8o+0dVqVR-?_KA|`HDIA_Y=UjYCFYlpt_-|(mJDof^ z76(YQy-vc__Nt*y)s$!`mhxvhjC<%d=yvPL9F5&483axs#2FC#U4$j9dh;Ra2^2XxHw( zS9WpQbMDz91c(1FM#`B*=7_qDy5051h9Y~En9nMFBJgYr6t{I8Hr;+mj>QW@@k2=x|Gz#Qr7yqVHcV1y81Dt`;X zgNCWv{r{+%e~K?!dL&v+*ejG?pf{(}sm@oN{~?fDS2S(t6O#3S*y$;bG6P>hZEimV z|8ZPB`|sn298M1Cm^hD^Mqh-tsbIV3lk9xh=#u3z<7ehVcSBQnijs3jae6(;Ez|Rw zS-@o)DV1swNW-|7>m|y0TgK!AK3RcAxJiHedNr3CZWvs@X)nN-e?aNU_J z!*j$r1{{5qFy-Sd@^itFCtrXL$oPdO;!E#SKl1xaP2z}YcdOixWKQmCP7B3g|Ij|mv z6p&ebYbz$*`(Eu{-7bnHu+XhN&$Ok)IrjMu=U+g-nx}t^ly5eO0cI*qa%T6A z4TE-8ZG!4o6lE_JX>~T|K@JsMB?=Kj|H2kLFc(LoG@8w(NsAzgEmq%5$GM#$czSqEHii^ zU8&qNj`!hdu)_RoX>yPi0Gz{HxJtCy283ZsyJ7=m6^Wwk1)(L}DMV#Fr;{zRIao^i zz!{D;)aVkhXJ3d0Q6H9w1~`jQJlGsAZqZ=d|JgYq8XaoPu(}h2-28*}=iZh4Wlu+s zuc0{ObJNlxTf|W^IMG2A3L`mn!P&vK*HuF5YG`sr$B(ocEE8q~07BJ)6Dr)l$$2a9 z79ej@Hz`CaV`h);Bd$MOzrv8;%9#dmO4J%$7hg92!Zog_lwPu~nhMbJXJ*Hmun2U) ztiP&fdXGzsj}o}ZO@baeOu1KTiT{`}8#C%qgmwObId+s-hzutC?aIHub^Yn) z6qhMIAys6u{wkaS0QS;Ye~M-p9`js(Sbo6=d2&9KPc`1^xO*q+3X0w6id?;u3|8Oa zoQ|@-TB}1OmgKpA^_*V?Tz@EfiywQ3wiiQrOupld9i{!bX9$o5zI3)8Qsr;w0IvR7 z4j|YFy-=-s-8Mriw}F8`szb zlTdZG@@I*mam27=wN_b_ZE0n<#Q2BqrUIc{dkB|KJt3+ss|}H60u62UFK@GndMPgq zbQBrAI?4fw2A)N%QRkc|f$eEjI24_nD(4G0{UtCa1`j!xpI_a2xaJKdnp1tLkC-W` zx|QdtQpZ3&0J`B2@LX-}Uq_HyA`Ef)bs%sFA)ykXLOARhm-bLfo&mN53`!deUpoUW zat?*_8~4FfY*;+_BVW6JrqFypFS4SZGLuKz)?ahB6}3td>*H*HTcw6e;A$}+4t1BU zJg9786#nJlR+Oc##AN4n22}EPx!W&-x--*+q023g0y^!o{lD?7Efgurk%n60n(C|G z+Bf`imu@IJBi)`(c^#;|>8mdTDI_#$Pc2&O4KidmAc2c~@Sq#aH|uTh`!uOOv1438 zh69^d1ZQDiH*@+a$In>=Tv~A1zt7z6vrhBr6L2*yjAhypooje-wx?=2o)>ocMA( zRSo0GIH++F`V~^K+Q}W^lV$t0WmRL$94XOtz-_^1(4r2BhrxP~RE~KZwPK@&d%>W- z#u%DxgNvoydQ>I%jcE^DhH$RciqgO8ab;(B%XQ5oc_$Z_n>Z~mP&Vo;HgXT*8l1%6 z2HuC$wg*U41gpgP2l6F1EOi#*A<+i)`MsD5;sVY;Ck3v;CGYY$-WBXElae(u+U9;! zfapOULpExom$i)9efx=HBsg^!d(uaRpU56(!-4RMYmcN5lhhRE>@jqSGpZsHvC76R z0)fqTX9TzdmmxK6x1Qn9tu;J)L|>kNQW>rw*M-c)4@%+uQhCIs3Wrqz?kWjehI`$T zwJb}IkFJ5<`jQ5HE+8lRq8LTr#6A4r0BC()i_}*Yqjw;1ok;PRvanC7U5TPenwJE1 z{r0%8W3^AqDgEJn8Ot~lfekNBEjbh`ep5|B7E7WW(Wo=z=wu$&^T{VP;%9Q^f8Hn+ z&`Vik$3nLn=gLpvte;ep*ts;+AC_0#tcRHsxA{z-SOoW>U4E*l_v0qQLvcUz0HR+Y zIa?}(caffn$Vz|enhdeCF+v5xH0g>hHnoWdjBL&wSS_8|JANuq?Q z-k@5r6vCzt?CPWb4d;%?+7NSWP6KUNcjbEMv`;IBV4pJ#939svV%->$+#r&?DGFJWD;TY@g5iv{tmYrT72->$}@ zFjju9iLc(+Xb&-2n-VOop}q@h4bQ#;w_H!f^;vE-!MHGo*&x6Q1=`O~0Ln(Y0^=s0 z{1y4BGjP|LkSLG&`zNPNxx9R7ZiGws!SuZT%5BxSQ*6!_sM>Al)|P>P+W|TZK(AJU z*TPSFg+C~6eZ^v|Q9W`T1Dr&2U+~v~RGs%fdYIZpc0lv5jMTNAyr-Fy=j52!M&Q)D zWmzd#c|`}oYl7*FfRovfMF^Vith{n*zexIO08 zE9DG#{4t}g;zs^y=2oh&@GDuuVFi`@BDtWfWdT4+LXZBH{*Xy0@L8mwkM?TJfN%zLC87*P- zH)m+j)Z+kCI6cssx{~LBgAAa3GHC-cqZxBN=+f#P_`VkKd}s1)DbV`$iux}-%;$w| z%+(Y#vn%}Qi0hHWQ$1)K*Sj_kEAnay;#a>6PCwM>AwD-X1Z6ufGlA(i&ni+z3|+a$ zfcX%eD0D07n#dD$00TEVN9$WxA&wQQA`=om zn(S1N0LET>vVB>~QW>ir@QX}fF+l|wdt~a|w`WqZO4?#iEWTpIe_!HB!YpmZsWI-B zDpUMofIV)16Y?d`-y!BAx7+-@HM9xp$k){Y&0Ah+z!2T1FB&KgsIMfq{eK_UA; z=FIWDQ!mhnYyfL33CfT08E|ct{1N<>PsgHyjZFvPnEHF4HZL^h$}w;rm@RWU?+NY? z$AYmi_yma>V9F)7YQBZrC+%b}G*co!%XfwpLNn$9Ss^nSIw%x_Ka4Oa$^y2Ny9Gop zP?~sl_~sXs3ve|Cf_S2tza2Gqnov91<`GQNp^oHVQfR(xvkFjedAlv`Kv$Tj_Utal z=MTHo;CNlEkblwtdlfUa=!jN>pWjRe>Z%>(%ki?<;cp#Dm{k{6!_gP|!_VDKhU^(n z9@bPCBOe?LGVQn2g{Gw>+f`wOAm=h>-%s-r_WiWa53v641%FV$=niQY(DL^{B9ebY zf&c~cU|z!FX+FcJK#oay1-wa%k3sCh(XcIsyuc50#UJd&2ln&$F#VpC@C_w$PNn`# zf$7x>Y;yM8_5<8~*TCreG5-mtxYJ@U5MjDtF1yan z4cjm)f=5A;8_Ez-0VOu#Z`~cU@loFWuW;U?qr~aZ5o^&afDMlD=}INT%6Rlg~rgdrs1LnXVc?ZGZPg zAif5dHSm0_uYQ2W{6@RdFL8Rp4!U+jRdDEoa#+yyWhiZR?pF`Z0OY3`?hq$aHXwM_ z18Q-pyQ)R&#xuG?e~M-4Pw?b&U&|$n1RkF}1d9cKx{@n^Zw5UORp{~a>DRxDV3iO8<2)4&4kWo&7zT@EIL*}HKgTKB_UsbpZ zQ>s3UBqT4(a*%QOd@Nl_^LK;;|N6k|0ia^LmBmpfWXchxR$;O|6hWNH0wlfAjsNb( zoZ72ece=D&lQ_fA1DHPWozdJ?NTZPH^U1CXRMupkuZq}k^X+hp;a3XgEv5G|MjFFL z=jibz@{aDCaAsldy27K9D>y(-$(CTtx}ZO4h2HNoD~nnRVtw&y=lkd&Uccn_0bd8% z^9-fE7A;Lt=LFEFA(Z?-Qoli24O+8W?+(?dt4oOx^GF8R-Ou=R%ariC1R#%Jit$1g zqD8GxY{I*ns&53;iekd{QERa7|8am==WhPq6kbmE_09509wWfLWr^Npe$qig%0%SlGS*9LcB$N%GZrzoISbMkLw9U+bX#eLI9eM_`z0zkL2hZAHW z9;z~@{F;*-zqs_iV(If$Ajdl9?st5nUB!WK;ECD$_CQvFqN5JOE$V2PrJWj3;V6f(2sGy($%5SX~P zMb6*0x9H-sXguw@0L*E0R z=3%{Bh({r05DW~^T%_GxsszyKu(*O0mAD)?5?@x*5u`+Aff46C>kTVI4Q=Iy7Ooyc zuRL*YzRLfbg(T%^rM8%u*zhh{CMEQpr`M(EaQ2b7ACejTaxG_5D>6eN6a)F8lUu!_ z4eWP4Ne^JKSW-l#x9aHFwN_VqRIFgfB|KEM!lfw{&+C@U^DET?V+N27R!_RARIsVO zFR0SftE%|lo@5sQmM-X23Ig8X_dBdlJ8MZ2XX-JKTh>Y~J37M}MzCmJ{ZKUAw>>ag zJ*UTA9T;Xex&>DTxA82zc}f}WpXovrpZBfBiK-s^YuZlqhyB8h&GIscV&Td#o4sjz zToZbv%Z;0+RNNGbKml2Ma%LI&fsjdzVuqT|W)*VT?GcaOT07%u&=e9W!tY1R z{hL9MOyMZ$N0Lz;W;8JnfeBT3A3n{Zl7hOysBk8#Jj3%RF*4molx#>NM#906qGFN@ zC&RyA%|sW|jtG^f7Zq?Gcb%|@5_Ek)ZbQpJB_7TLlTr+2T>#z_v!Om*2;n;DLsot@ zr#!c7gaObem=x3QCS(Mfxw=|BXzNW#C6++~g)*nSrE z#2vYgIOa?!#kr3&Nlc3y@lT*b4y&R57A~bCysmV)5+oYg!#BVibac%^UHwp8oi61W z9=OW(X{Ul3Pk_p^{#V05&;t`8^ftn%_>;glO++X*89%|Z>a%_<`tZIWS{ETw{{PnM zeDh`m$pKKUgP`bo!b{!wPv3YXbW>2aEI+|S{4r2^$pG+iXQ9-0LSS@L47PTDLMjB& zlOQmycs}|u5q`;daIct54nM&W-gpVlKK=OpI@mFOb_`QA{MP_kH@_izNi4P$e!?e& zzxZ7zmMg#iCm6L=Guvwu3J9ng4G4%bX>S@YiSZg9kfPybh<4x41iPKpTG zVVrE{K@_Qkh&)Y!>i#&+ zln80;hAZn}ELlPdWyv~}HA|$dW2da4iAYbD^jz6u?5472kR?kIl0?cj#!h34c|<9{ z{H}SPeqQtZ&Ohg#d*AatXU?2I?z!{5pO2eH#g!xHmA2cNL#D-8f0#1}wWAn>x;$0C zA7;pHlhh5f(0RMy>Xmo4AuvFAlz2j8WD-(jpCk^Co>dSR84o7ZUGjd98KrEc`XWXt zwH!;TnWHbt-Bx|=OY+dRwuh<$b)OF2HaovURH*u->tLpDg7qaSy!h*BDfHl!#Idku zxOD`7=*CZV8FtN7<9b|Q^lI~ePO=>pZ&Ht7WYiExdSsp=RUgrm&mVmTrH^E8walEc zyXZ7C=Iq*Cb0dCGff#NIsCb@GcTa?rr`_ylS7*~yvj&LYZ0(c#YW+hyO=Iv^JnOEy zFPhC}cs|H}w27^09<3sK+y4{~I`{TvF59!~mAK>miZB)*B?BWugQNb%HIzv*dFYnv ztHwJ`y)|j0C3c4@Nv3tghv;7-nhtF(%(}}Kb!iiy%IC+gt1Ks$U9C*7s?kAXhvkS8 z+66AAxX8uvM?=>u7-3tn+R6UvXE`51|D6rWMiCz1vjwmyh3-5z!+PPyUiOqvt6MLB zi8G4(^OOaltdRFCtc2xfEnN$Wy$fL(<;#Gh!vgS;V*5M8P$o2Q;JS|VnZUJ@W3*w_1@#CKl z-S(QTCi~2%Z7-HKayL~PxTJnM^SO`L(@JQNIg?;oKFWw{kTvo=-|F3m?qzd2C4z1( z)^fa(nipco^u;|~>5PGqft|m7$nyv9IlbQ?jE#%1^_Gt}qL5>l$>u)I8(Vcw# zMD^DXJ0H3q8@(;_H2B(VWiRu%#Mri3Y`oJd65({!)2X;G2v=M@lS#H2NIJ&dOtw^f z+33Y*j-{wX=ENr6SPCml8@7%-FliMi<7Y#WOS9@6z>jiDx4Z);uR4S28Cm`0LuhUZ z>&W4kBb74|y(JS~a~50-qzCI!C6IT|6y0vh;j_*S`_x1m*U>$}>xl4M-F4Yo=WTj87?MPcFDLGKv9t_b8707;Be~`tqge*Wp{~) zT@JJ;ybvmXo!l1d_9f8o6^DN%<8(|NXp^txFG}yi*rlcXC_VJ(>*%|lI zXSZ`^b?`j*_mfo;t&j)S!h%fY(>s`L$2Sg1+`RmF)WgV+HdZbZ_Zv83IB%#{5}NX2 zp4+OO>&XR+`kx5u_p#&Wnpxs!ZZ&av3}CfVan;5gm+`5--S0~d78q^muPh2gDr&|q zdl~6SYvyk-Sal6UuIklwgDwg3X&*SNpLFA{ahx_~Gz{uj)kCUSwXkgWE!ay8pNpDA z_OhFJn1pn^x;{BJm!V7{&Nw2ktwst-5`5N|n{PhXSbX?AF4(ulKg;e;Pr-Ubml`$) zY-t!a8$-MMMrFsvl4~>Y6)w4j%zxHr{5tk7|Lh%R`zl0E&6rN9bWr~f1a33Z-hZ=< zci{A*os;3RfW|Vire%Q8k~-vw3+B4o5{@~x@YWzPNN~XR0(Q-UPqwU3bgZa{()uXIG!*R$wZ$+zvK)fvGj}b1NZ!Rxc zz2aXPPbu~yo+cNc*UHf+K`#Kwq?^mRejH@#I4l-@v24BDxZZsQ{=!1$NYFQRonkC!>EmdV$%$X2vUm|-?JEoIB0j8HM`8u!DE4nbEojWrv zkq)H9r+B8KtQhG+$YYIUBSTwFQMH5Qfg z2;*SrA`?wG#-2}fKDiN&?To%!6s{0JIC;(#5KX?H=m->;n3|J}ehkcZmA`+eTpcVT zDL8C1^zClf0g>SY942$)8>?Tog>x%4e8Sim6XN~zSpy>F64n)GmRdZ&X!*A;tL-<#2ua%2#HBnHEQ%HS;CBJ;Ax2r*Rxahp2(8aJ z$#HUH`1MS=WK}eO_hBCm3;M`X#`+2-2b+TxVpF{JZ9g5S7%|*jdd9`t+~J?Hw9r$^ zUiL5pPCUB_;26nN>-S8}y2t#9l_1*C2%e?G+=uK{_#!_10?rb^>$XTb*V@IIS66V{ zSI=?GK`cB(GG~rXt|I{>FI;V-y@`l*8|N-VRx~ACT`K%BWm#T;_G4~zye8FVI=`Z6 zF`XWvneQ#P^kHd9bozD7E^ZeFYK;SglVb>a<~!u!P)W#%{4y_SPsG3ySwLA9B)CYF zhV8I`*(@>;DGk$O1%1ZVVL_~5E*k=rW90|Op|iVeP*W2+goD;3e)=jffOHwA&kdSu z0^kbi6s&}YdiZ$`0G%fIVJiUC6ay;(M)3OrT!8%DvlR_(-&&ztQFX|1=XWWJ9tQg- z&I5a%=mk*nl?0^Uf8zH=s4j|*5CI1!q(J9ML4d}Hng;R{r}ow|DFaYVXrV}JkZFWI z4fI-y3Q0|=08}ecD9=lRosLeE1`3j)LfKQY0F5ad4OE~+g&3!0fPJ&8e@DtwfgluQ zeFdpMPQwrGc@Ba3(>$~Ubewo*x9|C0-WC2=`< z7PVl5Aa#U`4}?KIXoRVY{IIbs>Z$b%esFS88ivcEHiegj0Gc-`_TxfByo;kk0T4u+ z1MI-T4sBK9a_+J{D937qTJ_AKse)3NwMo@HF0mjryZL&49g2Btuu$q@({<149 zqaCV5LDY%@Y^nzWl)$7FII#cxW-q&PzZ6BUzXzw^$%DjYI6$*m-DjYl%?BX}fcCEZ O%nF=zbk|6GSN{tyrB9>) delta 35860 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 yu?e%!_ptzGB|8GrCfu%p?(_ zQccdaaVK$5bz;*rnyK{_SQYM>;aES6Qs^lj9lEs6_J+%nIiuQC*fN;z8md>r_~Mfl zU%p5Dt_YT>gQqfr@`cR!$NWr~+`CZb%dn;WtzrAOI>P_JtsB76PYe*<%H(y>qx-`Kq!X_; z<{RpAqYhE=L1r*M)gNF3B8r(<%8mo*SR2hu zccLRZwGARt)Hlo1euqTyM>^!HK*!Q2P;4UYrysje@;(<|$&%vQekbn|0Ruu_Io(w4#%p6ld2Yp7tlA`Y$cciThP zKzNGIMPXX%&Ud0uQh!uQZz|FB`4KGD?3!ND?wQt6!n*f4EmCoJUh&b?;B{|lxs#F- z31~HQ`SF4x$&v00@(P+j1pAaj5!s`)b2RDBp*PB=2IB>oBF!*6vwr7Dp%zpAx*dPr zb@Zjq^XjN?O4QcZ*O+8>)|HlrR>oD*?WQl5ri3R#2?*W6iJ>>kH%KnnME&TT@ZzrHS$Q%LC?n|e>V+D+8D zYc4)QddFz7I8#}y#Wj6>4P%34dZH~OUDb?uP%-E zwjXM(?Sg~1!|wI(RVuxbu)-rH+O=igSho_pDCw(c6b=P zKk4ATlB?bj9+HHlh<_!&z0rx13K3ZrAR8W)!@Y}o`?a*JJsD+twZIv`W)@Y?Amu_u zz``@-e2X}27$i(2=9rvIu5uTUOVhzwu%mNazS|lZb&PT;XE2|B&W1>=B58#*!~D&) zfVmJGg8UdP*fx(>Cj^?yS^zH#o-$Q-*$SnK(ZVFkw+er=>N^7!)FtP3y~Xxnu^nzY zikgB>Nj0%;WOltWIob|}%lo?_C7<``a5hEkx&1ku$|)i>Rh6@3h*`slY=9U}(Ql_< zaNG*J8vb&@zpdhAvv`?{=zDedJ23TD&Zg__snRAH4eh~^oawdYi6A3w8<Ozh@Kw)#bdktM^GVb zrG08?0bG?|NG+w^&JvD*7LAbjED{_Zkc`3H!My>0u5Q}m!+6VokMLXxl`Mkd=g&Xx z-a>m*#G3SLlhbKB!)tnzfWOBV;u;ftU}S!NdD5+YtOjLg?X}dl>7m^gOpihrf1;PY zvll&>dIuUGs{Qnd- zwIR3oIrct8Va^Tm0t#(bJD7c$Z7DO9*7NnRZorrSm`b`cxz>OIC;jSE3DO8`hX955ui`s%||YQtt2 z5DNA&pG-V+4oI2s*x^>-$6J?p=I>C|9wZF8z;VjR??Icg?1w2v5Me+FgAeGGa8(3S z4vg*$>zC-WIVZtJ7}o9{D-7d>zCe|z#<9>CFve-OPAYsneTb^JH!Enaza#j}^mXy1 z+ULn^10+rWLF6j2>Ya@@Kq?26>AqK{A_| zQKb*~F1>sE*=d?A?W7N2j?L09_7n+HGi{VY;MoTGr_)G9)ot$p!-UY5zZ2Xtbm=t z@dpPSGwgH=QtIcEulQNI>S-#ifbnO5EWkI;$A|pxJd885oM+ zGZ0_0gDvG8q2xebj+fbCHYfAXuZStH2j~|d^sBAzo46(K8n59+T6rzBwK)^rfPT+B zyIFw)9YC-V^rhtK`!3jrhmW-sTmM+tPH+;nwjL#-SjQPUZ53L@A>y*rt(#M(qsiB2 zx6B)dI}6Wlsw%bJ8h|(lhkJVogQZA&n{?Vgs6gNSXzuZpEyu*xySy8ro07QZ7Vk1!3tJphN_5V7qOiyK8p z#@jcDD8nmtYi1^l8ml;AF<#IPK?!pqf9D4moYk>d99Im}Jtwj6c#+A;f)CQ*f-hZ< z=p_T86jog%!p)D&5g9taSwYi&eP z#JuEK%+NULWus;0w32-SYFku#i}d~+{Pkho&^{;RxzP&0!RCm3-9K6`>KZpnzS6?L z^H^V*s!8<>x8bomvD%rh>Zp3>Db%kyin;qtl+jAv8Oo~1g~mqGAC&Qi_wy|xEt2iz zWAJEfTV%cl2Cs<1L&DLRVVH05EDq`pH7Oh7sR`NNkL%wi}8n>IXcO40hp+J+sC!W?!krJf!GJNE8uj zg-y~Ns-<~D?yqbzVRB}G>0A^f0!^N7l=$m0OdZuqAOQqLc zX?AEGr1Ht+inZ-Qiwnl@Z0qukd__a!C*CKuGdy5#nD7VUBM^6OCpxCa2A(X;e0&V4 zM&WR8+wErQ7UIc6LY~Q9x%Sn*Tn>>P`^t&idaOEnOd(Ufw#>NoR^1QdhJ8s`h^|R_ zXX`c5*O~Xdvh%q;7L!_!ohf$NfEBmCde|#uVZvEo>OfEq%+Ns7&_f$OR9xsihRpBb z+cjk8LyDm@U{YN>+r46?nn{7Gh(;WhFw6GAxtcKD+YWV?uge>;+q#Xx4!GpRkVZYu zzsF}1)7$?%s9g9CH=Zs+B%M_)+~*j3L0&Q9u7!|+T`^O{xE6qvAP?XWv9_MrZKdo& z%IyU)$Q95AB4!#hT!_dA>4e@zjOBD*Y=XjtMm)V|+IXzjuM;(l+8aA5#Kaz_$rR6! zj>#&^DidYD$nUY(D$mH`9eb|dtV0b{S>H6FBfq>t5`;OxA4Nn{J(+XihF(stSche7$es&~N$epi&PDM_N`As;*9D^L==2Q7Z2zD+CiU(|+-kL*VG+&9!Yb3LgPy?A zm7Z&^qRG_JIxK7-FBzZI3Q<;{`DIxtc48k> zc|0dmX;Z=W$+)qE)~`yn6MdoJ4co;%!`ddy+FV538Y)j(vg}5*k(WK)KWZ3WaOG!8 z!syGn=s{H$odtpqFrT#JGM*utN7B((abXnpDM6w56nhw}OY}0TiTG1#f*VFZr+^-g zbP10`$LPq_;PvrA1XXlyx2uM^mrjTzX}w{yuLo-cOClE8MMk47T25G8M!9Z5ypOSV zAJUBGEg5L2fY)ZGJb^E34R2zJ?}Vf>{~gB!8=5Z) z9y$>5c)=;o0HeHHSuE4U)#vG&KF|I%-cF6f$~pdYJWk_dD}iOA>iA$O$+4%@>JU08 zS`ep)$XLPJ+n0_i@PkF#ri6T8?ZeAot$6JIYHm&P6EB=BiaNY|aA$W0I+nz*zkz_z zkEru!tj!QUffq%)8y0y`T&`fuus-1p>=^hnBiBqD^hXrPs`PY9tU3m0np~rISY09> z`P3s=-kt_cYcxWd{de@}TwSqg*xVhp;E9zCsnXo6z z?f&Sv^U7n4`xr=mXle94HzOdN!2kB~4=%)u&N!+2;z6UYKUDqi-s6AZ!haB;@&B`? z_TRX0%@suz^TRdCb?!vNJYPY8L_}&07uySH9%W^Tc&1pia6y1q#?*Drf}GjGbPjBS zbOPcUY#*$3sL2x4v_i*Y=N7E$mR}J%|GUI(>WEr+28+V z%v5{#e!UF*6~G&%;l*q*$V?&r$Pp^sE^i-0$+RH3ERUUdQ0>rAq2(2QAbG}$y{de( z>{qD~GGuOk559Y@%$?N^1ApVL_a704>8OD%8Y%8B;FCt%AoPu8*D1 zLB5X>b}Syz81pn;xnB}%0FnwazlWfUV)Z-~rZg6~b z6!9J$EcE&sEbzcy?CI~=boWA&eeIa%z(7SE^qgVLz??1Vbc1*aRvc%Mri)AJaAG!p z$X!_9Ds;Zz)f+;%s&dRcJt2==P{^j3bf0M=nJd&xwUGlUFn?H=2W(*2I2Gdu zv!gYCwM10aeus)`RIZSrCK=&oKaO_Ry~D1B5!y0R=%!i2*KfXGYX&gNv_u+n9wiR5 z*e$Zjju&ODRW3phN925%S(jL+bCHv6rZtc?!*`1TyYXT6%Ju=|X;6D@lq$8T zW{Y|e39ioPez(pBH%k)HzFITXHvnD6hw^lIoUMA;qAJ^CU?top1fo@s7xT13Fvn1H z6JWa-6+FJF#x>~+A;D~;VDs26>^oH0EI`IYT2iagy23?nyJ==i{g4%HrAf1-*v zK1)~@&(KkwR7TL}L(A@C_S0G;-GMDy=MJn2$FP5s<%wC)4jC5PXoxrQBFZ_k0P{{s@sz+gX`-!=T8rcB(=7vW}^K6oLWMmp(rwDh}b zwaGGd>yEy6fHv%jM$yJXo5oMAQ>c9j`**}F?MCry;T@47@r?&sKHgVe$MCqk#Z_3S z1GZI~nOEN*P~+UaFGnj{{Jo@16`(qVNtbU>O0Hf57-P>x8Jikp=`s8xWs^dAJ9lCQ z)GFm+=OV%AMVqVATtN@|vp61VVAHRn87}%PC^RAzJ%JngmZTasWBAWsoAqBU+8L8u z4A&Pe?fmTm0?mK-BL9t+{y7o(7jm+RpOhL9KnY#E&qu^}B6=K_dB}*VlSEiC9fn)+V=J;OnN)Ta5v66ic1rG+dGAJ1 z1%Zb_+!$=tQ~lxQrzv3x#CPb?CekEkA}0MYSgx$Jdd}q8+R=ma$|&1a#)TQ=l$1tQ z=tL9&_^vJ)Pk}EDO-va`UCT1m#Uty1{v^A3P~83_#v^ozH}6*9mIjIr;t3Uv%@VeW zGL6(CwCUp)Jq%G0bIG%?{_*Y#5IHf*5M@wPo6A{$Um++Co$wLC=J1aoG93&T7Ho}P z=mGEPP7GbvoG!uD$k(H3A$Z))+i{Hy?QHdk>3xSBXR0j!11O^mEe9RHmw!pvzv?Ua~2_l2Yh~_!s1qS`|0~0)YsbHSz8!mG)WiJE| z2f($6TQtt6L_f~ApQYQKSb=`053LgrQq7G@98#igV>y#i==-nEjQ!XNu9 z~;mE+gtj4IDDNQJ~JVk5Ux6&LCSFL!y=>79kE9=V}J7tD==Ga+IW zX)r7>VZ9dY=V&}DR))xUoV!u(Z|%3ciQi_2jl}3=$Agc(`RPb z8kEBpvY>1FGQ9W$n>Cq=DIpski};nE)`p3IUw1Oz0|wxll^)4dq3;CCY@RyJgFgc# zKouFh!`?Xuo{IMz^xi-h=StCis_M7yq$u) z?XHvw*HP0VgR+KR6wI)jEMX|ssqYvSf*_3W8zVTQzD?3>H!#>InzpSO)@SC8q*ii- z%%h}_#0{4JG;Jm`4zg};BPTGkYamx$Xo#O~lBirRY)q=5M45n{GCfV7h9qwyu1NxOMoP4)jjZMxmT|IQQh0U7C$EbnMN<3)Kk?fFHYq$d|ICu>KbY_hO zTZM+uKHe(cIZfEqyzyYSUBZa8;Fcut-GN!HSA9ius`ltNebF46ZX_BbZNU}}ZOm{M2&nANL9@0qvih15(|`S~z}m&h!u4x~(%MAO$jHRWNfuxWF#B)E&g3ghSQ9|> z(MFaLQj)NE0lowyjvg8z0#m6FIuKE9lDO~Glg}nSb7`~^&#(Lw{}GVOS>U)m8bF}x zVjbXljBm34Cs-yM6TVusr+3kYFjr28STT3g056y3cH5Tmge~ASxBj z%|yb>$eF;WgrcOZf569sDZOVwoo%8>XO>XQOX1OyN9I-SQgrm;U;+#3OI(zrWyow3 zk==|{lt2xrQ%FIXOTejR>;wv(Pb8u8}BUpx?yd(Abh6? zsoO3VYWkeLnF43&@*#MQ9-i-d0t*xN-UEyNKeyNMHw|A(k(_6QKO=nKMCxD(W(Yop zsRQ)QeL4X3Lxp^L%wzi2-WVSsf61dqliPUM7srDB?Wm6Lzn0&{*}|IsKQW;02(Y&| zaTKv|`U(pSzuvR6Rduu$wzK_W-Y-7>7s?G$)U}&uK;<>vU}^^ns@Z!p+9?St1s)dG zK%y6xkPyyS1$~&6v{kl?Md6gwM|>mt6Upm>oa8RLD^8T{0?HC!Z>;(Bob7el(DV6x zi`I)$&E&ngwFS@bi4^xFLAn`=fzTC;aimE^!cMI2n@Vo%Ae-ne`RF((&5y6xsjjAZ zVguVoQ?Z9uk$2ON;ersE%PU*xGO@T*;j1BO5#TuZKEf(mB7|g7pcEA=nYJ{s3vlbg zd4-DUlD{*6o%Gc^N!Nptgay>j6E5;3psI+C3Q!1ZIbeCubW%w4pq9)MSDyB{HLm|k zxv-{$$A*pS@csolri$Ge<4VZ}e~78JOL-EVyrbxKra^d{?|NnPp86!q>t<&IP07?Z z^>~IK^k#OEKgRH+LjllZXk7iA>2cfH6+(e&9ku5poo~6y{GC5>(bRK7hwjiurqAiZ zg*DmtgY}v83IjE&AbiWgMyFbaRUPZ{lYiz$U^&Zt2YjG<%m((&_JUbZcfJ22(>bi5 z!J?<7AySj0JZ&<-qXX;mcV!f~>G=sB0KnjWca4}vrtunD^1TrpfeS^4dvFr!65knK zZh`d;*VOkPs4*-9kL>$GP0`(M!j~B;#x?Ba~&s6CopvO86oM?-? zOw#dIRc;6A6T?B`Qp%^<U5 z19x(ywSH$_N+Io!6;e?`tWaM$`=Db!gzx|lQ${DG!zb1Zl&|{kX0y6xvO1o z220r<-oaS^^R2pEyY;=Qllqpmue|5yI~D|iI!IGt@iod{Opz@*ml^w2bNs)p`M(Io z|E;;m*Xpjd9l)4G#KaWfV(t8YUn@A;nK^#xgv=LtnArX|vWQVuw3}B${h+frU2>9^ z!l6)!Uo4`5k`<<;E(ido7M6lKTgWezNLq>U*=uz&s=cc$1%>VrAeOoUtA|T6gO4>UNqsdK=NF*8|~*sl&wI=x9-EGiq*aqV!(VVXA57 zw9*o6Ir8Lj1npUXvlevtn(_+^X5rzdR>#(}4YcB9O50q97%rW2me5_L=%ffYPUSRc z!vv?Kv>dH994Qi>U(a<0KF6NH5b16enCp+mw^Hb3Xs1^tThFpz!3QuN#}KBbww`(h z7GO)1olDqy6?T$()R7y%NYx*B0k_2IBiZ14&8|JPFxeMF{vW>HF-Vi3+ZOI=+qP}n zw(+!WcTd~4ZJX1!ZM&y!+uyt=&i!+~d(V%GjH;-NsEEv6nS1TERt|RHh!0>W4+4pp z1-*EzAM~i`+1f(VEHI8So`S`akPfPTfq*`l{Fz`hS%k#JS0cjT2mS0#QLGf=J?1`he3W*;m4)ce8*WFq1sdP=~$5RlH1EdWm|~dCvKOi4*I_96{^95p#B<(n!d?B z=o`0{t+&OMwKcxiBECznJcfH!fL(z3OvmxP#oWd48|mMjpE||zdiTBdWelj8&Qosv zZFp@&UgXuvJw5y=q6*28AtxZzo-UUpkRW%ne+Ylf!V-0+uQXBW=5S1o#6LXNtY5!I z%Rkz#(S8Pjz*P7bqB6L|M#Er{|QLae-Y{KA>`^} z@lPjeX>90X|34S-7}ZVXe{wEei1<{*e8T-Nbj8JmD4iwcE+Hg_zhkPVm#=@b$;)h6 z<<6y`nPa`f3I6`!28d@kdM{uJOgM%`EvlQ5B2bL)Sl=|y@YB3KeOzz=9cUW3clPAU z^sYc}xf9{4Oj?L5MOlYxR{+>w=vJjvbyO5}ptT(o6dR|ygO$)nVCvNGnq(6;bHlBd zl?w-|plD8spjDF03g5ip;W3Z z><0{BCq!Dw;h5~#1BuQilq*TwEu)qy50@+BE4bX28+7erX{BD4H)N+7U`AVEuREE8 z;X?~fyhF-x_sRfHIj~6f(+^@H)D=ngP;mwJjxhQUbUdzk8f94Ab%59-eRIq?ZKrwD z(BFI=)xrUlgu(b|hAysqK<}8bslmNNeD=#JW*}^~Nrswn^xw*nL@Tx!49bfJecV&KC2G4q5a!NSv)06A_5N3Y?veAz;Gv+@U3R% z)~UA8-0LvVE{}8LVDOHzp~2twReqf}ODIyXMM6=W>kL|OHcx9P%+aJGYi_Om)b!xe zF40Vntn0+VP>o<$AtP&JANjXBn7$}C@{+@3I@cqlwR2MdwGhVPxlTIcRVu@Ho-wO` z_~Or~IMG)A_`6-p)KPS@cT9mu9RGA>dVh5wY$NM9-^c@N=hcNaw4ITjm;iWSP^ZX| z)_XpaI61<+La+U&&%2a z0za$)-wZP@mwSELo#3!PGTt$uy0C(nTT@9NX*r3Ctw6J~7A(m#8fE)0RBd`TdKfAT zCf@$MAxjP`O(u9s@c0Fd@|}UQ6qp)O5Q5DPCeE6mSIh|Rj{$cAVIWsA=xPKVKxdhg zLzPZ`3CS+KIO;T}0Ip!fAUaNU>++ZJZRk@I(h<)RsJUhZ&Ru9*!4Ptn;gX^~4E8W^TSR&~3BAZc#HquXn)OW|TJ`CTahk+{qe`5+ixON^zA9IFd8)kc%*!AiLu z>`SFoZ5bW-%7}xZ>gpJcx_hpF$2l+533{gW{a7ce^B9sIdmLrI0)4yivZ^(Vh@-1q zFT!NQK$Iz^xu%|EOK=n>ug;(7J4OnS$;yWmq>A;hsD_0oAbLYhW^1Vdt9>;(JIYjf zdb+&f&D4@4AS?!*XpH>8egQvSVX`36jMd>$+RgI|pEg))^djhGSo&#lhS~9%NuWfX zDDH;3T*GzRT@5=7ibO>N-6_XPBYxno@mD_3I#rDD?iADxX`! zh*v8^i*JEMzyN#bGEBz7;UYXki*Xr(9xXax(_1qVW=Ml)kSuvK$coq2A(5ZGhs_pF z$*w}FbN6+QDseuB9=fdp_MTs)nQf!2SlROQ!gBJBCXD&@-VurqHj0wm@LWX-TDmS= z71M__vAok|@!qgi#H&H%Vg-((ZfxPAL8AI{x|VV!9)ZE}_l>iWk8UPTGHs*?u7RfP z5MC&=c6X;XlUzrz5q?(!eO@~* zoh2I*%J7dF!!_!vXoSIn5o|wj1#_>K*&CIn{qSaRc&iFVxt*^20ngCL;QonIS>I5^ zMw8HXm>W0PGd*}Ko)f|~dDd%;Wu_RWI_d;&2g6R3S63Uzjd7dn%Svu-OKpx*o|N>F zZg=-~qLb~VRLpv`k zWSdfHh@?dp=s_X`{yxOlxE$4iuyS;Z-x!*E6eqmEm*j2bE@=ZI0YZ5%Yj29!5+J$4h{s($nakA`xgbO8w zi=*r}PWz#lTL_DSAu1?f%-2OjD}NHXp4pXOsCW;DS@BC3h-q4_l`<))8WgzkdXg3! zs1WMt32kS2E#L0p_|x+x**TFV=gn`m9BWlzF{b%6j-odf4{7a4y4Uaef@YaeuPhU8 zHBvRqN^;$Jizy+ z=zW{E5<>2gp$pH{M@S*!sJVQU)b*J5*bX4h>5VJve#Q6ga}cQ&iL#=(u+KroWrxa%8&~p{WEUF0il=db;-$=A;&9M{Rq`ouZ5m%BHT6%st%saGsD6)fQgLN}x@d3q>FC;=f%O3Cyg=Ke@Gh`XW za@RajqOE9UB6eE=zhG%|dYS)IW)&y&Id2n7r)6p_)vlRP7NJL(x4UbhlcFXWT8?K=%s7;z?Vjts?y2+r|uk8Wt(DM*73^W%pAkZa1Jd zNoE)8FvQA>Z`eR5Z@Ig6kS5?0h;`Y&OL2D&xnnAUzQz{YSdh0k zB3exx%A2TyI)M*EM6htrxSlep!Kk(P(VP`$p0G~f$smld6W1r_Z+o?=IB@^weq>5VYsYZZR@` z&XJFxd5{|KPZmVOSxc@^%71C@;z}}WhbF9p!%yLj3j%YOlPL5s>7I3vj25 z@xmf=*z%Wb4;Va6SDk9cv|r*lhZ`(y_*M@>q;wrn)oQx%B(2A$9(74>;$zmQ!4fN; z>XurIk-7@wZys<+7XL@0Fhe-f%*=(weaQEdR9Eh6>Kl-EcI({qoZqyzziGwpg-GM#251sK_ z=3|kitS!j%;fpc@oWn65SEL73^N&t>Ix37xgs= zYG%eQDJc|rqHFia0!_sm7`@lvcv)gfy(+KXA@E{3t1DaZ$DijWAcA)E0@X?2ziJ{v z&KOYZ|DdkM{}t+@{@*6ge}m%xfjIxi%qh`=^2Rwz@w0cCvZ&Tc#UmCDbVwABrON^x zEBK43FO@weA8s7zggCOWhMvGGE`baZ62cC)VHyy!5Zbt%ieH+XN|OLbAFPZWyC6)p z4P3%8sq9HdS3=ih^0OOlqTPbKuzQ?lBEI{w^ReUO{V?@`ARsL|S*%yOS=Z%sF)>-y z(LAQdhgAcuF6LQjRYfdbD1g4o%tV4EiK&ElLB&^VZHbrV1K>tHTO{#XTo>)2UMm`2 z^t4s;vnMQgf-njU-RVBRw0P0-m#d-u`(kq7NL&2T)TjI_@iKuPAK-@oH(J8?%(e!0Ir$yG32@CGUPn5w4)+9@8c&pGx z+K3GKESI4*`tYlmMHt@br;jBWTei&(a=iYslc^c#RU3Q&sYp zSG){)V<(g7+8W!Wxeb5zJb4XE{I|&Y4UrFWr%LHkdQ;~XU zgy^dH-Z3lmY+0G~?DrC_S4@=>0oM8Isw%g(id10gWkoz2Q%7W$bFk@mIzTCcIB(K8 zc<5h&ZzCdT=9n-D>&a8vl+=ZF*`uTvQviG_bLde*k>{^)&0o*b05x$MO3gVLUx`xZ z43j+>!u?XV)Yp@MmG%Y`+COH2?nQcMrQ%k~6#O%PeD_WvFO~Kct za4XoCM_X!c5vhRkIdV=xUB3xI2NNStK*8_Zl!cFjOvp-AY=D;5{uXj}GV{LK1~IE2 z|KffUiBaStRr;10R~K2VVtf{TzM7FaPm;Y(zQjILn+tIPSrJh&EMf6evaBKIvi42-WYU9Vhj~3< zZSM-B;E`g_o8_XTM9IzEL=9Lb^SPhe(f(-`Yh=X6O7+6ALXnTcUFpI>ekl6v)ZQeNCg2 z^H|{SKXHU*%nBQ@I3It0m^h+6tvI@FS=MYS$ZpBaG7j#V@P2ZuYySbp@hA# ze(kc;P4i_-_UDP?%<6>%tTRih6VBgScKU^BV6Aoeg6Uh(W^#J^V$Xo^4#Ekp ztqQVK^g9gKMTHvV7nb64UU7p~!B?>Y0oFH5T7#BSW#YfSB@5PtE~#SCCg3p^o=NkMk$<8- z6PT*yIKGrvne7+y3}_!AC8NNeI?iTY(&nakN>>U-zT0wzZf-RuyZk^X9H-DT_*wk= z;&0}6LsGtfVa1q)CEUPlx#(ED@-?H<1_FrHU#z5^P3lEB|qsxEyn%FOpjx z3S?~gvoXy~L(Q{Jh6*i~=f%9kM1>RGjBzQh_SaIDfSU_9!<>*Pm>l)cJD@wlyxpBV z4Fmhc2q=R_wHCEK69<*wG%}mgD1=FHi4h!98B-*vMu4ZGW~%IrYSLGU{^TuseqVgV zLP<%wirIL`VLyJv9XG_p8w@Q4HzNt-o;U@Au{7%Ji;53!7V8Rv0^Lu^Vf*sL>R(;c zQG_ZuFl)Mh-xEIkGu}?_(HwkB2jS;HdPLSxVU&Jxy9*XRG~^HY(f0g8Q}iqnVmgjI zfd=``2&8GsycjR?M%(zMjn;tn9agcq;&rR!Hp z$B*gzHsQ~aXw8c|a(L^LW(|`yGc!qOnV(ZjU_Q-4z1&0;jG&vAKuNG=F|H?@m5^N@ zq{E!1n;)kNTJ>|Hb2ODt-7U~-MOIFo%9I)_@7fnX+eMMNh>)V$IXesJpBn|uo8f~#aOFytCT zf9&%MCLf8mp4kwHTcojWmM3LU=#|{3L>E}SKwOd?%{HogCZ_Z1BSA}P#O(%H$;z7XyJ^sjGX;j5 zrzp>|Ud;*&VAU3x#f{CKwY7Vc{%TKKqmB@oTHA9;>?!nvMA;8+Jh=cambHz#J18x~ zs!dF>$*AnsQ{{82r5Aw&^7eRCdvcgyxH?*DV5(I$qXh^zS>us*I66_MbL8y4d3ULj z{S(ipo+T3Ag!+5`NU2sc+@*m{_X|&p#O-SAqF&g_n7ObB82~$p%fXA5GLHMC+#qqL zdt`sJC&6C2)=juQ_!NeD>U8lDVpAOkW*khf7MCcs$A(wiIl#B9HM%~GtQ^}yBPjT@ z+E=|A!Z?A(rwzZ;T}o6pOVqHzTr*i;Wrc%&36kc@jXq~+w8kVrs;%=IFdACoLAcCAmhFNpbP8;s`zG|HC2Gv?I~w4ITy=g$`0qMQdkijLSOtX6xW%Z9Nw<;M- zMN`c7=$QxN00DiSjbVt9Mi6-pjv*j(_8PyV-il8Q-&TwBwH1gz1uoxs6~uU}PrgWB zIAE_I-a1EqlIaGQNbcp@iI8W1sm9fBBNOk(k&iLBe%MCo#?xI$%ZmGA?=)M9D=0t7 zc)Q0LnI)kCy{`jCGy9lYX%mUsDWwsY`;jE(;Us@gmWPqjmXL+Hu#^;k%eT>{nMtzj zsV`Iy6leTA8-PndszF;N^X@CJrTw5IIm!GPeu)H2#FQitR{1p;MasQVAG3*+=9FYK zw*k!HT(YQorfQj+1*mCV458(T5=fH`um$gS38hw(OqVMyunQ;rW5aPbF##A3fGH6h z@W)i9Uff?qz`YbK4c}JzQpuxuE3pcQO)%xBRZp{zJ^-*|oryTxJ-rR+MXJ)!f=+pp z10H|DdGd2exhi+hftcYbM0_}C0ZI-2vh+$fU1acsB-YXid7O|=9L!3e@$H*6?G*Zp z%qFB(sgl=FcC=E4CYGp4CN>=M8#5r!RU!u+FJVlH6=gI5xHVD&k;Ta*M28BsxfMV~ zLz+@6TxnfLhF@5=yQo^1&S}cmTN@m!7*c6z;}~*!hNBjuE>NLVl2EwN!F+)0$R1S! zR|lF%n!9fkZ@gPW|x|B={V6x3`=jS*$Pu0+5OWf?wnIy>Y1MbbGSncpKO0qE(qO=ts z!~@&!N`10S593pVQu4FzpOh!tvg}p%zCU(aV5=~K#bKi zHdJ1>tQSrhW%KOky;iW+O_n;`l9~omqM%sdxdLtI`TrJzN6BQz+7xOl*rM>xVI2~# z)7FJ^Dc{DC<%~VS?@WXzuOG$YPLC;>#vUJ^MmtbSL`_yXtNKa$Hk+l-c!aC7gn(Cg ze?YPYZ(2Jw{SF6MiO5(%_pTo7j@&DHNW`|lD`~{iH+_eSTS&OC*2WTT*a`?|9w1dh zh1nh@$a}T#WE5$7Od~NvSEU)T(W$p$s5fe^GpG+7fdJ9=enRT9$wEk+ZaB>G3$KQO zgq?-rZZnIv!p#>Ty~}c*Lb_jxJg$eGM*XwHUwuQ|o^}b3^T6Bxx{!?va8aC@-xK*H ztJBFvFfsSWu89%@b^l3-B~O!CXs)I6Y}y#0C0U0R0WG zybjroj$io0j}3%P7zADXOwHwafT#uu*zfM!oD$6aJx7+WL%t-@6^rD_a_M?S^>c;z zMK580bZXo1f*L$CuMeM4Mp!;P@}b~$cd(s5*q~FP+NHSq;nw3fbWyH)i2)-;gQl{S zZO!T}A}fC}vUdskGSq&{`oxt~0i?0xhr6I47_tBc`fqaSrMOzR4>0H^;A zF)hX1nfHs)%Zb-(YGX;=#2R6C{BG;k=?FfP?9{_uFLri~-~AJ;jw({4MU7e*d)?P@ zXX*GkNY9ItFjhwgAIWq7Y!ksbMzfqpG)IrqKx9q{zu%Mdl+{Dis#p9q`02pr1LG8R z@As?eG!>IoROgS!@J*to<27coFc1zpkh?w=)h9CbYe%^Q!Ui46Y*HO0mr% zEff-*$ndMNw}H2a5@BsGj5oFfd!T(F&0$<{GO!Qdd?McKkorh=5{EIjDTHU`So>8V zBA-fqVLb2;u7UhDV1xMI?y>fe3~4urv3%PX)lDw+HYa;HFkaLqi4c~VtCm&Ca+9C~ zge+67hp#R9`+Euq59WhHX&7~RlXn=--m8$iZ~~1C8cv^2(qO#X0?vl91gzUKBeR1J z^p4!!&7)3#@@X&2aF2-)1Ffcc^F8r|RtdL2X%HgN&XU-KH2SLCbpw?J5xJ*!F-ypZ zMG%AJ!Pr&}`LW?E!K~=(NJxuSVTRCGJ$2a*Ao=uUDSys!OFYu!Vs2IT;xQ6EubLIl z+?+nMGeQQhh~??0!s4iQ#gm3!BpMpnY?04kK375e((Uc7B3RMj;wE?BCoQGu=UlZt!EZ1Q*auI)dj3Jj{Ujgt zW5hd~-HWBLI_3HuO) zNrb^XzPsTIb=*a69wAAA3J6AAZZ1VsYbIG}a`=d6?PjM)3EPaDpW2YP$|GrBX{q*! z$KBHNif)OKMBCFP5>!1d=DK>8u+Upm-{hj5o|Wn$vh1&K!lVfDB&47lw$tJ?d5|=B z^(_9=(1T3Fte)z^>|3**n}mIX;mMN5v2F#l(q*CvU{Ga`@VMp#%rQkDBy7kYbmb-q z<5!4iuB#Q_lLZ8}h|hPODI^U6`gzLJre9u3k3c#%86IKI*^H-@I48Bi*@avYm4v!n0+v zWu{M{&F8#p9cx+gF0yTB_<2QUrjMPo9*7^-uP#~gGW~y3nfPAoV%amgr>PSyVAd@l)}8#X zR5zV6t*uKJZL}?NYvPVK6J0v4iVpwiN|>+t3aYiZSp;m0!(1`bHO}TEtWR1tY%BPB z(W!0DmXbZAsT$iC13p4f>u*ZAy@JoLAkJhzFf1#4;#1deO8#8d&89}en&z!W&A3++^1(;>0SB1*54d@y&9Pn;^IAf3GiXbfT`_>{R+Xv; zQvgL>+0#8-laO!j#-WB~(I>l0NCMt_;@Gp_f0#^c)t?&#Xh1-7RR0@zPyBz!U#0Av zT?}n({(p?p7!4S2ZBw)#KdCG)uPnZe+U|0{BW!m)9 zi_9$F?m<`2!`JNFv+w8MK_K)qJ^aO@7-Ig>cM4-r0bi=>?B_2mFNJ}aE3<+QCzRr*NA!QjHw# z`1OsvcoD0?%jq{*7b!l|L1+Tw0TTAM4XMq7*ntc-Ived>Sj_ZtS|uVdpfg1_I9knY z2{GM_j5sDC7(W&}#s{jqbybqJWyn?{PW*&cQIU|*v8YGOKKlGl@?c#TCnmnAkAzV- zmK={|1G90zz=YUvC}+fMqts0d4vgA%t6Jhjv?d;(Z}(Ep8fTZfHA9``fdUHkA+z3+ zhh{ohP%Bj?T~{i0sYCQ}uC#5BwN`skI7`|c%kqkyWIQ;!ysvA8H`b-t()n6>GJj6xlYDu~8qX{AFo$Cm3d|XFL=4uvc?Keb zzb0ZmMoXca6Mob>JqkNuoP>B2Z>D`Q(TvrG6m`j}-1rGP!g|qoL=$FVQYxJQjFn33lODt3Wb1j8VR zlR++vIT6^DtYxAv_hxupbLLN3e0%A%a+hWTKDV3!Fjr^cWJ{scsAdfhpI)`Bms^M6 zQG$waKgFr=c|p9Piug=fcJvZ1ThMnNhQvBAg-8~b1?6wL*WyqXhtj^g(Ke}mEfZVM zJuLNTUVh#WsE*a6uqiz`b#9ZYg3+2%=C(6AvZGc=u&<6??!slB1a9K)=VL zY9EL^mfyKnD zSJyYBc_>G;5RRnrNgzJz#Rkn3S1`mZgO`(r5;Hw6MveN(URf_XS-r58Cn80K)ArH4 z#Rrd~LG1W&@ttw85cjp8xV&>$b%nSXH_*W}7Ch2pg$$c0BdEo-HWRTZcxngIBJad> z;C>b{jIXjb_9Jis?NZJsdm^EG}e*pR&DAy0EaSGi3XWTa(>C%tz1n$u?5Fb z1qtl?;_yjYo)(gB^iQq?=jusF%kywm?CJP~zEHi0NbZ);$(H$w(Hy@{i>$wcVRD_X|w-~(0Z9BJyh zhNh;+eQ9BEIs;tPz%jSVnfCP!3L&9YtEP;svoj_bNzeGSQIAjd zBss@A;)R^WAu-37RQrM%{DfBNRx>v!G31Z}8-El9IOJlb_MSoMu2}GDYycNaf>uny z+8xykD-7ONCM!APry_Lw6-yT>5!tR}W;W`C)1>pxSs5o1z#j7%m=&=7O4hz+Lsqm` z*>{+xsabZPr&X=}G@obTb{nPTkccJX8w3CG7X+1+t{JcMabv~UNv+G?txRqXib~c^Mo}`q{$`;EBNJ;#F*{gvS12kV?AZ%O0SFB$^ zn+}!HbmEj}w{Vq(G)OGAzH}R~kS^;(-s&=ectz8vN!_)Yl$$U@HNTI-pV`LSj7Opu zTZ5zZ)-S_{GcEQPIQXLQ#oMS`HPu{`SQiAZ)m1at*Hy%3xma|>o`h%E%8BEbi9p0r zVjcsh<{NBKQ4eKlXU|}@XJ#@uQw*$4BxKn6#W~I4T<^f99~(=}a`&3(ur8R9t+|AQ zWkQx7l}wa48-jO@ft2h+7qn%SJtL%~890FG0s5g*kNbL3I&@brh&f6)TlM`K^(bhr zJWM6N6x3flOw$@|C@kPi7yP&SP?bzP-E|HSXQXG>7gk|R9BTj`e=4de9C6+H7H7n# z#GJeVs1mtHhLDmVO?LkYRQc`DVOJ_vdl8VUihO-j#t=0T3%Fc1f9F73ufJz*adn*p zc%&vi(4NqHu^R>sAT_0EDjVR8bc%wTz#$;%NU-kbDyL_dg0%TFafZwZ?5KZpcuaO54Z9hX zD$u>q!-9`U6-D`E#`W~fIfiIF5_m6{fvM)b1NG3xf4Auw;Go~Fu7cth#DlUn{@~yu z=B;RT*dp?bO}o%4x7k9v{r=Y@^YQ^UUm(Qmliw8brO^=NP+UOohLYiaEB3^DB56&V zK?4jV61B|1Uj_5fBKW;8LdwOFZKWp)g{B%7g1~DgO&N& z#lisxf?R~Z@?3E$Mms$$JK8oe@X`5m98V*aV6Ua}8Xs2#A!{x?IP|N(%nxsH?^c{& z@vY&R1QmQs83BW28qAmJfS7MYi=h(YK??@EhjL-t*5W!p z^gYX!Q6-vBqcv~ruw@oMaU&qp0Fb(dbVzm5xJN%0o_^@fWq$oa3X?9s%+b)x4w-q5Koe(@j6Ez7V@~NRFvd zfBH~)U5!ix3isg`6be__wBJp=1@yfsCMw1C@y+9WYD9_C%{Q~7^0AF2KFryfLlUP# zwrtJEcH)jm48!6tUcxiurAMaiD04C&tPe6DI0#aoqz#Bt0_7_*X*TsF7u*zv(iEfA z;$@?XVu~oX#1YXtceQL{dSneL&*nDug^OW$DSLF0M1Im|sSX8R26&)<0Fbh^*l6!5wfSu8MpMoh=2l z^^0Sr$UpZp*9oqa23fcCfm7`ya2<4wzJ`Axt7e4jJrRFVf?nY~2&tRL* zd;6_njcz01c>$IvN=?K}9ie%Z(BO@JG2J}fT#BJQ+f5LFSgup7i!xWRKw6)iITjZU z%l6hPZia>R!`aZjwCp}I zg)%20;}f+&@t;(%5;RHL>K_&7MH^S+7<|(SZH!u zznW|jz$uA`P9@ZWtJgv$EFp>)K&Gt+4C6#*khZQXS*S~6N%JDT$r`aJDs9|uXWdbg zBwho$phWx}x!qy8&}6y5Vr$G{yGSE*r$^r{}pw zVTZKvikRZ`J_IJrjc=X1uw?estdwm&bEahku&D04HD+0Bm~q#YGS6gp!KLf$A{%Qd z&&yX@Hp>~(wU{|(#U&Bf92+1i&Q*-S+=y=3pSZy$#8Uc$#7oiJUuO{cE6=tsPhwPe| zxQpK>`Dbka`V)$}e6_OXKLB%i76~4N*zA?X+PrhH<&)}prET;kel24kW%+9))G^JI zsq7L{P}^#QsZViX%KgxBvEugr>ZmFqe^oAg?{EI=&_O#e)F3V#rc z8$4}0Zr19qd3tE4#$3_f=Bbx9oV6VO!d3(R===i-7p=Vj`520w0D3W6lQfY48}!D* z&)lZMG;~er2qBoI2gsX+Ts-hnpS~NYRDtPd^FPzn!^&yxRy#CSz(b&E*tL|jIkq|l zf%>)7Dtu>jCf`-7R#*GhGn4FkYf;B$+9IxmqH|lf6$4irg{0ept__%)V*R_OK=T06 zyT_m-o@Kp6U{l5h>W1hGq*X#8*y@<;vsOFqEjTQXFEotR+{3}ODDnj;o0@!bB5x=N z394FojuGOtVKBlVRLtHp%EJv_G5q=AgF)SKyRN5=cGBjDWv4LDn$IL`*=~J7u&Dy5 zrMc83y+w^F&{?X(KOOAl-sWZDb{9X9#jrQtmrEXD?;h-}SYT7yM(X_6qksM=K_a;Z z3u0qT0TtaNvDER_8x*rxXw&C^|h{P1qxK|@pS7vdlZ#P z7PdB7MmC2}%sdzAxt>;WM1s0??`1983O4nFK|hVAbHcZ3x{PzytQLkCVk7hA!Lo` zEJH?4qw|}WH{dc4z%aB=0XqsFW?^p=X}4xnCJXK%c#ItOSjdSO`UXJyuc8bh^Cf}8 z@Ht|vXd^6{Fgai8*tmyRGmD_s_nv~r^Fy7j`Bu`6=G)5H$i7Q7lvQnmea&TGvJp9a|qOrUymZ$6G|Ly z#zOCg++$3iB$!6!>215A4!iryregKuUT344X)jQb3|9qY>c0LO{6Vby05n~VFzd?q zgGZv&FGlkiH*`fTurp>B8v&nSxNz)=5IF$=@rgND4d`!AaaX;_lK~)-U8la_Wa8i?NJC@BURO*sUW)E9oyv3RG^YGfN%BmxzjlT)bp*$<| zX3tt?EAy<&K+bhIuMs-g#=d1}N_?isY)6Ay$mDOKRh z4v1asEGWoAp=srraLW^h&_Uw|6O+r;wns=uwYm=JN4Q!quD8SQRSeEcGh|Eb5Jg8m zOT}u;N|x@aq)=&;wufCc^#)5U^VcZw;d_wwaoh9$p@Xrc{DD6GZUqZ ziC6OT^zSq@-lhbgR8B+e;7_Giv;DK5gn^$bs<6~SUadiosfewWDJu`XsBfOd1|p=q zE>m=zF}!lObA%ePey~gqU8S6h-^J2Y?>7)L2+%8kV}Gp=h`Xm_}rlm)SyUS=`=S7msKu zC|T!gPiI1rWGb1z$Md?0YJQ;%>uPLOXf1Z>N~`~JHJ!^@D5kSXQ4ugnFZ>^`zH8CAiZmp z6Ms|#2gcGsQ{{u7+Nb9sA?U>(0e$5V1|WVwY`Kn)rsnnZ4=1u=7u!4WexZD^IQ1Jk zfF#NLe>W$3m&C^ULjdw+5|)-BSHwpegdyt9NYC{3@QtMfd8GrIWDu`gd0nv-3LpGCh@wgBaG z176tikL!_NXM+Bv#7q^cyn9$XSeZR6#!B4JE@GVH zoobHZN_*RF#@_SVYKkQ_igme-Y5U}cV(hkR#k1c{bQNMji zU7aE`?dHyx=1`kOYZo_8U7?3-7vHOp`Qe%Z*i+FX!s?6huNp0iCEW-Z7E&jRWmUW_ z67j>)Ew!yq)hhG4o?^z}HWH-e=es#xJUhDRc4B51M4~E-l5VZ!&zQq`gWe`?}#b~7w1LH4Xa-UCT5LXkXQWheBa2YJYbyQ zl1pXR%b(KCXMO0OsXgl0P0Og<{(@&z1aokU-Pq`eQq*JYgt8xdFQ6S z6Z3IFSua8W&M#`~*L#r>Jfd6*BzJ?JFdBR#bDv$_0N!_5vnmo@!>vULcDm`MFU823 zpG9pqjqz^FE5zMDoGqhs5OMmC{Y3iVcl>F}5Rs24Y5B^mYQ;1T&ks@pIApHOdrzXF z-SdX}Hf{X;TaSxG_T$0~#RhqKISGKNK47}0*x&nRIPtmdwxc&QT3$8&!3fWu1eZ_P zJveQj^hJL#Sn!*4k`3}(d(aasl&7G0j0-*_2xtAnoX1@9+h zO#c>YQg60Z;o{Bi=3i7S`Ic+ZE>K{(u|#)9y}q*j8uKQ1^>+(BI}m%1v3$=4ojGBc zm+o1*!T&b}-lVvZqIUBc8V}QyFEgm#oyIuC{8WqUNV{Toz`oxhYpP!_p2oHHh5P@iB*NVo~2=GQm+8Yrkm2Xjc_VyHg1c0>+o~@>*Qzo zHVBJS>$$}$_4EniTI;b1WShX<5-p#TPB&!;lP!lBVBbLOOxh6FuYloD%m;n{r|;MU3!q4AVkua~fieeWu2 zQAQ$ue(IklX6+V;F1vCu-&V?I3d42FgWgsb_e^29ol}HYft?{SLf>DrmOp9o!t>I^ zY7fBCk+E8n_|apgM|-;^=#B?6RnFKlN`oR)`e$+;D=yO-(U^jV;rft^G_zl`n7qnM zL z*-Y4Phq+ZI1$j$F-f;`CD#|`-T~OM5Q>x}a>B~Gb3-+9i>Lfr|Ca6S^8g*{*?_5!x zH_N!SoRP=gX1?)q%>QTY!r77e2j9W(I!uAz{T`NdNmPBBUzi2{`XMB^zJGGwFWeA9 z{fk33#*9SO0)DjROug+(M)I-pKA!CX;IY(#gE!UxXVsa)X!UftIN98{pt#4MJHOhY zM$_l}-TJlxY?LS6Nuz1T<44m<4i^8k@D$zuCPrkmz@sdv+{ciyFJG2Zwy&%c7;atIeTdh!a(R^QXnu1Oq1b42*OQFWnyQ zWeQrdvP|w_idy53Wa<{QH^lFmEd+VlJkyiC>6B#s)F;w-{c;aKIm;Kp50HnA-o3lY z9B~F$gJ@yYE#g#X&3ADx&tO+P_@mnQTz9gv30_sTsaGXkfNYXY{$(>*PEN3QL>I!k zp)KibPhrfX3%Z$H6SY`rXGYS~143wZrG2;=FLj50+VM6soI~up_>fU(2Wl@{BRsMi zO%sL3x?2l1cXTF)k&moNsHfQrQ+wu(gBt{sk#CU=UhrvJIncy@tJX5klLjgMn>~h= zg|FR&;@eh|C7`>s_9c~0-{IAPV){l|Ts`i=)AW;d9&KPc3fMeoTS%8@V~D8*h;&(^>yjT84MM}=%#LS7shLAuuj(0VAYoozhWjq z4LEr?wUe2^WGwdTIgWBkDUJa>YP@5d9^Rs$kCXmMRxuF*YMVrn?0NFyPl}>`&dqZb z<5eqR=ZG3>n2{6v6BvJ`YBZeeTtB88TAY(x0a58EWyuf>+^|x8Qa6wA|1Nb_p|nA zWWa}|z8a)--Wj`LqyFk_a3gN2>5{Rl_wbW?#by7&i*^hRknK%jwIH6=dQ8*-_{*x0j^DUfMX0`|K@6C<|1cgZ~D(e5vBFFm;HTZF(!vT8=T$K+|F)x3kqzBV4-=p1V(lzi(s7jdu0>LD#N=$Lk#3HkG!a zIF<7>%B7sRNzJ66KrFV76J<2bdYhxll0y2^_rdG=I%AgW4~)1Nvz=$1UkE^J%BxLo z+lUci`UcU062os*=`-j4IfSQA{w@y|3}Vk?i;&SSdh8n+$iHA#%ERL{;EpXl6u&8@ zzg}?hkEOUOJt?ZL=pWZFJ19mI1@P=$U5*Im1e_8Z${JsM>Ov?nh8Z zP5QvI!{Jy@&BP48%P2{Jr_VgzW;P@7)M9n|lDT|Ep#}7C$&ud&6>C^5ZiwKIg2McPU(4jhM!BD@@L(Gd*Nu$ji(ljZ<{FIeW_1Mmf;76{LU z-ywN~=uNN)Xi6$<12A9y)K%X|(W0p|&>>4OXB?IiYr||WKDOJPxiSe01NSV-h24^L z_>m$;|C+q!Mj**-qQ$L-*++en(g|hw;M!^%_h-iDjFHLo-n3JpB;p?+o2;`*jpvJU zLY^lt)Un4joij^^)O(CKs@7E%*!w>!HA4Q?0}oBJ7Nr8NQ7QmY^4~jvf0-`%waOLn zdNjAPaC0_7c|RVhw)+71NWjRi!y>C+Bl;Z`NiL^zn2*0kmj5gyhCLCxts*cWCdRI| zjsd=sT5BVJc^$GxP~YF$-U{-?kW6r@^vHXB%{CqYzU@1>dzf#3SYedJG-Rm6^RB7s zGM5PR(yKPKR)>?~vpUIeTP7A1sc8-knnJk*9)3t^e%izbdm>Y=W{$wm(cy1RB-19i za#828DMBY+ps#7Y8^6t)=Ea@%Nkt)O6JCx|ybC;Ap}Z@Zw~*}3P>MZLPb4Enxz9Wf zssobT^(R@KuShj8>@!1M7tm|2%-pYYDxz-5`rCbaTCG5{;Uxm z*g=+H1X8{NUvFGzz~wXa%Eo};I;~`37*WrRU&K0dPSB$yk(Z*@K&+mFal^?c zurbqB-+|Kb5|sznT;?Pj!+kgFY1#Dr;_%A(GIQC{3ct|{*Bji%FNa6c-thbpBkA;U zURV!Dr&X{0J}iht#-Qp2=xzuh(fM>zRoiGrYl5ttw2#r34gC41CCOC31m~^UPTK@s z6;A@)7O7_%C)>bnAXerYuAHdE93>j2N}H${zEc6&SbZ|-fiG*-qtGuy-qDelH(|u$ zorf8_T6Zqe#Ub!+e3oSyrskt_HyW_^5lrWt#30l)tHk|j$@YyEkXUOV;6B51L;M@=NIWZXU;GrAa(LGxO%|im%7F<-6N;en0Cr zLH>l*y?pMwt`1*cH~LdBPFY_l;~`N!Clyfr;7w<^X;&(ZiVdF1S5e(+Q%60zgh)s4 zn2yj$+mE=miVERP(g8}G4<85^-5f@qxh2ec?n+$A_`?qN=iyT1?U@t?V6DM~BIlBB z>u~eXm-aE>R0sQy!-I4xtCNi!!qh?R1!kKf6BoH2GG{L4%PAz0{Sh6xpuyI%*~u)s z%rLuFl)uQUCBQAtMyN;%)zFMx4loh7uTfKeB2Xif`lN?2gq6NhWhfz0u5WP9J>=V2 zo{mLtSy&BA!mSzs&CrKWq^y40JF5a&GSXIi2= z{EYb59J4}VwikL4P=>+mc6{($FNE@e=VUwG+KV21;<@lrN`mnz5jYGASyvz7BOG_6(p^eTxD-4O#lROgon;R35=|nj#eHIfJBYPWG>H>`dHKCDZ3`R{-?HO0mE~(5_WYcFmp8sU?wr*UkAQiNDGc6T zA%}GOLXlOWqL?WwfHO8MB#8M8*~Y*gz;1rWWoVSXP&IbKxbQ8+s%4Jnt?kDsq7btI zCDr0PZ)b;B%!lu&CT#RJzm{l{2fq|BcY85`w~3LSK<><@(2EdzFLt9Y_`;WXL6x`0 zDoQ?=?I@Hbr;*VVll1Gmd8*%tiXggMK81a+T(5Gx6;eNb8=uYn z5BG-0g>pP21NPn>$ntBh>`*})Fl|38oC^9Qz>~MAazH%3Q~Qb!ALMf$srexgPZ2@&c~+hxRi1;}+)-06)!#Mq<6GhP z-Q?qmgo${aFBApb5p}$1OJKTClfi8%PpnczyVKkoHw7Ml9e7ikrF0d~UB}i3vizos zXW4DN$SiEV9{faLt5bHy2a>33K%7Td-n5C*N;f&ZqAg#2hIqEb(y<&f4u5BWJ>2^4 z414GosL=Aom#m&=x_v<0-fp1r%oVJ{T-(xnomNJ(Dryv zh?vj+%=II_nV+@NR+(!fZZVM&(W6{6%9cm+o+Z6}KqzLw{(>E86uA1`_K$HqINlb1 zKelh3-jr2I9V?ych`{hta9wQ2c9=MM`2cC{m6^MhlL2{DLv7C^j z$xXBCnDl_;l|bPGMX@*tV)B!c|4oZyftUlP*?$YU9C_eAsuVHJ58?)zpbr30P*C`T z7y#ao`uE-SOG(Pi+`$=e^mle~)pRrdwL5)N;o{gpW21of(QE#U6w%*C~`v-z0QqBML!!5EeYA5IQB0 z^l01c;L6E(iytN!LhL}wfwP7W9PNAkb+)Cst?qg#$n;z41O4&v+8-zPs+XNb-q zIeeBCh#ivnFLUCwfS;p{LC0O7tm+Sf9Jn)~b%uwP{%69;QC)Ok0t%*a5M+=;y8j=v z#!*pp$9@!x;UMIs4~hP#pnfVc!%-D<+wsG@R2+J&%73lK|2G!EQC)O05TCV=&3g)C!lT=czLpZ@Sa%TYuoE?v8T8`V;e$#Zf2_Nj6nvBgh1)2 GZ~q4|mN%#X literal 62076 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