commit 7ccb8c55793ade053ebee0d2d338ab8c0d0bfada Author: TheTrouper <93684527+thetrouper@users.noreply.github.com> Date: Thu Mar 7 15:56:54 2024 -0600 Got most of the project working diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..efbbfcd --- /dev/null +++ b/build.gradle @@ -0,0 +1,75 @@ +plugins { + id 'java' +} + +group = project.group +version = project.version + +jar { + from { + duplicatesStrategy = DuplicatesStrategy.EXCLUDE + configurations.runtimeClasspath.collect { + it.isDirectory() ? it : zipTree(it) + } + } +} + +repositories { + mavenCentral() + maven { + name = 'spigotmc-repo' + url = 'https://hub.spigotmc.org/nexus/content/repositories/snapshots/' + } + maven { + url = uri("https://repo.papermc.io/repository/maven-public/") + } + maven { + name = 'sonatype' + url = 'https://oss.sonatype.org/content/groups/public/' + } +} + +dependencies { + compileOnly 'io.papermc.paper:paper-api:1.20.4-R0.1-SNAPSHOT' + implementation 'com.google.code.gson:gson:2.10.1' + implementation files("libs/PDK-1.3.4.jar") +} + +def targetJavaVersion = 17 +java { + def javaVersion = JavaVersion.toVersion(targetJavaVersion) + sourceCompatibility = javaVersion + targetCompatibility = javaVersion + toolchain.languageVersion.set(JavaLanguageVersion.of(17)) + if (JavaVersion.current() < javaVersion) { + toolchain.languageVersion = JavaLanguageVersion.of(targetJavaVersion) + } +} + +tasks.withType(JavaCompile).configureEach { + if (targetJavaVersion >= 10 || JavaVersion.current().isJava10Compatible()) { + options.release = targetJavaVersion + } +} + +tasks.register('copyDeps', Copy) { + from configurations.runtimeClasspath + into 'build/deps' + include '*.jar' +} + + +processResources { + def props = [version: version] + inputs.properties props + filteringCharset 'UTF-8' + filesMatching('plugin.yml') { + expand props + } +} + +compileJava.options.encoding("UTF-8") + +tasks.withType(JavaCompile) { + options.encoding = "UTF-8" +} diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..99e4cb1 --- /dev/null +++ b/build.sh @@ -0,0 +1,48 @@ +#!/bin/bash + +# Run Gradle build +./gradlew build + +# Check if the build was successful +if [ $? -eq 0 ]; then + echo "Gradle build successful." + + # SFTP upload + SFTP_HOST="192.168.1.199" + SFTP_USER="trouper" + SFTP_PASSWORD="Trouper12()1" + SFTP_REMOTE_DIR="/home/trouper/docker/data/plugins/" + + # Create a temporary file with a unique name + TEMP_FILE=$(mktemp) + + # Specify the local file to upload + LOCAL_FILE="/run/media/trouper/'1TB drive'/IJ/IdeaProjects/UltraLS/build/libs/UltraLS-0.2.5.jar" + + # Write the SFTP commands to the temporary file + echo "put $LOCAL_FILE $SFTP_REMOTE_DIR" > "$TEMP_FILE" + echo "bye" >> "$TEMP_FILE" + + # Use sftp non-interactively with the specified commands + sftp -oStrictHostKeyChecking=no -oBatchMode=no -b "$TEMP_FILE" "$SFTP_USER@$SFTP_HOST" < '} + 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 + 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 +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 0000000..93e3f59 --- /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/libs/PDK-1.3.4.jar b/libs/PDK-1.3.4.jar new file mode 100644 index 0000000..e949bf1 Binary files /dev/null and b/libs/PDK-1.3.4.jar differ diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..e382a3c --- /dev/null +++ b/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'UltraLS' diff --git a/src/main/java/me/trouper/ultrals/UltraLS.java b/src/main/java/me/trouper/ultrals/UltraLS.java new file mode 100644 index 0000000..5990e1c --- /dev/null +++ b/src/main/java/me/trouper/ultrals/UltraLS.java @@ -0,0 +1,101 @@ +package me.trouper.ultrals; + +import io.github.itzispyder.pdk.PDK; +import io.github.itzispyder.pdk.utils.misc.JsonSerializable; +import me.trouper.ultrals.cmds.*; +import me.trouper.ultrals.data.BankStorage; +import me.trouper.ultrals.data.HeartItemStorage; +import me.trouper.ultrals.data.config.Config; +import me.trouper.ultrals.events.ClickEvent; +import me.trouper.ultrals.events.DeathEvent; +import me.trouper.ultrals.events.JoinEvent; +import org.bukkit.Bukkit; +import org.bukkit.plugin.java.JavaPlugin; + +import java.io.File; +import java.util.logging.Logger; + +public final class UltraLS extends JavaPlugin { + + private static UltraLS instance; + private static final File cfgfile = new File("plugins/UltraLS/main-config.json"); + private static final File bankfile = new File("plugins/UltraLS/banks.json"); + private static final File withdrawfile = new File("plugins/UltraLS/heart-item-storage.json"); + public static Config config = JsonSerializable.load(cfgfile, Config.class, new Config()); + public static BankStorage bank = JsonSerializable.load(bankfile, BankStorage.class, new BankStorage()); + public static HeartItemStorage hearts = JsonSerializable.load(bankfile, HeartItemStorage.class, new HeartItemStorage()); + public static final Logger log = Bukkit.getLogger(); + + /** + * Plugin startup logic + */ + @Override + public void onEnable() { + + log.info("\n]======------ Pre-load started! ------======["); + PDK.init(this); + instance = this; + + log.info("Loading Config..."); + + loadConfig(); + + startup(); + } + + public void startup() { + log.info("\n]======----- Loading UltraLS! -----======["); + + // Plugin startup logic + log.info("Starting Up! (%s)...".formatted(getDescription().getVersion())); + + // Commands + new UltraLSCommand().register(); + new GiveHeartCommand().register(); + new WithdrawCommand().register(); + new ReviveCommand().register(); + new DepositCommand().register(); + + // Events + new DeathEvent().register(); + new ClickEvent().register(); + new JoinEvent().register(); + + log.info(""" + Finished! + _ _ _ _ _ _____\s + | | | | | | | | / ____| + | | | | | |_ _ __ __ _| | | (___ \s + | | | | | __| '__/ _` | | \\___ \\\s + | |__| | | |_| | | (_| | |____ ____) | + \\____/|_|\\__|_| \\__,_|______|_____/\s + ]==-- LifeSteal done correctly --==["""); + } + + public void loadConfig() { + + // Init + config = JsonSerializable.load(cfgfile, Config.class,new Config()); + bank = JsonSerializable.load(bankfile,BankStorage.class,new BankStorage()); + hearts = JsonSerializable.load(withdrawfile, HeartItemStorage.class,new HeartItemStorage()); + // Save + config.save(); + config.save(); + bank.save(); + } + + + /** + * Plugin shutdown logic + */ + @Override + public void onDisable() { + // Plugin shutdown logic + log.info("UltraLS has disabled! (%s)".formatted(getDescription().getVersion())); + } + + public static UltraLS getInstance() { + return instance; + } + +} diff --git a/src/main/java/me/trouper/ultrals/cmds/DepositCommand.java b/src/main/java/me/trouper/ultrals/cmds/DepositCommand.java new file mode 100644 index 0000000..80c0c67 --- /dev/null +++ b/src/main/java/me/trouper/ultrals/cmds/DepositCommand.java @@ -0,0 +1,25 @@ +package me.trouper.ultrals.cmds; + +import io.github.itzispyder.pdk.commands.Args; +import io.github.itzispyder.pdk.commands.CommandRegistry; +import io.github.itzispyder.pdk.commands.CustomCommand; +import io.github.itzispyder.pdk.commands.completions.CompletionBuilder; +import me.trouper.ultrals.server.functions.BankFunctions; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +@CommandRegistry(value = "deposit",printStackTrace = true) +public class DepositCommand implements CustomCommand { + @Override + public void dispatchCommand(CommandSender sender, Args args) { + Player p = (Player) sender; + int amount = args.get(0).toInt(); + + BankFunctions.depositHeart(p,amount); + } + + @Override + public void dispatchCompletions(CompletionBuilder b) { + b.then(b.arg("")); + } +} diff --git a/src/main/java/me/trouper/ultrals/cmds/GiveHeartCommand.java b/src/main/java/me/trouper/ultrals/cmds/GiveHeartCommand.java new file mode 100644 index 0000000..5de284c --- /dev/null +++ b/src/main/java/me/trouper/ultrals/cmds/GiveHeartCommand.java @@ -0,0 +1,56 @@ +package me.trouper.ultrals.cmds; + +import io.github.itzispyder.pdk.commands.Args; +import io.github.itzispyder.pdk.commands.CommandRegistry; +import io.github.itzispyder.pdk.commands.CustomCommand; +import io.github.itzispyder.pdk.commands.completions.CompletionBuilder; +import io.github.itzispyder.pdk.utils.ServerUtils; +import me.trouper.ultrals.server.functions.TransferFunctions; +import me.trouper.ultrals.server.util.Text; +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.List; +@CommandRegistry(value = "giveheart",printStackTrace = true) +public class GiveHeartCommand implements CustomCommand { + @Override + public void dispatchCommand(CommandSender sender, Args args) { + Player s = (Player) sender; + Player r = Bukkit.getServer().getPlayer(args.get(0).toString()); + if (r == null) { + s.sendMessage(Text.prefix("&cYou must provide an online player!&7 Use the /revive command to give hearts to a dead player.")); + return; + } + int amount = args.get(1).toInt(); + String to = args.get(2).toString(); + String from = args.get(3).toString(); + if (from.equals("bank")) { + if (to.equals("bank")) { + TransferFunctions.bankToBank(s,r,amount); + return; + } + TransferFunctions.bankToBar(s,r,amount); + return; + } + if (to.equals("bank")) { + TransferFunctions.barToBank(s,r,amount); + } + TransferFunctions.barToBar(s,r,amount); + + } + + @Override + public void dispatchCompletions(CompletionBuilder b) { + List players = new ArrayList<>(); + for (Player player : ServerUtils.players()) { + players.add(player.getName()); + } + + b.then(b.arg(players) + .then(b.arg("") + .then(b.arg("[from: bar | bank]","bank","bar") + .then(b.arg("[to: bar | bank]","bank","bar"))))); + } +} diff --git a/src/main/java/me/trouper/ultrals/cmds/ReviveCommand.java b/src/main/java/me/trouper/ultrals/cmds/ReviveCommand.java new file mode 100644 index 0000000..8cc2cbc --- /dev/null +++ b/src/main/java/me/trouper/ultrals/cmds/ReviveCommand.java @@ -0,0 +1,20 @@ +package me.trouper.ultrals.cmds; + +import io.github.itzispyder.pdk.commands.Args; +import io.github.itzispyder.pdk.commands.CommandRegistry; +import io.github.itzispyder.pdk.commands.CustomCommand; +import io.github.itzispyder.pdk.commands.completions.CompletionBuilder; +import org.bukkit.command.CommandSender; + +@CommandRegistry(value = "revive") +public class ReviveCommand implements CustomCommand { + @Override + public void dispatchCommand(CommandSender commandSender, Args args) { + + } + + @Override + public void dispatchCompletions(CompletionBuilder completionBuilder) { + + } +} diff --git a/src/main/java/me/trouper/ultrals/cmds/UltraLSCommand.java b/src/main/java/me/trouper/ultrals/cmds/UltraLSCommand.java new file mode 100644 index 0000000..2c1e604 --- /dev/null +++ b/src/main/java/me/trouper/ultrals/cmds/UltraLSCommand.java @@ -0,0 +1,39 @@ +package me.trouper.ultrals.cmds; + +import io.github.itzispyder.pdk.commands.Args; +import io.github.itzispyder.pdk.commands.CommandRegistry; +import io.github.itzispyder.pdk.commands.CustomCommand; +import io.github.itzispyder.pdk.commands.Permission; +import io.github.itzispyder.pdk.commands.completions.CompletionBuilder; +import me.trouper.ultrals.UltraLS; +import me.trouper.ultrals.server.util.Text; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +@CommandRegistry(value = "ultrals", permission = @Permission("ultrals.admin"), printStackTrace = true) +public class UltraLSCommand implements CustomCommand { + + @Override + public void dispatchCommand(CommandSender sender, Args args) { + Player p = (Player) sender; + + switch (args.get(0).toString()) { + case "toggle" -> { + switch (args.get(1).toString()) { + case "debug" -> { + UltraLS.config.debugMode = !UltraLS.config.debugMode; + UltraLS.config.save(); + p.sendMessage(Text.prefix("Debug mode is now &a%s&7.".formatted(UltraLS.config.debugMode))); + } + } + } + } + } + + @Override + public void dispatchCompletions(CompletionBuilder b) { + b.then(b.arg("toggle") + .then(b.arg("debug"))); + } + +} diff --git a/src/main/java/me/trouper/ultrals/cmds/WithdrawCommand.java b/src/main/java/me/trouper/ultrals/cmds/WithdrawCommand.java new file mode 100644 index 0000000..73ccad7 --- /dev/null +++ b/src/main/java/me/trouper/ultrals/cmds/WithdrawCommand.java @@ -0,0 +1,34 @@ +package me.trouper.ultrals.cmds; + +import io.github.itzispyder.pdk.commands.Args; +import io.github.itzispyder.pdk.commands.CommandRegistry; +import io.github.itzispyder.pdk.commands.CustomCommand; +import io.github.itzispyder.pdk.commands.completions.CompletionBuilder; +import me.trouper.ultrals.server.functions.BankFunctions; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +@CommandRegistry(value = "withdraw",printStackTrace = true) +public class WithdrawCommand implements CustomCommand { + + @Override + public void dispatchCommand(CommandSender sender, Args args) { + Player p = (Player) sender; + int amount = args.get(0).toInt(); + + switch (args.get(1).toString()) { + case "item" -> { + BankFunctions.withdrawItem(p,amount); + } + default -> { + BankFunctions.withdraw(p,amount); + } + } + } + + @Override + public void dispatchCompletions(CompletionBuilder b) { + b.then(b.arg("") + .then(b.arg("healthbar","item")) + ); + } +} diff --git a/src/main/java/me/trouper/ultrals/data/BankStorage.java b/src/main/java/me/trouper/ultrals/data/BankStorage.java new file mode 100644 index 0000000..e0d00dc --- /dev/null +++ b/src/main/java/me/trouper/ultrals/data/BankStorage.java @@ -0,0 +1,20 @@ +package me.trouper.ultrals.data; + +import io.github.itzispyder.pdk.utils.misc.JsonSerializable; + +import java.io.File; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +public class BankStorage implements JsonSerializable { + + @Override + public File getFile() { + File file = new File("plugins/UltraLS/banks.json"); + file.getParentFile().mkdirs(); + return file; + } + + public Map balances = new HashMap<>(); +} diff --git a/src/main/java/me/trouper/ultrals/data/HeartItemStorage.java b/src/main/java/me/trouper/ultrals/data/HeartItemStorage.java new file mode 100644 index 0000000..8008eef --- /dev/null +++ b/src/main/java/me/trouper/ultrals/data/HeartItemStorage.java @@ -0,0 +1,20 @@ +package me.trouper.ultrals.data; + +import io.github.itzispyder.pdk.utils.misc.JsonSerializable; + +import java.io.File; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +public class HeartItemStorage implements JsonSerializable { + + @Override + public File getFile() { + File file = new File("plugins/UltraLS/heart-item-storage.json"); + file.getParentFile().mkdirs(); + return file; + } + + public Map withdrawn = new HashMap<>(); +} diff --git a/src/main/java/me/trouper/ultrals/data/Items.java b/src/main/java/me/trouper/ultrals/data/Items.java new file mode 100644 index 0000000..e87f11d --- /dev/null +++ b/src/main/java/me/trouper/ultrals/data/Items.java @@ -0,0 +1,12 @@ +package me.trouper.ultrals.data; + +import io.github.itzispyder.pdk.Global; +import io.github.itzispyder.pdk.plugin.builders.ItemBuilder; +import me.trouper.ultrals.UltraLS; +import org.bukkit.Material; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.inventory.ItemFlag; +import org.bukkit.inventory.ItemStack; + +public class Items { +} diff --git a/src/main/java/me/trouper/ultrals/data/config/Config.java b/src/main/java/me/trouper/ultrals/data/config/Config.java new file mode 100644 index 0000000..5b55e89 --- /dev/null +++ b/src/main/java/me/trouper/ultrals/data/config/Config.java @@ -0,0 +1,48 @@ +package me.trouper.ultrals.data.config; + +import io.github.itzispyder.pdk.utils.misc.JsonSerializable; + +import java.io.File; + +public class Config implements JsonSerializable { + + @Override + public File getFile() { + File file = new File("plugins/UltraLS/main-config.json"); + file.getParentFile().mkdirs(); + return file; + } + + public String prefix = "&9UltraLS> &7"; + public boolean debugMode = false; + public Plugin plugin = new Plugin(); + public Bank bank = new Bank(); + public NoobProtection noobProtection = new NoobProtection(); + + public class Plugin { + public int maxHP = 40; // maximum hearts a player can have + public int minHP = 2; // Minimum harts a player can have without taking death action. Setting to 0 is best if you plan on spectator mode-ing or banning people. + public int startingHP = 20; // The amount of HP you start with on first join + public boolean deathSpectator = false; // make the player a spectator/ghost when they die + public boolean deathBan = true; // Run the death ban command then they die + public boolean preventSpectatorTeleport = true; // Prevents players from using the spectator menu to leaka bases + public String deathBanCommand = "ban %s You have died!"; // command to be executed when death ban mode is enabled + public String reviveCommand = "pardon %s"; // command to be executed to undo a death ban + public int heartsFromEnvironment = 0; // Hearts lost from mobs/environmental damage such as lava or fall. + public int heartsFromPlayers = 2; // Hearts gained/lost through PvP + public int heartModelData = 6942; + } + + public class Bank { + public int startingBalance = 0; // The amount of hearts that you start with in the bank + public int maxBalance = 120; // The maximum balance a player can hold + public boolean stealDirectlyFromBank = true; // Weather to take hearts from the bank before the health bar + public boolean siphonFromBank = true; // If a player has hearts in their bank, but not in their health bar, hearts will be taken from the bank instead of banning them. + public boolean overflowToBank = true; // If the player is at max hearts, hearts they steal will get stored in their bank + } + + public class NoobProtection { + public int minutesPlayedToGiveHearts = 2; // How much playtime a player must have before they are allowed to give people hearts + public int minutesPlayedToWithdrawItemHearts = 2;// How much playtime a player must have to take out heart items + } +} diff --git a/src/main/java/me/trouper/ultrals/events/ClickEvent.java b/src/main/java/me/trouper/ultrals/events/ClickEvent.java new file mode 100644 index 0000000..6dea57c --- /dev/null +++ b/src/main/java/me/trouper/ultrals/events/ClickEvent.java @@ -0,0 +1,25 @@ +package me.trouper.ultrals.events; + +import io.github.itzispyder.pdk.events.CustomListener; +import me.trouper.ultrals.UltraLS; +import me.trouper.ultrals.server.functions.BankFunctions; +import org.bukkit.event.EventHandler; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.ItemStack; + +public class ClickEvent implements CustomListener { + @EventHandler + public void onClick(PlayerInteractEvent e) { + ItemStack i = e.getItem(); + if (!i.isEmpty() && + i.hasItemMeta() && + i.getItemMeta().hasCustomModelData() + && i.getItemMeta().hasLore() + && i.getItemMeta().getCustomModelData() != UltraLS.config.plugin.heartModelData) return; + + switch (e.getAction()) { + case LEFT_CLICK_AIR, LEFT_CLICK_BLOCK -> BankFunctions.depositItem(e.getPlayer(),false); + case RIGHT_CLICK_AIR, RIGHT_CLICK_BLOCK -> BankFunctions.depositItem(e.getPlayer(),true); + } + } +} diff --git a/src/main/java/me/trouper/ultrals/events/DeathEvent.java b/src/main/java/me/trouper/ultrals/events/DeathEvent.java new file mode 100644 index 0000000..216616d --- /dev/null +++ b/src/main/java/me/trouper/ultrals/events/DeathEvent.java @@ -0,0 +1,15 @@ +package me.trouper.ultrals.events; + +import io.github.itzispyder.pdk.events.CustomListener; +import me.trouper.ultrals.server.functions.StealFunctions; +import org.bukkit.event.EventHandler; +import org.bukkit.event.entity.PlayerDeathEvent; + +public class DeathEvent implements CustomListener { + @EventHandler + public void onDeath(PlayerDeathEvent e) { + StealFunctions.stealHeart(e.getPlayer(),e.getEntity().getKiller()); + } + + +} diff --git a/src/main/java/me/trouper/ultrals/events/JoinEvent.java b/src/main/java/me/trouper/ultrals/events/JoinEvent.java new file mode 100644 index 0000000..c47dc5a --- /dev/null +++ b/src/main/java/me/trouper/ultrals/events/JoinEvent.java @@ -0,0 +1,24 @@ +package me.trouper.ultrals.events; + +import io.github.itzispyder.pdk.events.CustomListener; +import me.trouper.ultrals.UltraLS; +import me.trouper.ultrals.server.util.Text; +import net.kyori.adventure.text.Component; +import org.bukkit.attribute.Attribute; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.player.PlayerJoinEvent; + +public class JoinEvent implements CustomListener { + @EventHandler + public void onFirstJoin(PlayerJoinEvent e) { + Player p = e.getPlayer(); + if (UltraLS.bank.balances.containsKey(p.getUniqueId().toString())) return; + UltraLS.bank.balances.put(p.getUniqueId().toString(),UltraLS.config.bank.startingBalance); + p.registerAttribute(Attribute.GENERIC_MAX_HEALTH); + p.getAttribute(Attribute.GENERIC_MAX_HEALTH).setBaseValue(UltraLS.config.plugin.startingHP); + UltraLS.bank.save(); + p.sendMessage(Component.text(Text.prefix("Welcome! Your HeartBank has been initialized correctly."))); + + } +} diff --git a/src/main/java/me/trouper/ultrals/server/functions/BankFunctions.java b/src/main/java/me/trouper/ultrals/server/functions/BankFunctions.java new file mode 100644 index 0000000..d825b52 --- /dev/null +++ b/src/main/java/me/trouper/ultrals/server/functions/BankFunctions.java @@ -0,0 +1,169 @@ +package me.trouper.ultrals.server.functions; + +import io.github.itzispyder.pdk.Global; +import io.github.itzispyder.pdk.plugin.builders.ItemBuilder; +import me.trouper.ultrals.UltraLS; +import me.trouper.ultrals.data.Items; +import me.trouper.ultrals.server.util.ServerUtils; +import me.trouper.ultrals.server.util.Text; +import net.kyori.adventure.text.Component; +import org.bukkit.Material; +import org.bukkit.attribute.Attribute; +import org.bukkit.attribute.AttributeInstance; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemFlag; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +import java.util.UUID; + +public class BankFunctions { + + public static void withdraw(Player p, int amount) { + int bal = UltraLS.bank.balances.get(p.getUniqueId().toString()); + AttributeInstance h = p.getAttribute(Attribute.GENERIC_MAX_HEALTH); + + if (bal - amount < 0) { + p.sendMessage(Text.prefix("&cInsufficient Balance. &7You only have &c%s&7 hearts in your bank.".formatted(bal))); + return; + } + if (h.getBaseValue() + amount > UltraLS.config.plugin.maxHP) { + p.sendMessage(Text.prefix("&cInsufficient Space. &7You would go over the max health. (&e%s&7)".formatted(UltraLS.config.plugin.maxHP))); + return; + } + + UltraLS.bank.balances.put(p.getUniqueId().toString(), bal - amount); + UltraLS.bank.save(); + h.setBaseValue(h.getBaseValue() + amount); + + p.sendMessage(Text.prefix("&7Withdrew &a%s&7 hearts from your bank. Your balance is now &e%s&7.".formatted(amount,bal - amount))); + } + + public static void withdrawItem(Player p, int amount) { + int bal = UltraLS.bank.balances.get(p.getUniqueId().toString()); + + if (bal - amount < 0) { + p.sendMessage(Text.prefix("&cInsufficient Balance. &7You only have &c%s&7 hearts in your bank.".formatted(bal))); + return; + } + + UltraLS.bank.balances.put(p.getUniqueId().toString(), bal - amount); + UltraLS.bank.save(); + + UUID withdrawID = UUID.randomUUID(); + + ServerUtils.verbose("UUID of Withdrawn item: %s".formatted(withdrawID.toString())); + + UltraLS.hearts.withdrawn.put(withdrawID.toString(),amount); + UltraLS.hearts.save(); + + ItemStack heartItem = ItemBuilder.create() + .material(Material.RED_DYE) + .name(Global.instance.color("&c%s &c&lHearts".formatted(amount))) + .lore(Global.instance.color("&4➥&7 (Right-Click) Deposit to bank")) + .lore(Global.instance.color("&4➥&7 (Left-Click) Deposit to health bar")) + .lore("") + .lore(Global.instance.color("&7ID: &8%s".formatted(withdrawID.toString()))) + .lore(Global.instance.color("&7Owner: &8%s".formatted(p.getName()))) + .enchant(Enchantment.LURE,1) + .customModelData(UltraLS.config.plugin.heartModelData) + .flag(ItemFlag.HIDE_ENCHANTS) + .build(); + + p.getInventory().addItem(heartItem); + p.sendMessage(Text.prefix("&7Withdrew &c%s&7 hearts.".formatted(amount))); + } + + public static void depositItem(Player p, boolean toBank) { + ItemStack i = p.getInventory().getItemInMainHand(); + + if (i.hasItemMeta() && i.getItemMeta().hasCustomModelData() && i.getItemMeta().hasLore() && i.getItemMeta().getCustomModelData() != UltraLS.config.plugin.heartModelData) { + p.sendMessage(Text.prefix("&cThat item is not a heart!")); + return; + } + + String idString = "NOT HEART"; + + for (String s : i.getLore()) { + ServerUtils.verbose(s); + if (s.contains(Text.color("&7ID: &8"))) { + s = s.replaceAll(Text.color("&7ID: &8"),""); + idString = s; + } + } + + if (idString.equals("NOT HEART")) { + p.sendMessage(Text.prefix("&cThat ID is invalid!")); + return; + } + + ServerUtils.verbose("UUID of Deposit item: %s".formatted(idString)); + UUID typeID = UUID.fromString(idString); + + if (!UltraLS.hearts.withdrawn.containsKey(typeID.toString())) { + p.sendMessage(Text.prefix("&cThat heart has already been redeemed!")); + return; + } + + int amount = UltraLS.hearts.withdrawn.get(typeID.toString()); + + p.getInventory().removeItem(i); + UltraLS.hearts.withdrawn.remove(typeID.toString()); + UltraLS.hearts.save(); + + + if (toBank) { + addToBank(p,amount); + } else { + addToBar(p,amount); + } + } + + public static void depositHeart(Player p, int amount) { + AttributeInstance h = p.getAttribute(Attribute.GENERIC_MAX_HEALTH); + + if (h.getBaseValue() - amount < UltraLS.config.plugin.minHP) { + p.sendMessage(Text.prefix("&cInsufficient Health. &7You would go below the minimum health and die! (&e%s&7)" + .formatted(UltraLS.config.plugin.minHP) + )); + return; + } + + h.setBaseValue(h.getBaseValue() - amount); + addToBank(p,amount); + } + + public static void addToBar(Player p, int amount) { + AttributeInstance h = p.getAttribute(Attribute.GENERIC_MAX_HEALTH); + + if (h.getBaseValue() + amount > UltraLS.config.plugin.maxHP) { + p.sendMessage(Text.prefix("&cInsufficient Space. &7You would go over the maximum health. (&e%s&7)" + .formatted(UltraLS.config.plugin.maxHP) + )); + return; + } + + h.setBaseValue(h.getBaseValue() + amount); + + p.sendMessage(Text.prefix("Deposited &c%s&7 hearts into your health bar." + .formatted(amount) + )); + } + + public static void addToBank(Player p, int amount) { + if (UltraLS.bank.balances.get(p.getUniqueId().toString()) + amount > UltraLS.config.bank.maxBalance) { + p.sendMessage(Text.prefix("&cInsufficient Space. &7You would go over the maximum balance. (&e%s&7)" + .formatted(UltraLS.config.bank.maxBalance) + )); + return; + } + + UltraLS.bank.balances.put(p.getUniqueId().toString(), UltraLS.bank.balances.get(p.getUniqueId().toString()) + amount); + UltraLS.bank.save(); + + p.sendMessage(Text.prefix("Deposited &c%s&7 hearts into your heart bank. Your new balance is &c%s&7." + .formatted(amount,UltraLS.bank.balances.get(p.getUniqueId().toString())) + )); + } +} diff --git a/src/main/java/me/trouper/ultrals/server/functions/DeathFunctions.java b/src/main/java/me/trouper/ultrals/server/functions/DeathFunctions.java new file mode 100644 index 0000000..b75968e --- /dev/null +++ b/src/main/java/me/trouper/ultrals/server/functions/DeathFunctions.java @@ -0,0 +1,33 @@ +package me.trouper.ultrals.server.functions; + +import me.trouper.ultrals.UltraLS; +import me.trouper.ultrals.server.util.ServerUtils; +import me.trouper.ultrals.server.util.Text; +import net.kyori.adventure.text.Component; +import org.bukkit.Bukkit; +import org.bukkit.GameMode; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; + +public class DeathFunctions { + + public static void unBan(OfflinePlayer p, String who) { + ServerUtils.sendCommand(UltraLS.config.plugin.reviveCommand.formatted(p.getName())); + Bukkit.broadcast(Component.text(Text.prefix("&a%s&7 has been revived by &e%s&7!".formatted(p.getName(),who)))); + } + + public static void ban(Player p) { + ServerUtils.sendCommand(UltraLS.config.plugin.deathBanCommand.formatted(p.getName())); + Bukkit.broadcast(Component.text(Text.prefix("&a%s&7 is now dead!".formatted(p.getName())))); + } + + public static void unSpectator(Player p) { + p.removeScoreboardTag("ULTRALS_dead"); + p.setGameMode(GameMode.SURVIVAL); + } + + public static void spectator(Player p) { + p.addScoreboardTag("ULTRALS_dead"); + p.setGameMode(GameMode.SPECTATOR); + } +} diff --git a/src/main/java/me/trouper/ultrals/server/functions/StealFunctions.java b/src/main/java/me/trouper/ultrals/server/functions/StealFunctions.java new file mode 100644 index 0000000..507ed7b --- /dev/null +++ b/src/main/java/me/trouper/ultrals/server/functions/StealFunctions.java @@ -0,0 +1,99 @@ +package me.trouper.ultrals.server.functions; + +import me.trouper.ultrals.UltraLS; +import me.trouper.ultrals.server.util.Text; +import org.bukkit.attribute.Attribute; +import org.bukkit.attribute.AttributeInstance; +import org.bukkit.entity.Player; + +public class StealFunctions { + + public static void stealHeart(Player v, Player k) { + // If set to steal from bank first, do that + if (UltraLS.config.bank.stealDirectlyFromBank) { + stealFromBank(v,k,true); + return; + } + stealFromBar(v,k,UltraLS.config.bank.siphonFromBank); + } + + public static void stealFromBank(Player v, Player k, boolean defaultBar) { + // Start at both player's bank + // Check that k is not max, and that v has hearts + // if v does not have hearts, steal from bar + int vb = UltraLS.bank.balances.getOrDefault(v.getUniqueId().toString(),0); + int kb = UltraLS.bank.balances.getOrDefault(k.getUniqueId().toString(),0); + + if (kb + UltraLS.config.plugin.heartsFromPlayers > UltraLS.config.bank.maxBalance) { + // Killer does not have space for hearts in the bank + if (defaultBar) { + k.sendMessage(Text.prefix("Your bank is full! Hearts will be added to your bar")); + stealFromBar(v,k,false); + return; + } + k.sendMessage(Text.prefix("Your bank is full!")); + return; + } + + if (vb - UltraLS.config.plugin.heartsFromPlayers <= 0) { + // Victim does not have any hearts in the bank + if (defaultBar) { + v.sendMessage("Your bank was empty! Hearts will been taken from your bar."); + stealFromBar(v,k,false); + return; + } + v.sendMessage("Your bank was empty!"); + return; + } + + UltraLS.bank.balances.put(v.getUniqueId().toString(), vb - UltraLS.config.plugin.heartsFromPlayers); + UltraLS.bank.balances.put(k.getUniqueId().toString(), kb + UltraLS.config.plugin.heartsFromPlayers); + + UltraLS.bank.save(); + + k.sendMessage(Text.prefix("You stole &a%s&7 heart(s) from &e%s&7.".formatted(UltraLS.config.plugin.heartsFromPlayers,v.getName()))); + v.sendMessage(Text.prefix("%s stole &a%s&7 heart(s) from you.".formatted(k.getName(),UltraLS.config.plugin.heartsFromPlayers))); + } + + public static void stealFromBar(Player v, Player k, boolean defaultBank) { + // Start at both player's attributes + // Check that k is not max, and that v has enough hearts + // if v does not have enough hearts, steal from bank + AttributeInstance vh = v.getAttribute(Attribute.GENERIC_MAX_HEALTH); + AttributeInstance kh = k.getAttribute(Attribute.GENERIC_MAX_HEALTH); + + if (kh.getBaseValue() + UltraLS.config.plugin.heartsFromPlayers > UltraLS.config.plugin.maxHP) { + // Killer does not have space for hearts + if (defaultBank) { + k.sendMessage(Text.prefix("Your health bar is full! Hearts will be added to your bank.")); + stealFromBank(v,k,false); + return; + } + k.sendMessage(Text.prefix("Your health bar is full!")); + return; + } + + if (vh.getBaseValue() - UltraLS.config.plugin.heartsFromPlayers <= UltraLS.config.plugin.minHP && !UltraLS.config.plugin.deathBan && !UltraLS.config.plugin.deathSpectator) { + // Victim does not have any hearts in their health bar, and the plugin is set to not spectator, or not ban them + if (defaultBank) { + v.sendMessage("You dont have enough hearts in your health bar! Hearts will been taken from your bank."); + stealFromBank(v,k,false); + return; + } + v.sendMessage("Your health bar does not have enough hearts to be stolen from."); + return; + } else if (vh.getBaseValue() - UltraLS.config.plugin.heartsFromPlayers <= UltraLS.config.plugin.minHP && UltraLS.config.plugin.deathBan) { + DeathFunctions.ban(v); + return; // Return, because we don't want to make them have negative hearts when they rejoin + } else if (vh.getBaseValue() - UltraLS.config.plugin.heartsFromPlayers <= UltraLS.config.plugin.minHP && UltraLS.config.plugin.deathSpectator) { + DeathFunctions.spectator(v); + return; + } + + vh.setBaseValue(vh.getBaseValue() - UltraLS.config.plugin.heartsFromPlayers); + kh.setBaseValue(kh.getBaseValue() + UltraLS.config.plugin.heartsFromPlayers); + + k.sendMessage(Text.prefix("You stole &a%s&7 heart(s) from &e%s&7.".formatted(UltraLS.config.plugin.heartsFromPlayers,v.getName()))); + v.sendMessage(Text.prefix("&c%s&7 stole &a%s&7 heart(s) from you.".formatted(k.getName(),UltraLS.config.plugin.heartsFromPlayers))); + } +} diff --git a/src/main/java/me/trouper/ultrals/server/functions/TransferFunctions.java b/src/main/java/me/trouper/ultrals/server/functions/TransferFunctions.java new file mode 100644 index 0000000..728730f --- /dev/null +++ b/src/main/java/me/trouper/ultrals/server/functions/TransferFunctions.java @@ -0,0 +1,124 @@ +package me.trouper.ultrals.server.functions; + +import me.trouper.ultrals.UltraLS; +import me.trouper.ultrals.server.util.Text; +import org.bukkit.attribute.Attribute; +import org.bukkit.attribute.AttributeInstance; +import org.bukkit.entity.Player; + +public class TransferFunctions { + + public static void bankToBank(Player s, Player r, int amount) { + int sb = UltraLS.bank.balances.get(s.getUniqueId().toString()); + int rb = UltraLS.bank.balances.get(r.getUniqueId().toString()); + + if (sb - amount < 0) { + s.sendMessage(Text.prefix("&cInsufficient Balance!&7 You only have &e%s&7 hearts in your bank.".formatted(sb))); + return; + } + + if (rb + amount > UltraLS.config.bank.maxBalance) { + s.sendMessage(Text.prefix("&cCould not wire hearts! &e%s&7's bank would overflow.".formatted(r.getName()))); + r.sendMessage(Text.prefix("&e%s&7 tried to wire &c%s&7 hearts to you, but your bank was full!".formatted(s.getName(),amount))); + return; + } + + UltraLS.bank.balances.put(s.getUniqueId().toString(),sb - amount); + UltraLS.bank.balances.put(r.getUniqueId().toString(),rb + amount); + + s.sendMessage(Text.prefix("&7You have wired &a%s&7 hearts to &e%s&7. Your new balance is &a%s&7." + .formatted(amount, + r.getName(), + UltraLS.bank.balances.get(s.getUniqueId().toString())))); + r.sendMessage(Text.prefix("&e%s&7 has wired &a%s&7 hearts to you. Your new balance is &a%s&7." + .formatted(s.getName(), + amount, + UltraLS.bank.balances.get(r.getUniqueId().toString())))); + } + + public static void bankToBar(Player s, Player r, int amount) { + int sb = UltraLS.bank.balances.get(s.getUniqueId().toString()); + AttributeInstance ra = r.getAttribute(Attribute.GENERIC_MAX_HEALTH); + + if (sb - amount < 0) { + s.sendMessage(Text.prefix("&cInsufficient Balance!&7 You only have &e%s&7 hearts in your bank.".formatted(sb))); + return; + } + + if (ra.getBaseValue() + amount > UltraLS.config.plugin.maxHP) { + s.sendMessage(Text.prefix("&cCould not transfer hearts! &e%s&7's health bar would overflow.".formatted(r.getName()))); + r.sendMessage(Text.prefix("&e%s&7 tried to transfer &c%s&7 hearts to you, but your health bar was full!".formatted(s.getName(),amount))); + return; + } + + UltraLS.bank.balances.put(s.getUniqueId().toString(),sb - amount); + ra.setBaseValue(ra.getBaseValue() + amount); + + s.sendMessage(Text.prefix("&7You have transferred &a%s&7 hearts to &e%s&7. Your new balance is &a%s&7." + .formatted(amount, + r.getName(), + UltraLS.bank.balances.get(s.getUniqueId().toString()) + ))); + r.sendMessage(Text.prefix("&e%s&7 has transferred &a%s&7 hearts to you." + .formatted(s.getName(), + amount + ))); + } + + public static void barToBank(Player s, Player r, int amount) { + int rb = UltraLS.bank.balances.get(r.getUniqueId().toString()); + AttributeInstance sa = s.getAttribute(Attribute.GENERIC_MAX_HEALTH); + + if (sa.getBaseValue() - amount < UltraLS.config.plugin.minHP) { + s.sendMessage(Text.prefix("&cInsufficient Hearts.&7 You would run out and die!")); + return; + } + + if (rb + amount > UltraLS.config.bank.maxBalance) { + s.sendMessage(Text.prefix("&cCould not transfer hearts! &e%s&7's bank would overflow.".formatted(r.getName()))); + r.sendMessage(Text.prefix("&e%s&7 tried to transfer &c%s&7 hearts to you, but your bank was full!".formatted(s.getName(),amount))); + return; + } + + sa.setBaseValue(sa.getBaseValue() - amount); + UltraLS.bank.balances.put(s.getUniqueId().toString(),rb + amount); + + s.sendMessage(Text.prefix("&7You have transferred &a%s&7 hearts to &e%s&7." + .formatted(amount, + r.getName() + ))); + r.sendMessage(Text.prefix("&e%s&7 has transferred &a%s&7 hearts to you. You new balance is &a%s&7." + .formatted(s.getName(), + amount, + UltraLS.bank.balances.get(r.getUniqueId().toString()) + ))); + } + + public static void barToBar(Player s, Player r, int amount) { + AttributeInstance ra = r.getAttribute(Attribute.GENERIC_MAX_HEALTH); + AttributeInstance sa = s.getAttribute(Attribute.GENERIC_MAX_HEALTH); + + if (sa.getBaseValue() - amount < UltraLS.config.plugin.minHP) { + s.sendMessage(Text.prefix("&cInsufficient Hearts.&7 You would run out and die!")); + return; + } + + if (ra.getBaseValue() + amount > UltraLS.config.plugin.maxHP) { + s.sendMessage(Text.prefix("&cCould not give &e%s&7 hearts! Their health bar would overflow.".formatted(r.getName()))); + r.sendMessage(Text.prefix("&e%s&7 tried to give &c%s&7 hearts to you, but your health bar was full!".formatted(s.getName(),amount))); + return; + } + + sa.setBaseValue(sa.getBaseValue() - amount); + ra.setBaseValue(ra.getBaseValue() + amount); + + s.sendMessage(Text.prefix("&7You have given &a%s&7 hearts to &e%s&7." + .formatted(amount, + r.getName() + ))); + r.sendMessage(Text.prefix("&e%s&7 has given &a%s&7 hearts to you." + .formatted(s.getName(), + amount + ))); + } +} diff --git a/src/main/java/me/trouper/ultrals/server/util/CipherUtils.java b/src/main/java/me/trouper/ultrals/server/util/CipherUtils.java new file mode 100644 index 0000000..98dabb4 --- /dev/null +++ b/src/main/java/me/trouper/ultrals/server/util/CipherUtils.java @@ -0,0 +1,35 @@ +package me.trouper.ultrals.server.util; + +import javax.crypto.Cipher; +import javax.crypto.spec.SecretKeySpec; +import java.util.Base64; + +public class CipherUtils { + private static final String secretKey = "aYN8iuz1kMHU2af8iMv7UY0HTmiqr2yqserThqQQufNO8E9jBMFdgAbo5deLVM7B"; // 16, 24, or 32 bytes + private static final String algorithm = "AES"; + public static String encrypt(String strToEncrypt) { + try { + SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes(), algorithm); + Cipher cipher = Cipher.getInstance(algorithm); + cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec); + byte[] encryptedBytes = cipher.doFinal(strToEncrypt.getBytes()); + return Base64.getEncoder().encodeToString(encryptedBytes); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public static String decrypt(String strToDecrypt) { + try { + SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes(), algorithm); + Cipher cipher = Cipher.getInstance(algorithm); + cipher.init(Cipher.DECRYPT_MODE, secretKeySpec); + byte[] decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(strToDecrypt)); + return new String(decryptedBytes); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } +} diff --git a/src/main/java/me/trouper/ultrals/server/util/FileUtils.java b/src/main/java/me/trouper/ultrals/server/util/FileUtils.java new file mode 100644 index 0000000..1d85be8 --- /dev/null +++ b/src/main/java/me/trouper/ultrals/server/util/FileUtils.java @@ -0,0 +1,17 @@ +package me.trouper.ultrals.server.util; + +import me.trouper.ultrals.UltraLS; + +import java.io.File; +public class FileUtils { + public static boolean folderExists(String folderName) { + File folder = new File(UltraLS.getInstance().getDataFolder(), folderName); + return folder.exists() && folder.isDirectory(); + } + public static void createFolder(String folderName) { + File folder = new File(UltraLS.getInstance().getDataFolder(), folderName); + if (!folder.exists()) { + folder.mkdirs(); + } + } +} diff --git a/src/main/java/me/trouper/ultrals/server/util/MathUtils.java b/src/main/java/me/trouper/ultrals/server/util/MathUtils.java new file mode 100644 index 0000000..f5af139 --- /dev/null +++ b/src/main/java/me/trouper/ultrals/server/util/MathUtils.java @@ -0,0 +1,58 @@ +package me.trouper.ultrals.server.util; + +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; + +public final class MathUtils { + + public static double avg(Integer... ints) { + final List list = Arrays.stream(ints).filter(Objects::nonNull).toList(); + return avg(list); + } + + public static double avg(List ints) { + double sum = 0.0; + for (Integer i : ints) sum += i; + return sum / ints.size(); + } + + public static double round(double value, int nthPlace) { + return Math.floor(value * nthPlace) / nthPlace; + } + + public static String bytesToHex(byte[] bytes) { + StringBuilder result = new StringBuilder(); + for (byte b : bytes) { + result.append(Integer.toString((b & 0xff) + 0x100, 16).substring(1)); + } + return result.toString(); + } + + public static String SHA512(String input) { + try { + + MessageDigest digest = MessageDigest.getInstance("SHA-256"); + + + byte[] encodedHash = digest.digest(input.getBytes(StandardCharsets.UTF_8)); + + StringBuilder hexString = new StringBuilder(2 * encodedHash.length); + for (byte b : encodedHash) { + String hex = Integer.toHexString(0xff & b); + if (hex.length() == 1) { + hexString.append('0'); + } + hexString.append(hex); + } + + return hexString.toString(); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + return null; + } + } +} diff --git a/src/main/java/me/trouper/ultrals/server/util/ServerUtils.java b/src/main/java/me/trouper/ultrals/server/util/ServerUtils.java new file mode 100644 index 0000000..bbeba8a --- /dev/null +++ b/src/main/java/me/trouper/ultrals/server/util/ServerUtils.java @@ -0,0 +1,104 @@ +package me.trouper.ultrals.server.util; + +import me.trouper.ultrals.UltraLS; +import net.md_5.bungee.api.ChatMessageType; +import net.md_5.bungee.api.chat.TextComponent; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.metadata.MetadataValue; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.function.Consumer; +import java.util.function.Predicate; + +public class ServerUtils { + public static void sendCommand(String command) { + ServerUtils.verbose("Getting scheduler"); + Bukkit.getScheduler().scheduleSyncDelayedTask(UltraLS.getInstance(), () -> { + try { + ServerUtils.verbose("Attempting to run command..."); + Bukkit.getServer().dispatchCommand(Bukkit.getServer().getConsoleSender(), command); + } catch (Exception e) { + e.printStackTrace(); + } + },1); + } + public static void verbose(String message) { + if (UltraLS.config.debugMode) { + String log = "[UltraLS] [DEBUG]: " + message; + UltraLS.log.info(log); + for (Player trustedPlayer : Bukkit.getOnlinePlayers()) { + if (trustedPlayer.isOp()) { + trustedPlayer.sendMessage("§d§lUltraDupe §7[§bDEBUG§7] §8» §7" + message); + } + } + } + } + + public static List getPlayers() { + return new ArrayList<>(Bukkit.getOnlinePlayers()); + } + + public static List getStaff() { + return getPlayers().stream().filter(Player -> Player.hasPermission("ultrals.staff")).toList(); + } + + public static void forEachPlayer(Consumer consumer) { + getPlayers().forEach(consumer); + } + + public static void forEachStaff(Consumer consumer) { + getStaff().forEach(consumer); + } + + public static void dmEachPlayer(Predicate condition, String dm) { + forEachPlayer(p -> { + if (condition.test(p)) p.sendMessage(dm); + }); + } + + public static void dmEachPlayer(String dm) { + forEachPlayer(p -> p.sendMessage(dm)); + } + + public static void forEachSpecified(Iterable players, Consumer consumer) { + players.forEach(consumer); + } + + public static void forEachSpecified(Consumer consumer, Player... players) { + Arrays.stream(players).forEach(consumer); + } + public static void forEachPlayerRun(Predicate condition, Consumer task) { + forEachPlayer(p -> { + if (condition.test(p)) { + task.accept(p); + } + }); + } + public static void sendActionBar(Player p, String msg) { + p.spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(msg)); + } + + public static boolean hasBlockBelow(Player player, Material material) { + for (int y = player.getLocation().getBlockY() - 1; y >= player.getLocation().getBlockY() - 12; y--) { + if (player.getWorld().getBlockAt(player.getLocation().getBlockX(), y, player.getLocation().getBlockZ()).getType() == material) { + return true; + } + } + return false; + } + + public static boolean isVanished(Player player) { + for (MetadataValue meta : player.getMetadata("vanished")) { + if (meta.asBoolean()) return true; + } + return false; + } + + public static String[] unVanishedPlayers() { + return io.github.itzispyder.pdk.utils.ServerUtils.players(ServerUtils::isVanished).stream().map(Player::getName).toArray(String[]::new); + } +} diff --git a/src/main/java/me/trouper/ultrals/server/util/Text.java b/src/main/java/me/trouper/ultrals/server/util/Text.java new file mode 100644 index 0000000..a94e9bf --- /dev/null +++ b/src/main/java/me/trouper/ultrals/server/util/Text.java @@ -0,0 +1,90 @@ +package me.trouper.ultrals.server.util; + + +import me.trouper.ultrals.UltraLS; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class Text { + + public static String regexHighlighter(String input, String regex, String startString, String endString) { + // Create a Pattern object + Pattern pattern = Pattern.compile(regex); + + // Create a Matcher object + Matcher matcher = pattern.matcher(input); + + // StringBuffer to store the result + StringBuffer result = new StringBuffer(); + + // Find and append matches + while (matcher.find()) { + matcher.appendReplacement(result, startString + matcher.group() + endString); + } + + // Append the remainder of the input + matcher.appendTail(result); + + return result.toString(); + } + + public static final char SECTION_SYMBOL = (char)167; + + public static String color(String msg) { + return msg.replace('&', SECTION_SYMBOL); + } + public static String prefix(String text) { + String prefix = UltraLS.config.prefix; + return color(prefix + text); + } + public static String removeFirstColor(String input) { + if (input.startsWith("\u00a7")) { + if (input.length() > 2) { + return input.substring(2); + } else { + return ""; + } + } else { + return input; + } + } + public static String replaceRepeatingLetters(String input) { + if (input == null || input.isEmpty()) { + return input; + } + + StringBuilder simplifiedText = new StringBuilder(); + char currentChar = input.charAt(0); + int count = 1; + + for (int i = 1; i < input.length(); i++) { + char nextChar = input.charAt(i); + + if (Character.toLowerCase(nextChar) == Character.toLowerCase(currentChar)) { + count++; + } else { + simplifiedText.append(currentChar); + + if (count > 1) { + simplifiedText.append(currentChar); + } + + currentChar = nextChar; + count = 1; + } + } + + simplifiedText.append(currentChar); + + if (count > 1) { + simplifiedText.append(currentChar); + } + + return simplifiedText.toString(); + } + + public static String cleanName(String type) { + return type.replaceAll("_"," ").toLowerCase(); + } +} diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml new file mode 100644 index 0000000..ac95c4f --- /dev/null +++ b/src/main/resources/plugin.yml @@ -0,0 +1,35 @@ +name: UltraLS +version: '${version}' +main: me.trouper.ultrals.UltraLS +api-version: 1.19 +authors: [ TheTrouper ] +description: The only acceptable dupe plugin. +website: https://thetrouper.github.io/ +permissions: + ultrals.admin: + default: op + description: Access to give and take hearts from players + +commands: + ultrals: + description: Admin command to edit people's hearts + usage: /ultrals + permission: ultrals.admin + aliases: + - lsadmin + - adminls + - ls + - uls + deposit: + description: put hearts from you healthbar into your bank + permission: ultrals.deposit + usage: /deposit + withdraw: + description: put hearts from you bank into your health bar or inventory + permission: ultrals.withdraw + usage: /withdraw [bank|item] + giveheart: + description: Give hearts to players + permission: ultrals.giveheart + usage: /giveheart [from your; bank|bar] [to their; bank|bar] +