diff --git a/.gitignore b/.gitignore index 7284919e..5819bfd4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,157 +1,3 @@ - -# Created by https://www.gitignore.io/api/java,maven,gradle,eclipse,netbeans,intellij -# Edit at https://www.gitignore.io/?templates=java,maven,gradle,eclipse,netbeans,intellij - -### Eclipse ### - -.metadata -bin/ -tmp/ -*.tmp -*.bak -*.swp -*~.nib -local.properties -.settings/ -.loadpath -.recommenders - -# External tool builders -.externalToolBuilders/ - -# Locally stored "Eclipse launch configurations" -*.launch - -# PyDev specific (Python IDE for Eclipse) -*.pydevproject - -# CDT-specific (C/C++ Development Tooling) -.cproject - -# CDT- autotools -.autotools - -# Java annotation processor (APT) -.factorypath - -# PDT-specific (PHP Development Tools) -.buildpath - -# sbteclipse plugin -.target - -# Tern plugin -.tern-project - -# TeXlipse plugin -.texlipse - -# STS (Spring Tool Suite) -.springBeans - -# Code Recommenders -.recommenders/ - -# Annotation Processing -.apt_generated/ - -# Scala IDE specific (Scala & Java development for Eclipse) -.cache-main -.scala_dependencies -.worksheet - -### Eclipse Patch ### -# Eclipse Core -.project - -# JDT-specific (Eclipse Java Development Tools) -.classpath - -# Annotation Processing -.apt_generated - -.sts4-cache/ - -### Intellij ### -# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm -# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 - -# User-specific stuff -.idea/**/workspace.xml -.idea/**/tasks.xml -.idea/**/usage.statistics.xml -.idea/**/dictionaries -.idea/**/shelf - -# Generated files -.idea/**/contentModel.xml - -# Sensitive or high-churn files -.idea/**/dataSources/ -.idea/**/dataSources.ids -.idea/**/dataSources.local.xml -.idea/**/sqlDataSources.xml -.idea/**/dynamic.xml -.idea/**/uiDesigner.xml -.idea/**/dbnavigator.xml - -# Gradle -.idea/**/gradle.xml -.idea/**/libraries - -# Gradle and Maven with auto-import -# When using Gradle or Maven with auto-import, you should exclude module files, -# since they will be recreated, and may cause churn. Uncomment if using -# auto-import. -# .idea/modules.xml -# .idea/*.iml -# .idea/modules - -# CMake -cmake-build-*/ - -# Mongo Explorer plugin -.idea/**/mongoSettings.xml - -# File-based project format -*.iws - -# IntelliJ -out/ - -# mpeltonen/sbt-idea plugin -.idea_modules/ - -# JIRA plugin -atlassian-ide-plugin.xml - -# Cursive Clojure plugin -.idea/replstate.xml - -# Crashlytics plugin (for Android Studio and IntelliJ) -com_crashlytics_export_strings.xml -crashlytics.properties -crashlytics-build.properties -fabric.properties - -# Editor-based Rest Client -.idea/httpRequests - -# Android studio 3.1+ serialized cache file -.idea/caches/build_file_checksums.ser - -### Intellij Patch ### -# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 - -# *.iml -# modules.xml -# .idea/misc.xml -# *.ipr - -# Sonarlint plugin -.idea/sonarlint - -### Java ### # Compiled class file *.class @@ -168,6 +14,7 @@ fabric.properties *.jar *.war *.nar +*.settings *.ear *.zip *.tar.gz @@ -175,49 +22,8 @@ fabric.properties # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml hs_err_pid* - -### Maven ### -target/ -pom.xml.tag -pom.xml.releaseBackup -pom.xml.versionsBackup -pom.xml.next -release.properties -dependency-reduced-pom.xml -buildNumber.properties -.mvn/timing.properties -.mvn/wrapper/maven-wrapper.jar - -### NetBeans ### -**/nbproject/private/ -**/nbproject/Makefile-*.mk -**/nbproject/Package-*.bash -build/ -nbbuild/ -dist/ -nbdist/ -.nb-gradle/ - -### Gradle ### -.gradle - -# Ignore Gradle GUI config -gradle-app.setting - -# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) -!gradle-wrapper.jar - -# Cache of project -.gradletasknamecache - -# # Work around https://youtrack.jetbrains.com/issue/IDEA-116898 -# gradle/wrapper/gradle-wrapper.properties - -### Gradle Patch ### -**/build/ - -# End of https://www.gitignore.io/api/java,maven,gradle,eclipse,netbeans,intellij - -.idea/ -FabledSkyBlock.iml -gradle* \ No newline at end of file +/.gradle/ +/.settings/ +/.idea/ +/build/ +/bin/ diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 09acf950..259460db 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,21 +1,19 @@ +image: gradle:alpine + +variables: + path: "/builds/$CI_PROJECT_PATH" + +before_script: + - export GRADLE_USER_HOME=`pwd`/.gradle + stages: - build -variables: - name: "FabledSkyBlock" - path: "/builds/$CI_PROJECT_PATH" - version: "Build-73" - build: stage: build - image: maven:3.5.3-jdk-8 script: - - find $path/ -type f -name "*.xml" -print0 | xargs -0 sed -i -e s/maven-version-number/$version/g - - find $path/ -type f -name "*.yml" -print0 | xargs -0 sed -i -e s/maven-version-number/$version/g - - mvn clean package - - find $path/ -depth -path '*original*' -delete - - mv $path/target/*.jar $path/ + - gradle build + - mv $path/build/libs/*.jar $path/ artifacts: - name: $name-$version paths: - - "$path/*.jar" + - $path/*.jar diff --git a/LICENSE b/LICENSE index d429552d..7ecbbf10 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2018 Brianna O’Keefe +Copyright (c) 2019 Brianna O’Keefe Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software with minimal restriction, including the rights to use, copy, modify or merge while excluding the rights to publish, (re)distribute, sub-license, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: diff --git a/build.gradle b/build.gradle new file mode 100644 index 00000000..904a046e --- /dev/null +++ b/build.gradle @@ -0,0 +1,44 @@ +import org.apache.tools.ant.filters.ReplaceTokens +apply plugin: 'java' + +group 'com.songoda.fabledskyblock' +version 'Build-73' + +sourceCompatibility = 1.8 + +repositories { + mavenCentral() + jcenter() + + maven { + url 'http://repo.songoda.com/artifactory/private/' + } +} + +dependencies { + // PlaceholderAPI + implementation (group: 'be.maximvdw', name: 'placeholderapi', version: '2.5.1') + implementation (group: 'me.clip', name: 'placeholderapi', version: '2.9.2') + + // Vault + implementation (group: 'net.milkbowl', name: 'vault', version: '1.7.1') + + // Leaderheads + implementation (group: 'me.robin', name: 'leaderheads', version: '1.0') + + // EpicSpawners + implementation (group: 'com.songoda', name: 'epicspawners', version: '5.7.1') + + // WildStacker + implementation (group: 'com.bgsoftware', name: 'wildstacker-api', version: 'b14') + + // Spigot + implementation (group: 'org.spigotmc', name: 'spigot', version: '1.13.2') +} + +processResources { + filter ReplaceTokens, tokens: ["version": project.property("version")] + from (sourceSets.main.resources.srcDirs) { + include '**/*.yml' + } +} diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..44e7c4d1 --- /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-5.2.1-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100644 index 00000000..af6708ff --- /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='"-Xmx64m"' + +# 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/gradlew.bat b/gradlew.bat new file mode 100644 index 00000000..6d57edc7 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,84 @@ +@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 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" + +@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 init + +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 init + +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 + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +: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 %CMD_LINE_ARGS% + +: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/pom.xml b/pom.xml deleted file mode 100644 index 834df6a7..00000000 --- a/pom.xml +++ /dev/null @@ -1,63 +0,0 @@ - - com.songoda - FabledSkyBlock - 4.0.0 - maven-version-number - - clean package - - - 3.6.1 - org.apache.maven.plugins - maven-compiler-plugin - - 1.8 - 1.8 - - - - - - - private - http://repo.songoda.com/artifactory/private/ - - - - - be.maximvdw - placeholderapi - 2.5.1 - - - me.clip - placeholderapi - 2.9.2 - - - net.milkbowl - vault - 1.7.1 - - - me.robin - leaderheads - 1.0 - - - com.songoda - epicspawners - 5.7.1 - - - com.bgsoftware - wildstacker-api - b14 - - - org.spigotmc - spigot - 1.13.2 - - - \ No newline at end of file diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 00000000..4b64804c --- /dev/null +++ b/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'FabledSkyBlock' diff --git a/src/main/java/me/goodandevil/skyblock/levelling/Chunk.java b/src/main/java/me/goodandevil/skyblock/levelling/Chunk.java index d8be70d3..4de54f8c 100644 --- a/src/main/java/me/goodandevil/skyblock/levelling/Chunk.java +++ b/src/main/java/me/goodandevil/skyblock/levelling/Chunk.java @@ -1,84 +1,169 @@ package me.goodandevil.skyblock.levelling; import java.io.File; -import java.util.ArrayList; -import java.util.List; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; +import net.md_5.bungee.api.ChatMessageType; +import net.md_5.bungee.api.chat.TextComponent; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; import org.bukkit.ChunkSnapshot; import org.bukkit.Location; +import org.bukkit.World; import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.scheduler.BukkitRunnable; import me.goodandevil.skyblock.SkyBlock; import me.goodandevil.skyblock.island.Island; import me.goodandevil.skyblock.island.IslandEnvironment; import me.goodandevil.skyblock.island.IslandWorld; +import org.bukkit.entity.Player; public class Chunk { + private static final int MAX_CHUNKS = 150; private final SkyBlock skyblock; private Island island; - private List chunkSnapshots = new ArrayList<>(); - private boolean complete; + private int initialNumberOfChunks = -1; + private Set chunkPositions = new HashSet<>(); + private Set chunkSnapshots = new HashSet<>(); + private boolean isReady = false; + private boolean isFinished = false; public Chunk(SkyBlock skyblock, Island island) { this.skyblock = skyblock; this.island = island; - - complete = false; } - public void prepare() { - new BukkitRunnable() { - @Override - public void run() { - prepareChunkSnapshots(); - } - }.runTask(skyblock); - } + public void prepareInitial() { + Bukkit.getScheduler().runTask(this.skyblock, () -> { + FileConfiguration config = this.skyblock.getFileManager().getConfig(new File(this.skyblock.getDataFolder(), "config.yml")).getFileConfiguration(); + FileConfiguration islandData = this.skyblock.getFileManager().getConfig(new File(new File(this.skyblock.getDataFolder().toString() + "/island-data"), this.island.getOwnerUUID().toString() + ".yml")).getFileConfiguration(); - public List getChunkSnapshots() { - return chunkSnapshots; - } + boolean hasNether = config.getBoolean("Island.World.Nether.Enable") && islandData.getBoolean("Unlocked.Nether", false); + boolean hasEnd = config.getBoolean("Island.World.End.Enable") && islandData.getBoolean("Unlocked.End", false); - public boolean isComplete() { - return complete; - } - - private void prepareChunkSnapshots() { - FileConfiguration config = skyblock.getFileManager().getConfig(new File(skyblock.getDataFolder(), "config.yml")).getFileConfiguration(); - FileConfiguration islandData = skyblock.getFileManager().getConfig(new File(new File(skyblock.getDataFolder().toString() + "/island-data"), island.getOwnerUUID().toString() + ".yml")).getFileConfiguration(); - boolean hasNormal = true; - boolean hasNether = config.getBoolean("Island.World.Nether.Enable") && islandData.getBoolean("Unlocked.Nether", false); - boolean hasEnd = config.getBoolean("Island.World.End.Enable") && islandData.getBoolean("Unlocked.End", false); - - for (IslandWorld iWorld : IslandWorld.values()) { - if ((iWorld == IslandWorld.Normal && hasNormal) || (iWorld == IslandWorld.Nether && hasNether) || (iWorld == IslandWorld.End && hasEnd)) { - Location islandLocation = island.getLocation(iWorld, IslandEnvironment.Island); - - Location minLocation = new Location(islandLocation.getWorld(), - islandLocation.getBlockX() - island.getRadius(), 0, - islandLocation.getBlockZ() - island.getRadius()); - Location maxLocation = new Location(islandLocation.getWorld(), - islandLocation.getBlockX() + island.getRadius(), islandLocation.getWorld().getMaxHeight(), - islandLocation.getBlockZ() + island.getRadius()); - - int MinX = Math.min(maxLocation.getBlockX(), minLocation.getBlockX()); - int MinZ = Math.min(maxLocation.getBlockZ(), minLocation.getBlockZ()); - - int MaxX = Math.max(maxLocation.getBlockX(), minLocation.getBlockX()); - int MaxZ = Math.max(maxLocation.getBlockZ(), minLocation.getBlockZ()); - - for (int x = MinX - 16; x <= MaxX + 16; x += 16) { - for (int z = MinZ - 16; z <= MaxZ + 16; z += 16) { - org.bukkit.Chunk chunk = islandLocation.getWorld().getBlockAt(x, 0, z).getChunk(); - chunkSnapshots.add(chunk.getChunkSnapshot()); - } + for (IslandWorld islandWorld : IslandWorld.values()) { + if (islandWorld == IslandWorld.Normal || (islandWorld == IslandWorld.Nether && hasNether) || (islandWorld == IslandWorld.End && hasEnd)) { + this.getChunksToScan(islandWorld); } } + + this.initialNumberOfChunks = this.chunkPositions.size(); + + this.prepareNextChunkSnapshots(); + }); + } + + public boolean isReadyToScan() { + return this.isReady; + } + + public Set getAvailableChunkSnapshots() { + this.isReady = false; + return this.chunkSnapshots; + } + + public boolean isFinished() { + return this.isFinished; + } + + public void prepareNextChunkSnapshots() { + Bukkit.getScheduler().runTask(this.skyblock, () -> { + this.chunkSnapshots.clear(); + + Iterator it = this.chunkPositions.iterator(); + if (!it.hasNext()) { + this.isReady = true; + this.isFinished = true; + this.sendFinishedMessage(); + return; + } + + int percentComplete = (int)((1 - ((double)this.chunkPositions.size() / this.initialNumberOfChunks)) * 100); + this.sendPercentMessage(percentComplete); + + while (it.hasNext() && this.chunkSnapshots.size() < MAX_CHUNKS) { + ChunkPosition chunkPosition = it.next(); + World world = chunkPosition.getWorld(); + int x = chunkPosition.getX(); + int z = chunkPosition.getZ(); + if (!world.isChunkLoaded(x, z)) { + world.loadChunk(x, z); + this.chunkSnapshots.add(world.getChunkAt(x, z).getChunkSnapshot()); + world.unloadChunk(x, z); + } else { + this.chunkSnapshots.add(world.getChunkAt(x, z).getChunkSnapshot()); + } + it.remove(); + } + + this.isReady = true; + }); + } + + private void sendPercentMessage(int percent) { + String message = ChatColor.translateAlternateColorCodes('&', + this.skyblock.getFileManager() + .getConfig(new File(this.skyblock.getDataFolder(), "language.yml")) + .getFileConfiguration().getString("Command.Island.Level.Scanning.Progress.Message") + .replace("%percent", String.valueOf(percent))); + for (Player player : this.skyblock.getIslandManager().getPlayersAtIsland(this.island)) { + player.spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(message)); + } + } + + private void sendFinishedMessage() { + String message = ChatColor.translateAlternateColorCodes('&', this.skyblock.getFileManager() + .getConfig(new File(this.skyblock.getDataFolder(), "language.yml")) + .getFileConfiguration().getString("Command.Island.Level.Scanning.Finished.Message")); + for (Player player : this.skyblock.getIslandManager().getPlayersAtIsland(this.island)) { + player.spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(message)); + } + } + + private void getChunksToScan(IslandWorld islandWorld) { + Location islandLocation = this.island.getLocation(islandWorld, IslandEnvironment.Island); + World world = islandLocation.getWorld(); + + Location minLocation = new Location(world, islandLocation.getBlockX() - this.island.getRadius(), 0, islandLocation.getBlockZ() - this.island.getRadius()); + Location maxLocation = new Location(world, islandLocation.getBlockX() + this.island.getRadius(), world.getMaxHeight(), islandLocation.getBlockZ() + this.island.getRadius()); + + int minX = Math.min(maxLocation.getBlockX(), minLocation.getBlockX()); + int minZ = Math.min(maxLocation.getBlockZ(), minLocation.getBlockZ()); + + int maxX = Math.max(maxLocation.getBlockX(), minLocation.getBlockX()); + int maxZ = Math.max(maxLocation.getBlockZ(), minLocation.getBlockZ()); + + for (int x = minX; x < maxX + 16; x += 16) { + for (int z = minZ; z < maxZ + 16; z += 16) { + this.chunkPositions.add(new ChunkPosition(world, x >> 4, z >> 4)); + } + } + } + + private class ChunkPosition { + private World world; + private int x, z; + + public ChunkPosition(World world, int x, int z) { + this.world = world; + this.x = x; + this.z = z; } - complete = true; + public World getWorld() { + return this.world; + } + + public int getX() { + return this.x; + } + + public int getZ() { + return this.z; + } } } diff --git a/src/main/java/me/goodandevil/skyblock/levelling/LevellingManager.java b/src/main/java/me/goodandevil/skyblock/levelling/LevellingManager.java index b9b739a0..9f901255 100644 --- a/src/main/java/me/goodandevil/skyblock/levelling/LevellingManager.java +++ b/src/main/java/me/goodandevil/skyblock/levelling/LevellingManager.java @@ -42,37 +42,44 @@ public class LevellingManager { StackableManager stackableManager = skyblock.getStackableManager(); Chunk chunk = new Chunk(skyblock, island); - chunk.prepare(); + chunk.prepareInitial(); int NMSVersion = NMSUtil.getVersionNumber(); + int height = 0; + + for (IslandWorld worldList : IslandWorld.values()) { + org.bukkit.World world = worldManager.getWorld(worldList); + + if (height == 0 || height > world.getMaxHeight()) { + height = world.getMaxHeight(); + } + } + + int worldMaxHeight = height; + + boolean isEpicSpawnersEnabled = Bukkit.getPluginManager().isPluginEnabled("EpicSpawners"); + boolean isWildStackerEnabled = Bukkit.getPluginManager().isPluginEnabled("WildStacker"); + + Map levellingData = new HashMap<>(); + new BukkitRunnable() { @Override public void run() { - if (!chunk.isComplete()) return; - cancel(); + if (!chunk.isReadyToScan()) return; + + if (chunk.isFinished()) { + finalizeMaterials(levellingData, player, island); + cancel(); + return; + } Method getBlockTypeMethod = null; Method getBlockTypeIdMethod = null; Method getBlockTypeDataMethod = null; Method getMaterialMethod = null; - int worldMaxHeight = 0; - - for (IslandWorld worldList : IslandWorld.values()) { - org.bukkit.World world = worldManager.getWorld(worldList); - - if (worldMaxHeight == 0 || worldMaxHeight > world.getMaxHeight()) { - worldMaxHeight = world.getMaxHeight(); - } - } - - boolean isEpicSpawnersEnabled = Bukkit.getPluginManager().isPluginEnabled("EpicSpawners"); - boolean isWildStackerEnabled = Bukkit.getPluginManager().isPluginEnabled("WildStacker"); - - Map levellingData = new HashMap<>(); - - for (ChunkSnapshot chunkSnapshotList : chunk.getChunkSnapshots()) { + for (ChunkSnapshot chunkSnapshotList : chunk.getAvailableChunkSnapshots()) { for (int x = 0; x < 16; x++) { for (int z = 0; z < 16; z++) { for (int y = 0; y < worldMaxHeight; y++) { @@ -175,38 +182,42 @@ public class LevellingManager { } } - Map materials = new HashMap<>(); - for (LevellingData data : levellingData.keySet()) { - long amount = levellingData.get(data); - if (data.getMaterials() != null) { - materials.put(data.getMaterials().name(), amount); - } - } - - if (materials.size() == 0) { - if (player != null) { - skyblock.getMessageManager().sendMessage(player, skyblock.getFileManager() - .getConfig(new File(skyblock.getDataFolder(), "language.yml")) - .getFileConfiguration().getString("Command.Island.Level.Materials.Message")); - skyblock.getSoundManager().playSound(player, Sounds.VILLAGER_NO.bukkitSound(), 1.0F, 1.0F); - } - } else { - IslandLevel level = island.getLevel(); - level.setLastCalculatedPoints(level.getPoints()); - level.setLastCalculatedLevel(level.getLevel()); - level.setMaterials(materials); - - Bukkit.getServer().getPluginManager().callEvent( - new IslandLevelChangeEvent(island.getAPIWrapper(), island.getAPIWrapper().getLevel())); - - if (player != null) { - me.goodandevil.skyblock.menus.Levelling.getInstance().open(player); - } - } + chunk.prepareNextChunkSnapshots(); } }.runTaskTimerAsynchronously(skyblock, 0L, 1L); } + private void finalizeMaterials(Map levellingData, Player player, Island island) { + Map materials = new HashMap<>(); + for (LevellingData data : levellingData.keySet()) { + long amount = levellingData.get(data); + if (data.getMaterials() != null) { + materials.put(data.getMaterials().name(), amount); + } + } + + if (materials.size() == 0) { + if (player != null) { + skyblock.getMessageManager().sendMessage(player, skyblock.getFileManager() + .getConfig(new File(skyblock.getDataFolder(), "language.yml")) + .getFileConfiguration().getString("Command.Island.Level.Materials.Message")); + skyblock.getSoundManager().playSound(player, Sounds.VILLAGER_NO.bukkitSound(), 1.0F, 1.0F); + } + } else { + IslandLevel level = island.getLevel(); + level.setLastCalculatedPoints(level.getPoints()); + level.setLastCalculatedLevel(level.getLevel()); + level.setMaterials(materials); + + Bukkit.getServer().getPluginManager().callEvent( + new IslandLevelChangeEvent(island.getAPIWrapper(), island.getAPIWrapper().getLevel())); + + if (player != null) { + me.goodandevil.skyblock.menus.Levelling.getInstance().open(player); + } + } + } + public void registerMaterials() { Config config = skyblock.getFileManager().getConfig(new File(skyblock.getDataFolder(), "levelling.yml")); FileConfiguration configLoad = config.getFileConfiguration(); diff --git a/src/main/resources/LICENSE b/src/main/resources/LICENSE deleted file mode 100644 index d429552d..00000000 --- a/src/main/resources/LICENSE +++ /dev/null @@ -1,9 +0,0 @@ -Copyright (c) 2018 Brianna O’Keefe - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software with minimal restriction, including the rights to use, copy, modify or merge while excluding the rights to publish, (re)distribute, sub-license, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The same distribution rights and limitations above shall similarly apply to any and all source code, and other means that can be used to emulate this work. - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/src/main/resources/language.yml b/src/main/resources/language.yml index 8d2a3d07..f980ffa8 100644 --- a/src/main/resources/language.yml +++ b/src/main/resources/language.yml @@ -458,6 +458,11 @@ Command: Message: "&bSkyBlock &8| &aInfo&8: &7&oProcessing Island level request... Please wait!" Loading: Message: "&bSkyBlock &8| &aInfo&8: &7&oLoading Island Materials... Please wait!" + Scanning: + Progress: + Message: "&eScanning island level: &b%percent%" + Finished: + Message: "&aIsland level scan complete!" Owner: Yourself: Message: "&bSkyBlock &8| &cError&8: &eYou are not an Island owner." diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 8f878b3f..a0abcbf6 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,6 +1,6 @@ name: FabledSkyBlock main: me.goodandevil.skyblock.SkyBlock -version: maven-version-number +version: @version@ api-version: 1.13 description: A unique SkyBlock plugin author: Songoda