Compare commits
No commits in common. 'master' and 'v1.2.1' have entirely different histories.
@ -0,0 +1,13 @@
|
|||||||
|
image: openjdk
|
||||||
|
|
||||||
|
matrix:
|
||||||
|
- env: SCRIPT=shadowJar
|
||||||
|
|
||||||
|
install:
|
||||||
|
- gradle dependencies
|
||||||
|
|
||||||
|
script:
|
||||||
|
- if [[ "SCRIPT" ]]; then gradle $SCRIPT; fi
|
||||||
|
|
||||||
|
cache:
|
||||||
|
- .gradle
|
@ -1,42 +0,0 @@
|
|||||||
name: Gradle Build
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
push:
|
|
||||||
branches: [ main, develop, actions ]
|
|
||||||
pull_request:
|
|
||||||
branches: [ main, develop, actions ]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
shadowJar:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
|
|
||||||
- name: Setup Java
|
|
||||||
uses: actions/setup-java@v1
|
|
||||||
with:
|
|
||||||
java-version: 1.8
|
|
||||||
|
|
||||||
- name: Cache build data
|
|
||||||
uses: actions/cache@v2
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
~/.gradle/caches
|
|
||||||
~/.gradle/wrapper
|
|
||||||
key: ${{ runner.os }}-gradle-${{ hashFiles('build.gradle') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-gradle-
|
|
||||||
|
|
||||||
- name: Build Jar
|
|
||||||
run: chmod +x gradlew && ./gradlew shadowJar
|
|
||||||
|
|
||||||
- name: Upload artifacts
|
|
||||||
uses: actions/upload-artifact@v2
|
|
||||||
with:
|
|
||||||
name: chunkmaster
|
|
||||||
path: build/libs/chunkmaster-*.jar
|
|
||||||
|
|
||||||
- name: Cleanup Gradle Cache
|
|
||||||
run: |
|
|
||||||
rm -f ~/.gradle/caches/modules-2/modules-2.lock
|
|
||||||
rm -f ~/.gradle/caches/modules-2/gc.properties
|
|
@ -1,36 +0,0 @@
|
|||||||
name: Gradle Unit Tests
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
push:
|
|
||||||
branches: [ main, develop, actions, feature/unit-tests ]
|
|
||||||
pull_request:
|
|
||||||
branches: [ main, develop, actions, feature/unit-tests ]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
test:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
|
|
||||||
- name: Setup Java
|
|
||||||
uses: actions/setup-java@v1
|
|
||||||
with:
|
|
||||||
java-version: 1.8
|
|
||||||
|
|
||||||
- name: Cache build data
|
|
||||||
uses: actions/cache@v2
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
~/.gradle/caches
|
|
||||||
~/.gradle/wrapper
|
|
||||||
key: ${{ runner.os }}-gradle-${{ hashFiles('build.gradle') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-gradle-
|
|
||||||
|
|
||||||
- name: Test
|
|
||||||
run: chmod +x gradlew && ./gradlew test
|
|
||||||
|
|
||||||
- name: Cleanup Gradle Cache
|
|
||||||
run: |
|
|
||||||
rm -f ~/.gradle/caches/modules-2/modules-2.lock
|
|
||||||
rm -f ~/.gradle/caches/modules-2/gc.properties
|
|
@ -1,4 +1,6 @@
|
|||||||
|
gradle
|
||||||
.gradle
|
.gradle
|
||||||
.idea
|
.idea
|
||||||
build
|
build
|
||||||
out
|
out
|
||||||
|
gradlew*
|
@ -1,2 +1 @@
|
|||||||
kotlin.code.style=official
|
kotlin.code.style=official
|
||||||
PLUGIN_VERSION=1.4.2
|
|
Binary file not shown.
@ -1,5 +0,0 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
|
||||||
distributionPath=wrapper/dists
|
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.2-bin.zip
|
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
|
||||||
zipStorePath=wrapper/dists
|
|
@ -1,185 +0,0 @@
|
|||||||
#!/usr/bin/env sh
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright 2015 the original author or 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
|
|
||||||
##
|
|
||||||
##############################################################################
|
|
||||||
|
|
||||||
# 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" "-Xms64m"'
|
|
||||||
|
|
||||||
# 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 or MSYS, switch paths to Windows format before running java
|
|
||||||
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; 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=`expr $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"
|
|
||||||
|
|
||||||
exec "$JAVACMD" "$@"
|
|
@ -1,89 +0,0 @@
|
|||||||
@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
|
|
@ -1,44 +0,0 @@
|
|||||||
package net.trivernis.chunkmaster.commands
|
|
||||||
|
|
||||||
import net.trivernis.chunkmaster.Chunkmaster
|
|
||||||
import net.trivernis.chunkmaster.lib.Subcommand
|
|
||||||
import org.bukkit.command.Command
|
|
||||||
import org.bukkit.command.CommandSender
|
|
||||||
|
|
||||||
class CmdCompleted(private val plugin: Chunkmaster) : Subcommand {
|
|
||||||
override val name = "completed"
|
|
||||||
|
|
||||||
override fun execute(sender: CommandSender, args: List<String>): Boolean {
|
|
||||||
plugin.sqliteManager.completedGenerationTasks.getCompletedTasks().thenAccept { tasks ->
|
|
||||||
val worlds = tasks.map { it.world }.toHashSet()
|
|
||||||
var response = "\n" + plugin.langManager.getLocalized("COMPLETED_TASKS_HEADER") + "\n\n"
|
|
||||||
|
|
||||||
for (world in worlds) {
|
|
||||||
response += plugin.langManager.getLocalized("COMPLETED_WORLD_HEADER", world) + "\n"
|
|
||||||
|
|
||||||
for (task in tasks.filter { it.world == world }) {
|
|
||||||
response += plugin.langManager.getLocalized(
|
|
||||||
"COMPLETED_TASK_ENTRY",
|
|
||||||
task.id,
|
|
||||||
task.radius,
|
|
||||||
task.center.x,
|
|
||||||
task.center.z,
|
|
||||||
task.shape
|
|
||||||
) + "\n"
|
|
||||||
}
|
|
||||||
response += "\n"
|
|
||||||
}
|
|
||||||
sender.sendMessage(response)
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onTabComplete(
|
|
||||||
sender: CommandSender,
|
|
||||||
command: Command,
|
|
||||||
alias: String,
|
|
||||||
args: List<String>
|
|
||||||
): MutableList<String> {
|
|
||||||
return mutableListOf()
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,92 +0,0 @@
|
|||||||
package net.trivernis.chunkmaster.lib
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Better argument parser for command arguments
|
|
||||||
*/
|
|
||||||
class ArgParser {
|
|
||||||
private var input = ""
|
|
||||||
private var position = 0
|
|
||||||
private var currentChar = ' '
|
|
||||||
private var escaped = false
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parses arguments from a string and respects quotes
|
|
||||||
*/
|
|
||||||
fun parseArguments(arguments: String): List<String> {
|
|
||||||
if (arguments.isEmpty()) {
|
|
||||||
return emptyList()
|
|
||||||
}
|
|
||||||
|
|
||||||
input = arguments
|
|
||||||
position = 0
|
|
||||||
currentChar = input[position]
|
|
||||||
escaped = false
|
|
||||||
val args = ArrayList<String>()
|
|
||||||
var arg = ""
|
|
||||||
|
|
||||||
while (!endReached()) {
|
|
||||||
nextCharacter()
|
|
||||||
|
|
||||||
if (currentChar == '\\' && !escaped) {
|
|
||||||
escaped = true
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentChar.isWhitespace() && !escaped) {
|
|
||||||
if (arg.isNotBlank()) {
|
|
||||||
args.add(arg)
|
|
||||||
}
|
|
||||||
arg = ""
|
|
||||||
} else if (currentChar == '"' && !escaped) {
|
|
||||||
if (arg.isNotBlank()) {
|
|
||||||
args.add(arg)
|
|
||||||
}
|
|
||||||
arg = parseString()
|
|
||||||
if (arg.isNotBlank()) {
|
|
||||||
args.add(arg)
|
|
||||||
}
|
|
||||||
arg = ""
|
|
||||||
} else {
|
|
||||||
arg += currentChar
|
|
||||||
}
|
|
||||||
escaped = false
|
|
||||||
}
|
|
||||||
if (arg.isNotBlank()) {
|
|
||||||
args.add(arg)
|
|
||||||
}
|
|
||||||
return args
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parses an enquoted string
|
|
||||||
*/
|
|
||||||
private fun parseString(): String {
|
|
||||||
var output = ""
|
|
||||||
|
|
||||||
while (!endReached()) {
|
|
||||||
nextCharacter()
|
|
||||||
|
|
||||||
if (currentChar == '\\') {
|
|
||||||
escaped = !escaped
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentChar == '"' && !escaped) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
output += currentChar
|
|
||||||
escaped = false
|
|
||||||
}
|
|
||||||
return output
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun nextCharacter() {
|
|
||||||
if (!endReached()) {
|
|
||||||
currentChar = input[position++]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun endReached(): Boolean {
|
|
||||||
return position >= input.length
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
package net.trivernis.chunkmaster.lib.database
|
|
||||||
|
|
||||||
import net.trivernis.chunkmaster.lib.generation.ChunkCoordinates
|
|
||||||
|
|
||||||
data class CompletedGenerationTask(
|
|
||||||
val id: Int,
|
|
||||||
val world: String,
|
|
||||||
val radius: Int,
|
|
||||||
val center: ChunkCoordinates,
|
|
||||||
val shape: String
|
|
||||||
)
|
|
@ -1,80 +0,0 @@
|
|||||||
package net.trivernis.chunkmaster.lib.database
|
|
||||||
|
|
||||||
import net.trivernis.chunkmaster.lib.generation.ChunkCoordinates
|
|
||||||
import java.sql.ResultSet
|
|
||||||
import java.util.concurrent.CompletableFuture
|
|
||||||
|
|
||||||
class CompletedGenerationTasks(private val sqliteManager: SqliteManager) {
|
|
||||||
/**
|
|
||||||
* Returns the list of all completed tasks
|
|
||||||
*/
|
|
||||||
fun getCompletedTasks(): CompletableFuture<List<CompletedGenerationTask>> {
|
|
||||||
val completableFuture = CompletableFuture<List<CompletedGenerationTask>>()
|
|
||||||
|
|
||||||
sqliteManager.executeStatement("SELECT * FROM completed_generation_tasks", HashMap()) { res ->
|
|
||||||
val tasks = ArrayList<CompletedGenerationTask>()
|
|
||||||
|
|
||||||
while (res!!.next()) {
|
|
||||||
tasks.add(mapSqlResponseToWrapperObject(res))
|
|
||||||
}
|
|
||||||
completableFuture.complete(tasks)
|
|
||||||
}
|
|
||||||
return completableFuture
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a list of completed tasks for a world
|
|
||||||
*/
|
|
||||||
fun getCompletedTasksForWorld(world: String): CompletableFuture<List<CompletedGenerationTask>> {
|
|
||||||
val completableFuture = CompletableFuture<List<CompletedGenerationTask>>()
|
|
||||||
|
|
||||||
sqliteManager.executeStatement(
|
|
||||||
"SELECT * FROM completed_generation_tasks WHERE world = ?",
|
|
||||||
hashMapOf(1 to world)
|
|
||||||
) { res ->
|
|
||||||
val tasks = ArrayList<CompletedGenerationTask>()
|
|
||||||
|
|
||||||
while (res!!.next()) {
|
|
||||||
tasks.add(mapSqlResponseToWrapperObject(res))
|
|
||||||
}
|
|
||||||
completableFuture.complete(tasks)
|
|
||||||
}
|
|
||||||
return completableFuture
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun mapSqlResponseToWrapperObject(res: ResultSet): CompletedGenerationTask {
|
|
||||||
val id = res.getInt("id")
|
|
||||||
val world = res.getString("world")
|
|
||||||
val center = ChunkCoordinates(res.getInt("center_x"), res.getInt("center_z"))
|
|
||||||
val radius = res.getInt("completed_radius")
|
|
||||||
val shape = res.getString("shape")
|
|
||||||
return CompletedGenerationTask(id, world, radius, center, shape)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a completed task
|
|
||||||
*/
|
|
||||||
fun addCompletedTask(
|
|
||||||
id: Int,
|
|
||||||
world: String,
|
|
||||||
radius: Int,
|
|
||||||
center: ChunkCoordinates,
|
|
||||||
shape: String
|
|
||||||
): CompletableFuture<Void> {
|
|
||||||
val completableFuture = CompletableFuture<Void>()
|
|
||||||
sqliteManager.executeStatement(
|
|
||||||
"INSERT INTO completed_generation_tasks (id, world, completed_radius, center_x, center_z, shape) VALUES (?, ?, ?, ?, ?, ?)",
|
|
||||||
hashMapOf(
|
|
||||||
1 to id,
|
|
||||||
2 to world,
|
|
||||||
3 to radius,
|
|
||||||
4 to center.x,
|
|
||||||
5 to center.z,
|
|
||||||
6 to shape,
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
completableFuture.complete(null)
|
|
||||||
}
|
|
||||||
return completableFuture
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
package net.trivernis.chunkmaster.lib.database
|
|
||||||
|
|
||||||
import net.trivernis.chunkmaster.lib.generation.ChunkCoordinates
|
|
||||||
import net.trivernis.chunkmaster.lib.generation.TaskState
|
|
||||||
|
|
||||||
data class GenerationTaskData(
|
|
||||||
val id: Int,
|
|
||||||
val world: String,
|
|
||||||
val radius: Int,
|
|
||||||
val shape: String,
|
|
||||||
val state: TaskState,
|
|
||||||
val center: ChunkCoordinates,
|
|
||||||
val last: ChunkCoordinates
|
|
||||||
)
|
|
@ -1,104 +0,0 @@
|
|||||||
package net.trivernis.chunkmaster.lib.database
|
|
||||||
|
|
||||||
import net.trivernis.chunkmaster.lib.generation.ChunkCoordinates
|
|
||||||
import net.trivernis.chunkmaster.lib.generation.TaskState
|
|
||||||
import java.util.concurrent.CompletableFuture
|
|
||||||
|
|
||||||
class GenerationTasks(private val sqliteManager: SqliteManager) {
|
|
||||||
/**
|
|
||||||
* Returns all stored generation tasks
|
|
||||||
*/
|
|
||||||
fun getGenerationTasks(): CompletableFuture<List<GenerationTaskData>> {
|
|
||||||
val completableFuture = CompletableFuture<List<GenerationTaskData>>()
|
|
||||||
|
|
||||||
sqliteManager.executeStatement("SELECT * FROM generation_tasks", HashMap()) { res ->
|
|
||||||
val tasks = ArrayList<GenerationTaskData>()
|
|
||||||
|
|
||||||
while (res!!.next()) {
|
|
||||||
val id = res.getInt("id")
|
|
||||||
val world = res.getString("world")
|
|
||||||
val center = ChunkCoordinates(res.getInt("center_x"), res.getInt("center_z"))
|
|
||||||
val last = ChunkCoordinates(res.getInt("last_x"), res.getInt("last_z"))
|
|
||||||
val radius = res.getInt("radius")
|
|
||||||
val shape = res.getString("shape")
|
|
||||||
val state = stringToState(res.getString("state"))
|
|
||||||
val taskData = GenerationTaskData(id, world, radius, shape, state, center, last)
|
|
||||||
if (tasks.find { it.id == id } == null) {
|
|
||||||
tasks.add(taskData)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
completableFuture.complete(tasks)
|
|
||||||
}
|
|
||||||
return completableFuture
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a generation task to the database
|
|
||||||
*/
|
|
||||||
fun addGenerationTask(world: String, center: ChunkCoordinates, radius: Int, shape: String): CompletableFuture<Int> {
|
|
||||||
val completableFuture = CompletableFuture<Int>()
|
|
||||||
sqliteManager.executeStatement(
|
|
||||||
"""
|
|
||||||
INSERT INTO generation_tasks (center_x, center_z, last_x, last_z, world, radius, shape)
|
|
||||||
values (?, ?, ?, ?, ?, ?, ?)""",
|
|
||||||
hashMapOf(
|
|
||||||
1 to center.x,
|
|
||||||
2 to center.z,
|
|
||||||
3 to center.x,
|
|
||||||
4 to center.z,
|
|
||||||
5 to world,
|
|
||||||
6 to radius,
|
|
||||||
7 to shape
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
sqliteManager.executeStatement(
|
|
||||||
"""
|
|
||||||
SELECT id FROM generation_tasks ORDER BY id DESC LIMIT 1
|
|
||||||
""".trimIndent(), HashMap()
|
|
||||||
) {
|
|
||||||
it!!.next()
|
|
||||||
completableFuture.complete(it.getInt("id"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return completableFuture
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deletes a generationTask from the database
|
|
||||||
*/
|
|
||||||
fun deleteGenerationTask(id: Int): CompletableFuture<Void> {
|
|
||||||
val completableFuture = CompletableFuture<Void>()
|
|
||||||
sqliteManager.executeStatement("DELETE FROM generation_tasks WHERE id = ?;", hashMapOf(1 to id)) {
|
|
||||||
completableFuture.complete(null)
|
|
||||||
}
|
|
||||||
return completableFuture
|
|
||||||
}
|
|
||||||
|
|
||||||
fun updateGenerationTask(id: Int, last: ChunkCoordinates, state: TaskState): CompletableFuture<Void> {
|
|
||||||
val completableFuture = CompletableFuture<Void>()
|
|
||||||
sqliteManager.executeStatement(
|
|
||||||
"""
|
|
||||||
UPDATE generation_tasks SET last_x = ?, last_z = ?, state = ?
|
|
||||||
WHERE id = ?
|
|
||||||
""".trimIndent(),
|
|
||||||
hashMapOf(1 to last.x, 2 to last.z, 3 to state.toString(), 4 to id)
|
|
||||||
) {
|
|
||||||
completableFuture.complete(null)
|
|
||||||
}
|
|
||||||
return completableFuture
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts a string into a task state
|
|
||||||
*/
|
|
||||||
private fun stringToState(stringState: String): TaskState {
|
|
||||||
TaskState.valueOf(stringState)
|
|
||||||
return when (stringState) {
|
|
||||||
"GENERATING" -> TaskState.GENERATING
|
|
||||||
"VALIDATING" -> TaskState.VALIDATING
|
|
||||||
"PAUSING" -> TaskState.PAUSING
|
|
||||||
"CORRECTING" -> TaskState.CORRECTING
|
|
||||||
else -> TaskState.GENERATING
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,84 +0,0 @@
|
|||||||
package net.trivernis.chunkmaster.lib.database
|
|
||||||
|
|
||||||
import net.trivernis.chunkmaster.lib.generation.ChunkCoordinates
|
|
||||||
import java.util.concurrent.CompletableFuture
|
|
||||||
import kotlin.math.ceil
|
|
||||||
|
|
||||||
class PendingChunks(private val sqliteManager: SqliteManager) {
|
|
||||||
|
|
||||||
private val insertionCount = 300
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a list of pending chunks for a taskId
|
|
||||||
*/
|
|
||||||
fun getPendingChunks(taskId: Int): CompletableFuture<List<ChunkCoordinates>> {
|
|
||||||
val completableFuture = CompletableFuture<List<ChunkCoordinates>>()
|
|
||||||
sqliteManager.executeStatement("SELECT * FROM pending_chunks WHERE task_id = ?", hashMapOf(1 to taskId)) {
|
|
||||||
val pendingChunks = ArrayList<ChunkCoordinates>()
|
|
||||||
while (it!!.next()) {
|
|
||||||
pendingChunks.add(ChunkCoordinates(it.getInt("chunk_x"), it.getInt("chunk_z")))
|
|
||||||
}
|
|
||||||
completableFuture.complete(pendingChunks)
|
|
||||||
}
|
|
||||||
return completableFuture
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clears all pending chunks of a task
|
|
||||||
*/
|
|
||||||
fun clearPendingChunks(taskId: Int): CompletableFuture<Void> {
|
|
||||||
val completableFuture = CompletableFuture<Void>()
|
|
||||||
sqliteManager.executeStatement("DELETE FROM pending_chunks WHERE task_id = ?", hashMapOf(1 to taskId)) {
|
|
||||||
completableFuture.complete(null)
|
|
||||||
}
|
|
||||||
return completableFuture
|
|
||||||
}
|
|
||||||
|
|
||||||
fun addPendingChunks(taskId: Int, pendingChunks: List<ChunkCoordinates>): CompletableFuture<Void> {
|
|
||||||
val futures = ArrayList<CompletableFuture<Void>>()
|
|
||||||
val statementCount = ceil(pendingChunks.size.toDouble() / insertionCount).toInt()
|
|
||||||
|
|
||||||
for (i in 0 until statementCount) {
|
|
||||||
futures.add(
|
|
||||||
insertPendingChunks(
|
|
||||||
taskId,
|
|
||||||
pendingChunks.subList(
|
|
||||||
i * insertionCount,
|
|
||||||
((i * insertionCount) + insertionCount).coerceAtMost(pendingChunks.size)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (futures.size > 0) {
|
|
||||||
return CompletableFuture.allOf(*futures.toTypedArray())
|
|
||||||
} else {
|
|
||||||
return CompletableFuture.supplyAsync { null }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds pending chunks for a taskid
|
|
||||||
*/
|
|
||||||
private fun insertPendingChunks(taskId: Int, pendingChunks: List<ChunkCoordinates>): CompletableFuture<Void> {
|
|
||||||
val completableFuture = CompletableFuture<Void>()
|
|
||||||
if (pendingChunks.isEmpty()) {
|
|
||||||
completableFuture.complete(null)
|
|
||||||
} else {
|
|
||||||
var sql = "INSERT INTO pending_chunks (task_id, chunk_x, chunk_z) VALUES"
|
|
||||||
var index = 1
|
|
||||||
val valueMap = HashMap<Int, Any>()
|
|
||||||
|
|
||||||
for (coordinates in pendingChunks) {
|
|
||||||
sql += "(?, ?, ?),"
|
|
||||||
valueMap[index++] = taskId
|
|
||||||
valueMap[index++] = coordinates.x
|
|
||||||
valueMap[index++] = coordinates.z
|
|
||||||
}
|
|
||||||
sqliteManager.executeStatement(sql.removeSuffix(","), valueMap) {
|
|
||||||
completableFuture.complete(null)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return completableFuture
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,83 +0,0 @@
|
|||||||
package net.trivernis.chunkmaster.lib.database
|
|
||||||
|
|
||||||
import java.util.concurrent.CompletableFuture
|
|
||||||
|
|
||||||
class WorldProperties(private val sqliteManager: SqliteManager) {
|
|
||||||
|
|
||||||
private val properties = HashMap<String, Pair<Int, Int>>()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the world center for one world
|
|
||||||
*/
|
|
||||||
fun getWorldCenter(worldName: String): CompletableFuture<Pair<Int, Int>?> {
|
|
||||||
val completableFuture = CompletableFuture<Pair<Int, Int>?>()
|
|
||||||
|
|
||||||
if (properties[worldName] != null) {
|
|
||||||
completableFuture.complete(properties[worldName])
|
|
||||||
} else {
|
|
||||||
sqliteManager.executeStatement("SELECT * FROM world_properties WHERE name = ?", hashMapOf(1 to worldName)) {
|
|
||||||
if (it != null && it.next()) {
|
|
||||||
completableFuture.complete(Pair(it.getInt("center_x"), it.getInt("center_z")))
|
|
||||||
} else {
|
|
||||||
completableFuture.complete(null)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return completableFuture
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the center of a world
|
|
||||||
*/
|
|
||||||
fun setWorldCenter(worldName: String, center: Pair<Int, Int>): CompletableFuture<Void> {
|
|
||||||
val completableFuture = CompletableFuture<Void>()
|
|
||||||
|
|
||||||
getWorldCenter(worldName).thenAccept {
|
|
||||||
if (it != null) {
|
|
||||||
updateWorldProperties(worldName, center).thenAccept { completableFuture.complete(null) }
|
|
||||||
} else {
|
|
||||||
insertWorldProperties(worldName, center).thenAccept { completableFuture.complete(null) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return completableFuture
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates an entry in the world properties
|
|
||||||
*/
|
|
||||||
private fun updateWorldProperties(worldName: String, center: Pair<Int, Int>): CompletableFuture<Void> {
|
|
||||||
val completableFuture = CompletableFuture<Void>()
|
|
||||||
sqliteManager.executeStatement(
|
|
||||||
"UPDATE world_properties SET center_x = ?, center_z = ? WHERE name = ?",
|
|
||||||
hashMapOf(
|
|
||||||
1 to center.first,
|
|
||||||
2 to center.second,
|
|
||||||
3 to worldName
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
properties[worldName] = center
|
|
||||||
completableFuture.complete(null)
|
|
||||||
}
|
|
||||||
return completableFuture
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Inserts into the world properties
|
|
||||||
*/
|
|
||||||
private fun insertWorldProperties(worldName: String, center: Pair<Int, Int>): CompletableFuture<Void> {
|
|
||||||
val completableFuture = CompletableFuture<Void>()
|
|
||||||
sqliteManager.executeStatement(
|
|
||||||
"INSERT INTO world_properties (name, center_x, center_z) VALUES (?, ?, ?)",
|
|
||||||
hashMapOf(
|
|
||||||
1 to worldName,
|
|
||||||
2 to center.first,
|
|
||||||
3 to center.second
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
properties[worldName] = center
|
|
||||||
completableFuture.complete(null)
|
|
||||||
}
|
|
||||||
return completableFuture
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,57 +0,0 @@
|
|||||||
package net.trivernis.chunkmaster.lib.generation
|
|
||||||
|
|
||||||
import net.trivernis.chunkmaster.Chunkmaster
|
|
||||||
import org.bukkit.Chunk
|
|
||||||
import java.util.*
|
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock
|
|
||||||
|
|
||||||
class ChunkUnloader(private val plugin: Chunkmaster) : Runnable {
|
|
||||||
private val maxLoadedChunks = plugin.config.getInt("generation.max-loaded-chunks")
|
|
||||||
private val lock = ReentrantReadWriteLock()
|
|
||||||
private var unloadingQueue = Vector<Chunk>(maxLoadedChunks)
|
|
||||||
val isFull: Boolean
|
|
||||||
get() {
|
|
||||||
return pendingSize == maxLoadedChunks
|
|
||||||
}
|
|
||||||
|
|
||||||
val pendingSize: Int
|
|
||||||
get() {
|
|
||||||
lock.readLock().lock()
|
|
||||||
val size = unloadingQueue.size
|
|
||||||
lock.readLock().unlock()
|
|
||||||
return size
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unloads all chunks in the unloading queue with each run
|
|
||||||
*/
|
|
||||||
override fun run() {
|
|
||||||
lock.writeLock().lock()
|
|
||||||
try {
|
|
||||||
val chunkToUnload = unloadingQueue.toHashSet()
|
|
||||||
|
|
||||||
for (chunk in chunkToUnload) {
|
|
||||||
try {
|
|
||||||
chunk.unload(true)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
plugin.logger.severe(e.toString())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
unloadingQueue.clear()
|
|
||||||
} finally {
|
|
||||||
lock.writeLock().unlock()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a chunk to unload to the queue
|
|
||||||
*/
|
|
||||||
fun add(chunk: Chunk) {
|
|
||||||
lock.writeLock().lockInterruptibly()
|
|
||||||
try {
|
|
||||||
unloadingQueue.add(chunk)
|
|
||||||
} finally {
|
|
||||||
lock.writeLock().unlock()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,145 +0,0 @@
|
|||||||
package net.trivernis.chunkmaster.lib.generation
|
|
||||||
|
|
||||||
import io.papermc.lib.PaperLib
|
|
||||||
import net.trivernis.chunkmaster.Chunkmaster
|
|
||||||
import net.trivernis.chunkmaster.lib.shapes.Shape
|
|
||||||
import org.bukkit.World
|
|
||||||
import java.util.concurrent.ArrayBlockingQueue
|
|
||||||
|
|
||||||
class DefaultGenerationTask(
|
|
||||||
private val plugin: Chunkmaster,
|
|
||||||
unloader: ChunkUnloader,
|
|
||||||
world: World,
|
|
||||||
startChunk: ChunkCoordinates,
|
|
||||||
override val radius: Int = -1,
|
|
||||||
shape: Shape,
|
|
||||||
missingChunks: HashSet<ChunkCoordinates>,
|
|
||||||
state: TaskState
|
|
||||||
) : GenerationTask(plugin, world, unloader, startChunk, shape, missingChunks, state) {
|
|
||||||
|
|
||||||
private val maxPendingChunks = plugin.config.getInt("generation.max-pending-chunks")
|
|
||||||
val pendingChunks = ArrayBlockingQueue<PendingChunkEntry>(maxPendingChunks)
|
|
||||||
|
|
||||||
override var count = 0
|
|
||||||
override var endReached: Boolean = false
|
|
||||||
|
|
||||||
init {
|
|
||||||
updateGenerationAreaMarker()
|
|
||||||
count = shape.count
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Runs the generation task. Every Iteration the next chunks will be generated if
|
|
||||||
* they haven't been generated already
|
|
||||||
* After a configured number of chunks chunks have been generated, they will all be unloaded and saved.
|
|
||||||
*/
|
|
||||||
override fun generate() {
|
|
||||||
generateMissing()
|
|
||||||
seekGenerated()
|
|
||||||
generateUntilBorder()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validates that all chunks have been generated or generates missing ones
|
|
||||||
*/
|
|
||||||
override fun validate() {
|
|
||||||
this.shape.reset()
|
|
||||||
val missedChunks = HashSet<ChunkCoordinates>()
|
|
||||||
|
|
||||||
while (!cancelRun && !borderReached()) {
|
|
||||||
val chunkCoordinates = nextChunkCoordinates
|
|
||||||
triggerDynmapRender(chunkCoordinates)
|
|
||||||
if (!PaperLib.isChunkGenerated(world, chunkCoordinates.x, chunkCoordinates.z)) {
|
|
||||||
missedChunks.add(chunkCoordinates)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.missingChunks.addAll(missedChunks)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates chunks that are missing
|
|
||||||
*/
|
|
||||||
override fun generateMissing() {
|
|
||||||
val missing = this.missingChunks.toHashSet()
|
|
||||||
this.count = 0
|
|
||||||
|
|
||||||
while (missing.size > 0 && !cancelRun) {
|
|
||||||
if (plugin.mspt < msptThreshold && !unloader.isFull) {
|
|
||||||
val chunk = missing.first()
|
|
||||||
missing.remove(chunk)
|
|
||||||
this.requestGeneration(chunk)
|
|
||||||
this.count++
|
|
||||||
} else {
|
|
||||||
Thread.sleep(50L)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!cancelRun) {
|
|
||||||
this.joinPending()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Seeks until it encounters a chunk that hasn't been generated yet
|
|
||||||
*/
|
|
||||||
private fun seekGenerated() {
|
|
||||||
do {
|
|
||||||
lastChunkCoords = nextChunkCoordinates
|
|
||||||
count = shape.count
|
|
||||||
} while (PaperLib.isChunkGenerated(world, lastChunkCoords.x, lastChunkCoords.z) && !borderReached())
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates the world until it encounters the worlds border
|
|
||||||
*/
|
|
||||||
private fun generateUntilBorder() {
|
|
||||||
var chunkCoordinates: ChunkCoordinates
|
|
||||||
|
|
||||||
while (!cancelRun && !borderReached()) {
|
|
||||||
if (plugin.mspt < msptThreshold && !unloader.isFull) {
|
|
||||||
chunkCoordinates = nextChunkCoordinates
|
|
||||||
requestGeneration(chunkCoordinates)
|
|
||||||
|
|
||||||
lastChunkCoords = chunkCoordinates
|
|
||||||
count = shape.count
|
|
||||||
} else {
|
|
||||||
Thread.sleep(50L)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!cancelRun) {
|
|
||||||
joinPending()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun joinPending() {
|
|
||||||
while (!this.pendingChunks.isEmpty()) {
|
|
||||||
Thread.sleep(msptThreshold)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Request the generation of a chunk
|
|
||||||
*/
|
|
||||||
private fun requestGeneration(chunkCoordinates: ChunkCoordinates) {
|
|
||||||
if (!PaperLib.isChunkGenerated(world, chunkCoordinates.x, chunkCoordinates.z) || PaperLib.isSpigot()) {
|
|
||||||
val pendingChunkEntry = PendingChunkEntry(
|
|
||||||
chunkCoordinates,
|
|
||||||
PaperLib.getChunkAtAsync(world, chunkCoordinates.x, chunkCoordinates.z, true)
|
|
||||||
)
|
|
||||||
this.pendingChunks.put(pendingChunkEntry)
|
|
||||||
pendingChunkEntry.chunk.thenAccept {
|
|
||||||
this.unloader.add(it)
|
|
||||||
this.pendingChunks.remove(pendingChunkEntry)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cancels the generation task.
|
|
||||||
* This unloads all chunks that were generated but not unloaded yet.
|
|
||||||
*/
|
|
||||||
override fun cancel() {
|
|
||||||
this.cancelRun = true
|
|
||||||
this.pendingChunks.forEach { it.chunk.cancel(false) }
|
|
||||||
updateGenerationAreaMarker(true)
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,121 @@
|
|||||||
|
package net.trivernis.chunkmaster.lib.generation
|
||||||
|
|
||||||
|
import net.trivernis.chunkmaster.Chunkmaster
|
||||||
|
import net.trivernis.chunkmaster.lib.shapes.Shape
|
||||||
|
import org.bukkit.Chunk
|
||||||
|
import org.bukkit.World
|
||||||
|
import java.lang.Exception
|
||||||
|
import java.util.concurrent.CompletableFuture
|
||||||
|
|
||||||
|
class GenerationTaskPaper(
|
||||||
|
private val plugin: Chunkmaster,
|
||||||
|
override val world: World,
|
||||||
|
startChunk: ChunkCoordinates,
|
||||||
|
override val radius: Int = -1,
|
||||||
|
shape: Shape
|
||||||
|
) : GenerationTask(plugin, startChunk, shape) {
|
||||||
|
|
||||||
|
private val maxPendingChunks = plugin.config.getInt("generation.max-pending-chunks")
|
||||||
|
|
||||||
|
private val pendingChunks = HashSet<CompletableFuture<Chunk>>()
|
||||||
|
|
||||||
|
override var count = 0
|
||||||
|
override var endReached: Boolean = false
|
||||||
|
|
||||||
|
init {
|
||||||
|
updateGenerationAreaMarker()
|
||||||
|
count = shape.count
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs the generation task. Every Iteration the next chunks will be generated if
|
||||||
|
* they haven't been generated already
|
||||||
|
* After a configured number of chunks chunks have been generated, they will all be unloaded and saved.
|
||||||
|
*/
|
||||||
|
override fun run() {
|
||||||
|
if (plugin.mspt < msptThreshold) {
|
||||||
|
if (loadedChunks.size > maxLoadedChunks) {
|
||||||
|
unloadLoadedChunks()
|
||||||
|
} else if (pendingChunks.size < maxPendingChunks) {
|
||||||
|
if (borderReachedCheck()) return
|
||||||
|
|
||||||
|
var chunk = nextChunkCoordinates
|
||||||
|
for (i in 0 until chunkSkips) {
|
||||||
|
if (world.isChunkGenerated(chunk.x, chunk.z)) {
|
||||||
|
chunk = nextChunkCoordinates
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!world.isChunkGenerated(chunk.x, chunk.z)) {
|
||||||
|
for (i in 0 until chunksPerStep) {
|
||||||
|
if (borderReached()) break
|
||||||
|
if (!world.isChunkGenerated(chunk.x, chunk.z)) {
|
||||||
|
pendingChunks.add(world.getChunkAtAsync(chunk.x, chunk.z, true))
|
||||||
|
}
|
||||||
|
chunk = nextChunkCoordinates
|
||||||
|
}
|
||||||
|
if (!world.isChunkGenerated(chunk.x, chunk.z)) {
|
||||||
|
pendingChunks.add(world.getChunkAtAsync(chunk.x, chunk.z, true))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lastChunkCoords = chunk
|
||||||
|
count = shape.count
|
||||||
|
}
|
||||||
|
}
|
||||||
|
checkChunksLoaded()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancels the generation task.
|
||||||
|
* This unloads all chunks that were generated but not unloaded yet.
|
||||||
|
*/
|
||||||
|
override fun cancel() {
|
||||||
|
updateGenerationAreaMarker(true)
|
||||||
|
updateLastChunkMarker(true)
|
||||||
|
unloadAllChunks()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancels all pending chunks and unloads all loaded chunks.
|
||||||
|
*/
|
||||||
|
private fun unloadAllChunks() {
|
||||||
|
for (pendingChunk in pendingChunks) {
|
||||||
|
if (pendingChunk.isDone) {
|
||||||
|
loadedChunks.add(pendingChunk.get())
|
||||||
|
} else {
|
||||||
|
pendingChunk.cancel(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pendingChunks.clear()
|
||||||
|
if (loadedChunks.isNotEmpty()) {
|
||||||
|
lastChunkCoords = ChunkCoordinates(loadedChunks.last().x, loadedChunks.last().z)
|
||||||
|
}
|
||||||
|
for (chunk in loadedChunks) {
|
||||||
|
if (chunk.isLoaded) {
|
||||||
|
try {
|
||||||
|
chunk.unload(true);
|
||||||
|
} catch (e: Exception){
|
||||||
|
plugin.logger.severe(e.toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if some chunks have been loaded and adds them to the loaded chunk set.
|
||||||
|
*/
|
||||||
|
private fun checkChunksLoaded() {
|
||||||
|
val completedEntries = HashSet<CompletableFuture<Chunk>>()
|
||||||
|
for (pendingChunk in pendingChunks) {
|
||||||
|
if (pendingChunk.isDone) {
|
||||||
|
completedEntries.add(pendingChunk)
|
||||||
|
loadedChunks.add(pendingChunk.get())
|
||||||
|
} else if (pendingChunk.isCompletedExceptionally || pendingChunk.isCancelled) {
|
||||||
|
completedEntries.add(pendingChunk)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pendingChunks.removeAll(completedEntries)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,72 @@
|
|||||||
|
package net.trivernis.chunkmaster.lib.generation
|
||||||
|
|
||||||
|
import net.trivernis.chunkmaster.Chunkmaster
|
||||||
|
import net.trivernis.chunkmaster.lib.shapes.Shape
|
||||||
|
import org.bukkit.World
|
||||||
|
import java.lang.Exception
|
||||||
|
|
||||||
|
class GenerationTaskSpigot(
|
||||||
|
private val plugin: Chunkmaster,
|
||||||
|
override val world: World,
|
||||||
|
startChunk: ChunkCoordinates,
|
||||||
|
override val radius: Int = -1,
|
||||||
|
shape: Shape
|
||||||
|
) : GenerationTask(plugin, startChunk, shape) {
|
||||||
|
|
||||||
|
|
||||||
|
override var count = 0
|
||||||
|
override var endReached: Boolean = false
|
||||||
|
|
||||||
|
init {
|
||||||
|
updateGenerationAreaMarker()
|
||||||
|
count = shape.count
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs the generation task. Every Iteration the next chunks will be generated if
|
||||||
|
* they haven't been generated already
|
||||||
|
* After a configured number of chunks chunks have been generated, they will all be unloaded and saved.
|
||||||
|
*/
|
||||||
|
override fun run() {
|
||||||
|
if (plugin.mspt < msptThreshold) {
|
||||||
|
if (loadedChunks.size > maxLoadedChunks) {
|
||||||
|
unloadLoadedChunks()
|
||||||
|
} else {
|
||||||
|
if (borderReachedCheck()) return
|
||||||
|
|
||||||
|
var chunk = nextChunkCoordinates
|
||||||
|
for (i in 0 until chunksPerStep) {
|
||||||
|
if (borderReached()) break
|
||||||
|
val chunkInstance = world.getChunkAt(chunk.x, chunk.z)
|
||||||
|
chunkInstance.load(true)
|
||||||
|
loadedChunks.add(chunkInstance)
|
||||||
|
chunk = nextChunkCoordinates
|
||||||
|
}
|
||||||
|
val chunkInstance = world.getChunkAt(chunk.x, chunk.z)
|
||||||
|
chunkInstance.load(true)
|
||||||
|
loadedChunks.add(chunkInstance)
|
||||||
|
|
||||||
|
lastChunkCoords = chunk
|
||||||
|
count = shape.count
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancels the generation task.
|
||||||
|
* This unloads all chunks that were generated but not unloaded yet.
|
||||||
|
*/
|
||||||
|
override fun cancel() {
|
||||||
|
for (chunk in loadedChunks) {
|
||||||
|
if (chunk.isLoaded) {
|
||||||
|
try {
|
||||||
|
chunk.unload(true)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
plugin.logger.severe(e.toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
updateGenerationAreaMarker(true)
|
||||||
|
updateLastChunkMarker(true)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package net.trivernis.chunkmaster.lib.generation
|
||||||
|
|
||||||
|
class PausedTaskEntry(
|
||||||
|
override val id: Int,
|
||||||
|
override val generationTask: GenerationTask
|
||||||
|
) : TaskEntry {
|
||||||
|
override fun cancel() {
|
||||||
|
generationTask.cancel()
|
||||||
|
}
|
||||||
|
}
|
@ -1,9 +0,0 @@
|
|||||||
package net.trivernis.chunkmaster.lib.generation
|
|
||||||
|
|
||||||
import org.bukkit.Chunk
|
|
||||||
import java.util.concurrent.CompletableFuture
|
|
||||||
|
|
||||||
class PendingChunkEntry(val coordinates: ChunkCoordinates, val chunk: CompletableFuture<Chunk>) {
|
|
||||||
val isDone: Boolean
|
|
||||||
get() = chunk.isDone
|
|
||||||
}
|
|
@ -0,0 +1,46 @@
|
|||||||
|
package net.trivernis.chunkmaster.lib.generation
|
||||||
|
|
||||||
|
import org.bukkit.scheduler.BukkitTask
|
||||||
|
|
||||||
|
class RunningTaskEntry(
|
||||||
|
override val id: Int,
|
||||||
|
val task: BukkitTask,
|
||||||
|
override val generationTask: GenerationTask
|
||||||
|
) : TaskEntry {
|
||||||
|
|
||||||
|
private var lastProgress: Pair<Long, Double>? = null
|
||||||
|
private var lastChunkCount: Pair<Long, Int>? = null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the generation Speed
|
||||||
|
*/
|
||||||
|
val generationSpeed: Pair<Double?, Double?>
|
||||||
|
get() {
|
||||||
|
var generationSpeed: Double? = null
|
||||||
|
var chunkGenerationSpeed: Double? = null
|
||||||
|
if (lastProgress != null) {
|
||||||
|
val progressDiff = generationTask.shape.progress() - lastProgress!!.second
|
||||||
|
val timeDiff = (System.currentTimeMillis() - lastProgress!!.first).toDouble()/1000
|
||||||
|
generationSpeed = progressDiff/timeDiff
|
||||||
|
}
|
||||||
|
if (lastChunkCount != null) {
|
||||||
|
val chunkDiff = generationTask.count - lastChunkCount!!.second
|
||||||
|
val timeDiff = (System.currentTimeMillis() - lastChunkCount!!.first).toDouble()/1000
|
||||||
|
chunkGenerationSpeed = chunkDiff/timeDiff
|
||||||
|
}
|
||||||
|
lastProgress = Pair(System.currentTimeMillis(), generationTask.shape.progress())
|
||||||
|
lastChunkCount = Pair(System.currentTimeMillis(), generationTask.count)
|
||||||
|
return Pair(generationSpeed, chunkGenerationSpeed)
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
lastProgress = Pair(System.currentTimeMillis(), generationTask.shape.progress())
|
||||||
|
lastChunkCount = Pair(System.currentTimeMillis(), generationTask.count)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun cancel() {
|
||||||
|
task.cancel()
|
||||||
|
generationTask.cancel()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
package net.trivernis.chunkmaster.lib.generation
|
||||||
|
|
||||||
|
import org.bukkit.scheduler.BukkitTask
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic task entry
|
||||||
|
*/
|
||||||
|
interface TaskEntry {
|
||||||
|
val id: Int
|
||||||
|
val generationTask: GenerationTask
|
||||||
|
|
||||||
|
fun cancel()
|
||||||
|
}
|
@ -1,24 +0,0 @@
|
|||||||
package net.trivernis.chunkmaster.lib.generation
|
|
||||||
|
|
||||||
enum class TaskState {
|
|
||||||
GENERATING {
|
|
||||||
override fun toString(): String {
|
|
||||||
return "GENERATING"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
VALIDATING {
|
|
||||||
override fun toString(): String {
|
|
||||||
return "VALIDATING"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
CORRECTING {
|
|
||||||
override fun toString(): String {
|
|
||||||
return "CORRECTING"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
PAUSING {
|
|
||||||
override fun toString(): String {
|
|
||||||
return "PAUSING"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
package net.trivernis.chunkmaster.lib.generation.taskentry
|
|
||||||
|
|
||||||
import net.trivernis.chunkmaster.lib.generation.GenerationTask
|
|
||||||
|
|
||||||
class PausedTaskEntry(
|
|
||||||
override val id: Int,
|
|
||||||
override val generationTask: GenerationTask
|
|
||||||
) : TaskEntry
|
|
@ -1,71 +0,0 @@
|
|||||||
package net.trivernis.chunkmaster.lib.generation.taskentry
|
|
||||||
|
|
||||||
import net.trivernis.chunkmaster.lib.generation.GenerationTask
|
|
||||||
|
|
||||||
class RunningTaskEntry(
|
|
||||||
override val id: Int,
|
|
||||||
override val generationTask: GenerationTask
|
|
||||||
) : TaskEntry {
|
|
||||||
|
|
||||||
private var lastProgress: Pair<Long, Double>? = null
|
|
||||||
private var lastChunkCount: Pair<Long, Int>? = null
|
|
||||||
private var thread = Thread(generationTask)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the generation Speed
|
|
||||||
*/
|
|
||||||
val generationSpeed: Pair<Double?, Double?>
|
|
||||||
get() {
|
|
||||||
var generationSpeed: Double? = null
|
|
||||||
var chunkGenerationSpeed: Double? = null
|
|
||||||
val progress =
|
|
||||||
generationTask.shape.progress(if (generationTask.radius < 0) (generationTask.world.worldBorder.size / 32).toInt() else null)
|
|
||||||
if (lastProgress != null) {
|
|
||||||
val progressDiff = progress - lastProgress!!.second
|
|
||||||
val timeDiff = (System.currentTimeMillis() - lastProgress!!.first).toDouble() / 1000
|
|
||||||
generationSpeed = progressDiff / timeDiff
|
|
||||||
}
|
|
||||||
if (lastChunkCount != null) {
|
|
||||||
val chunkDiff = generationTask.count - lastChunkCount!!.second
|
|
||||||
val timeDiff = (System.currentTimeMillis() - lastChunkCount!!.first).toDouble() / 1000
|
|
||||||
chunkGenerationSpeed = chunkDiff / timeDiff
|
|
||||||
}
|
|
||||||
lastProgress = Pair(System.currentTimeMillis(), progress)
|
|
||||||
lastChunkCount = Pair(System.currentTimeMillis(), generationTask.count)
|
|
||||||
return Pair(generationSpeed, chunkGenerationSpeed)
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
lastProgress = Pair(System.currentTimeMillis(), generationTask.shape.progress(null))
|
|
||||||
lastChunkCount = Pair(System.currentTimeMillis(), generationTask.count)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun start() {
|
|
||||||
thread.start()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun cancel(timeout: Long): Boolean {
|
|
||||||
if (generationTask.isRunning) {
|
|
||||||
generationTask.cancel()
|
|
||||||
thread.interrupt()
|
|
||||||
}
|
|
||||||
return try {
|
|
||||||
joinThread(timeout)
|
|
||||||
} catch (e: InterruptedException) {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun joinThread(timeout: Long): Boolean {
|
|
||||||
var threadStopped = false
|
|
||||||
|
|
||||||
for (i in 0..100) {
|
|
||||||
if (!thread.isAlive || !generationTask.isRunning) {
|
|
||||||
threadStopped = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
Thread.sleep(timeout / 100)
|
|
||||||
}
|
|
||||||
return threadStopped
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
package net.trivernis.chunkmaster.lib.generation.taskentry
|
|
||||||
|
|
||||||
import net.trivernis.chunkmaster.lib.generation.GenerationTask
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generic task entry
|
|
||||||
*/
|
|
||||||
interface TaskEntry {
|
|
||||||
val id: Int
|
|
||||||
val generationTask: GenerationTask
|
|
||||||
}
|
|
@ -1,85 +0,0 @@
|
|||||||
RESUME_FOR_WORLD = Resumiendo tarea de generación de chunks para el mundo '%s'...
|
|
||||||
TASK_FINISHED = Tarea #%d terminada después de %d chunks.
|
|
||||||
TASK_CANCELLED = Tarea #%s cancelada.
|
|
||||||
TASK_LOAD_FAILED = §cFallo al cargar la tarea #%d.
|
|
||||||
TASK_LOAD_SUCCESS = %d tareas guardadas cargadas.
|
|
||||||
TASK_NOT_FOUND = §c¡Tarea %s no encontrada!
|
|
||||||
CREATE_DELAYED_LOAD = Creando tarea Bukkit para cargar la generación de chunks...
|
|
||||||
TASK_PERIODIC_REPORT = Tarea #%d en ejecución para '%s'. Estado: %s. Progreso: %d Chunks %s %s, Velocidad: %.1f ch/s, Último Chunk: %d, %d
|
|
||||||
TASK_PERIODIC_REPORT_CORRECTING = Tarea #%d gerenando chunks perdidos para '%s'. Progreso: %d Chunks %s
|
|
||||||
TASK_SAVE_FAILED = §cExcepción al guardar las tareas: %s
|
|
||||||
|
|
||||||
WORLD_NAME_REQUIRED = §c¡Tienes que proporcionar un nombre del mundo!
|
|
||||||
WORLD_NOT_FOUND = §c¡Mundo §2%s §cno encontrado!
|
|
||||||
TASK_ALREADY_EXISTS = §c¡Una tarea para '%s' ya existe!
|
|
||||||
TASK_CREATION_SUCCESS = §9¡Tarea de generación para el mundo §2%s§9 §2%s§9 y forma %s creada con éxito!
|
|
||||||
TASK_UNIT_WORLDBORDER = hasta el borde del mundo
|
|
||||||
TASK_UNIT_RADIUS = con un radius de %s
|
|
||||||
TASK_ID_REQUIRED = §c¡Necesitas proporcionar una id de tarea!
|
|
||||||
INVALID_ARGUMENT = §c¡Argumento invalido en %s: %s!
|
|
||||||
|
|
||||||
PAUSED_TASKS_HEADER = Tareas de generación actualmente en pausa
|
|
||||||
TASKS_ENTRY = - §9#%d§r - §2%s§r - §2%s§r - §2%s Chunks %s§r
|
|
||||||
RUNNING_TASKS_HEADER = Tareas de generación en curso
|
|
||||||
NO_GENERATION_TASKS = No hay tareas de generación.
|
|
||||||
|
|
||||||
COMPLETED_TASKS_HEADER = §nTareas de generación completadas§r
|
|
||||||
COMPLETED_WORLD_HEADER = §l%s§r
|
|
||||||
COMPLETED_TASK_ENTRY = - §9#%d§r: §2%d§r radio de chunks desde el centro §2(%d, %d)§r con forma §2%s§r
|
|
||||||
|
|
||||||
PAUSE_SUCCESS = §9Tareas de generación pausadas
|
|
||||||
ALREADY_PAUSED = §cEl progreso de generación ya está en pausa.
|
|
||||||
|
|
||||||
RESUME_SUCCESS = §9Tareas de generación renaudadas
|
|
||||||
NOT_PAUSED = §cEl progreso de generación no está en pausa.
|
|
||||||
|
|
||||||
CONFIG_RELOADING = Recargando el archivo de configuración...
|
|
||||||
CONFIG_RELOADED = §2El archivo de configuración ha sido recargado!
|
|
||||||
|
|
||||||
TELEPORTED = §9Has sido teletransportado al chunk §2%s, %s
|
|
||||||
TP_ONLY_PLAYER = §c¡Este comando solo puede ser ejecutado por un jugador!
|
|
||||||
|
|
||||||
NO_PERMISSION = §c¡No tienes permiso para este comando!
|
|
||||||
SUBCOMMAND_NOT_FOUND = §c¡Subcomando §2%s §cno encontrado!
|
|
||||||
|
|
||||||
STOPPING_ALL_TASKS = Deteniendo todas las tareas de generación...
|
|
||||||
SAVING_TASK_PROGRESS = Guardando el progreso de la tarea #%s en la base de datos...
|
|
||||||
DB_INIT = Iniciando la base de datos...
|
|
||||||
DB_INIT_FINISHED = Base de datos ha sido inicializada.
|
|
||||||
DB_INIT_EROR = Error al inicializar la base de datos: %s.
|
|
||||||
|
|
||||||
DATABASE_CONNECTION_ERROR = §c¡No se ha podido establecer la conexión con la base de datos!
|
|
||||||
SQL_ERROR = §cSe ha producido un error en sql %s!
|
|
||||||
NO_DATABASE_CONNECTION = §cNo se ha podido ejecutar sql: No hay conexión con la base de datos.
|
|
||||||
CREATE_TABLE_DEFINITION = Tabla %s creada con definición %s.
|
|
||||||
TABLE_CREATE_ERROR = §cSe ha producido un error al crear la tabla %s.
|
|
||||||
UPDATE_TABLE_DEFINITION = Tabla %s actualizada con sql %s.
|
|
||||||
UPDATE_TABLE_FAILED = Se ha producido un error al actualizar la tabla %s con sql %s.
|
|
||||||
|
|
||||||
TOO_FEW_ARGUMENTS = §cNo has aportado suficientes argumentos.
|
|
||||||
COORD_INVALID = §cLas coordenadas proporcionadas ('%s', '%s') son incorrectas!
|
|
||||||
CENTER_UPDATED = §9El centro del mundo §2%s §9se ha actualizado a §2(%s, %s)§9.
|
|
||||||
CENTER_INFO = §9El centro del mundo §2%s §9es §2(%s, %s)§9.
|
|
||||||
|
|
||||||
PLUGIN_DETECTED = ¡Plugin %s con versión %s detectada!
|
|
||||||
|
|
||||||
RESUME_PLAYER_LEAVE = El número de jugadores es menor que el configurado como valor de pausa. Reanudando generación...
|
|
||||||
PAUSE_PLAYER_JOIN = El número de jugadores es igual que el configurado como valor de pausa. Pausando generación...
|
|
||||||
PAUSE_MANUALLY = Generación se pausó manualmente. No se resumirá automáticamente.
|
|
||||||
|
|
||||||
STATS_HEADER = §nEstadísticas§r
|
|
||||||
STATS_SERVER = §lEstadísticas del Servidor§r
|
|
||||||
STATS_SERVER_VERSION = - Versión del Servidor: §2%s§r
|
|
||||||
STATS_PLUGIN_VERSION = - Versión del Plugin: §2%s§r
|
|
||||||
STATS_MEMORY = - Memoria (u/a): §2%d mb / %d mb = (%.2f porcentaje)§r
|
|
||||||
STATS_CORES = - Cores: §2%d§r
|
|
||||||
|
|
||||||
STATS_WORLD_NAME = §l%s§r
|
|
||||||
STATS_ENTITY_COUNT = - §2%d§r Entidades
|
|
||||||
STATS_LOADED_CHUNKS = - §2%d§r Chunks cargados
|
|
||||||
STATS_PLUGIN_LOADED_CHUNKS = - §2%d§r Chunks cargados por Chunkmaster
|
|
||||||
STATS_GENERATING = - Generando: §2%s§r
|
|
||||||
|
|
||||||
SAVING_CHUNKS = Guardando %d chunks guardados...
|
|
||||||
CANCEL_FAIL = Fallo en la cancelación de la tarea #%d en el tiempo de espera configurado!
|
|
||||||
NO_AUTOSTART = Autoarranque configurado a §2false§r. Pausando...
|
|
@ -1,75 +0,0 @@
|
|||||||
RESUME_FOR_WORLD = Reprise de la tâche de génération pour le monde '%s'...
|
|
||||||
TASK_FINISHED = Tâche #%d terminée après %d chunks.
|
|
||||||
TASK_CANCELED = Tâche #%s annulée.
|
|
||||||
TASK_LOAD_FAILED = §cImpossible de charger la tâche #%d.
|
|
||||||
TASK_LOAD_SUCCESS = %d tâches chargées avec succès.
|
|
||||||
TASK_NOT_FOUND = §cTâche %s introuvable!
|
|
||||||
CREATE_DELAYED_LOAD = Création de la tâche pour la génération du terrain plus tard...
|
|
||||||
TASK_PERIODIC_REPORT = Tâche #%d en cours pour '%s'. État: %s. Progression: %d chunks %s %s, Vitesse: %.1f ch/s, Dernier Chunk: %d, %d
|
|
||||||
TASK_SAVE_FAILED = §cErreur lors de la sauvegarde de la tâche: %s
|
|
||||||
|
|
||||||
WORLD_NAME_REQUIRED = §cVous devez renseigner le nom d'un monde!
|
|
||||||
WORLD_NOT_FOUND = §cMonde §2%s §cintrouvable!
|
|
||||||
TASK_ALREADY_EXISTS = §cUne tâche pour '%s' existe déjà!
|
|
||||||
TASK_CREATION_SUCCESS = §9Tâche de génération pour le monde §2%s§9 §2%s§9 avec une forme %s créée avec succès!
|
|
||||||
TASK_UNIT_WORLDBORDER = jusqu'à la limite du monde
|
|
||||||
TASK_UNIT_RADIUS = avec un rayon de %s
|
|
||||||
TASK_ID_REQUIRED = §cVous devez renseigner l'id de la tache!
|
|
||||||
INVALID_ARGUMENT = §cArgument invalide à %s: %s!
|
|
||||||
|
|
||||||
PAUSED_TASKS_HEADER = Tâches de génération en pause
|
|
||||||
TASKS_ENTRY = - §9#%d§r - §2%s§r - §2%s§r - §2%s chunks %s§r
|
|
||||||
RUNNING_TASKS_HEADER = Tâches de génération en cours
|
|
||||||
NO_GENERATION_TASKS = Il n'y a aucune tâche de génération.
|
|
||||||
|
|
||||||
PAUSE_SUCCESS = §9Mise en pause de toutes les tâches de génération.
|
|
||||||
ALREADY_PAUSED = §cLa génération est déjà en pause!
|
|
||||||
|
|
||||||
RESUME_SUCCESS = §9Reprise de toutes les tâches de génération.
|
|
||||||
NOT_PAUSED = §cLa génération n'est pas en pause!
|
|
||||||
|
|
||||||
CONFIG_RELOADING = Rechargement du fichier de configuration...
|
|
||||||
CONFIG_RELOADED = §2La configuration a été rechargé!
|
|
||||||
|
|
||||||
TELEPORTED = §9Vous avez été téléporté au chunk §2%s, %s
|
|
||||||
TP_ONLY_PLAYER = §cCette commande ne peut être exécutée que par un joueur!
|
|
||||||
|
|
||||||
NO_PERMISSION = §cVous n'avez pas la permission d'exécuter cette commande!
|
|
||||||
SUBCOMMAND_NOT_FOUND = §cSSous-commande §2%s §cintrouvable!
|
|
||||||
|
|
||||||
STOPPING_ALL_TASKS = Arrêts de toutes les tâches de génération...
|
|
||||||
SAVING_TASK_PROGRESS = Sauvegarde de la progression de la tâche #%s dans la base de données...
|
|
||||||
DB_INIT = Initialisation de la base de données...
|
|
||||||
DB_INIT_FINISHED = Base de données initialisée.
|
|
||||||
DB_INIT_EROR = Erreur lors de l'initialisation de la base de données: %s.
|
|
||||||
|
|
||||||
DATABASE_CONNECTION_ERROR = §cConnexion impossible à la base de données!
|
|
||||||
SQL_ERROR = §cErreur lors de l'exécution SQL %s!
|
|
||||||
NO_DATABASE_CONNECTION = §cImpossible d'exécuter une requête SQL: Pas de connexion à la base de données.
|
|
||||||
CREATE_TABLE_DEFINITION = Table créée %s avec pour définition %s.
|
|
||||||
TABLE_CREATE_ERROR = §cErreur lors de la création de la table %s.
|
|
||||||
UPDATE_TABLE_DEFINITION = Mise à jour de la table %s par la requête SQL %s.
|
|
||||||
UPDATE_TABLE_FAILED = Impossible de mettre à jour la table %s par la requête SQL %s.
|
|
||||||
|
|
||||||
TOO_FEW_ARGUMENTS = §cIl manques des arguments pour exécuter la commande.
|
|
||||||
COORD_INVALID = §cLes coordonnées renseignées ('%s', '%s') sont invalides!
|
|
||||||
CENTER_UPDATED = §9Le centre du monde §2%s §9a été défini en §2(%s, %s)§9.
|
|
||||||
CENTER_INFO = §9Le centre du monde §2%s §9est §2(%s, %s)§9.
|
|
||||||
|
|
||||||
PLUGIN_DETECTED = Version de %s détectée %s
|
|
||||||
|
|
||||||
RESUME_PLAYER_LEAVE = Le nombre de joueurs est plus bas que la limite configurée. Reprise de la génération...
|
|
||||||
PAUSE_PLAYER_JOIN = Le nombre de joueurs a atteint la limite configurée. Arrêt de la génération...
|
|
||||||
PAUSE_MANUALLY = La génération a été manuellement arrêtée. Celle-ci ne reprendra pas automatiquement.
|
|
||||||
|
|
||||||
STATS_HEADER = §nStatistiques§r
|
|
||||||
STATS_SERVER = §lStatistiques serveur§r
|
|
||||||
STATS_SERVER_VERSION = - Version du serveur: §2%s§r
|
|
||||||
STATS_PLUGIN_VERSION = - Version du plugin: §2%s§r
|
|
||||||
STATS_MEMORY = - Mémoire vive (u/a): §2%d mb / %d mb = (%.2f pourcent)§r
|
|
||||||
STATS_CORES = - Coeurs processeur: §2%d§r
|
|
||||||
|
|
||||||
STATS_WORLD_NAME = §l%s§r
|
|
||||||
STATS_ENTITY_COUNT = - §2%d§r Entités
|
|
||||||
STATS_LOADED_CHUNKS = - §2%d§r Chunks chargés
|
|
||||||
STATS_PLUGIN_LOADED_CHUNKS = - §2%d§r Chunks chargés par Chunkmaster
|
|
@ -1,60 +0,0 @@
|
|||||||
package net.trivernis.chunkmaster.lib
|
|
||||||
|
|
||||||
import io.kotest.matchers.shouldBe
|
|
||||||
import org.junit.Test
|
|
||||||
|
|
||||||
class ArgParserTest {
|
|
||||||
var argParser = ArgParser()
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `it parses arguments`() {
|
|
||||||
argParser.parseArguments("first second third forth").shouldBe(listOf("first", "second", "third", "forth"))
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `it handles escaped sequences`() {
|
|
||||||
argParser.parseArguments("first second\\ pt2 third").shouldBe(listOf("first", "second pt2", "third"))
|
|
||||||
argParser.parseArguments("first \"second\\\" part 2\" third")
|
|
||||||
.shouldBe(listOf("first", "second\" part 2", "third"))
|
|
||||||
argParser.parseArguments("first \\\\second third").shouldBe(listOf("first", "\\second", "third"))
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `it parses quoted arguments as one argument`() {
|
|
||||||
argParser.parseArguments("first \"second with space\" third")
|
|
||||||
.shouldBe(listOf("first", "second with space", "third"))
|
|
||||||
argParser.parseArguments("\"first\" \"second\" \"third\"").shouldBe(listOf("first", "second", "third"))
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `it parses single arguments`() {
|
|
||||||
argParser.parseArguments("one").shouldBe(listOf("one"))
|
|
||||||
argParser.parseArguments("\"one\"").shouldBe(listOf("one"))
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `it parses no arguments`() {
|
|
||||||
argParser.parseArguments("").shouldBe(emptyList())
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `it parses just whitespace as no arguments`() {
|
|
||||||
argParser.parseArguments(" ").shouldBe(emptyList())
|
|
||||||
argParser.parseArguments("\t\t").shouldBe(emptyList())
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `it parses arguments with weird whitespace`() {
|
|
||||||
argParser.parseArguments(" first second \t third \n forth ")
|
|
||||||
.shouldBe(listOf("first", "second", "third", "forth"))
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `it deals predictable with malformed input`() {
|
|
||||||
argParser.parseArguments("first \"second third fourth").shouldBe(listOf("first", "second third fourth"))
|
|
||||||
argParser.parseArguments("\"first second \"third\" fourth")
|
|
||||||
.shouldBe(listOf("first second ", "third", " fourth"))
|
|
||||||
argParser.parseArguments("first second third fourth\"").shouldBe(listOf("first", "second", "third", "fourth"))
|
|
||||||
argParser.parseArguments("\"").shouldBe(emptyList())
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,29 +0,0 @@
|
|||||||
package net.trivernis.chunkmaster.lib
|
|
||||||
|
|
||||||
import io.kotest.matchers.string.shouldNotBeEmpty
|
|
||||||
import io.mockk.every
|
|
||||||
import io.mockk.mockk
|
|
||||||
import net.trivernis.chunkmaster.Chunkmaster
|
|
||||||
import org.bukkit.configuration.file.FileConfiguration
|
|
||||||
import org.junit.Test
|
|
||||||
|
|
||||||
class LanguageManagerTest {
|
|
||||||
private var langManager: LanguageManager
|
|
||||||
|
|
||||||
init {
|
|
||||||
val plugin = mockk<Chunkmaster>()
|
|
||||||
val config = mockk<FileConfiguration>()
|
|
||||||
|
|
||||||
every { plugin.dataFolder } returns createTempDir()
|
|
||||||
every { plugin.config } returns config
|
|
||||||
every { config.getString("language") } returns "en"
|
|
||||||
|
|
||||||
langManager = LanguageManager(plugin)
|
|
||||||
langManager.loadProperties()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `it returns localized for a key`() {
|
|
||||||
langManager.getLocalized("NOT_PAUSED").shouldNotBeEmpty()
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,75 +0,0 @@
|
|||||||
package net.trivernis.chunkmaster.lib.shapes
|
|
||||||
|
|
||||||
import io.kotest.matchers.booleans.shouldBeTrue
|
|
||||||
import io.kotest.matchers.collections.shouldContainAll
|
|
||||||
import io.kotest.matchers.doubles.shouldBeBetween
|
|
||||||
import io.kotest.matchers.shouldBe
|
|
||||||
import org.junit.Test
|
|
||||||
import org.junit.jupiter.api.BeforeEach
|
|
||||||
|
|
||||||
class CircleTest {
|
|
||||||
private val circle = Circle(center = Pair(0, 0), radius = 2, start = Pair(0, 0))
|
|
||||||
|
|
||||||
@BeforeEach
|
|
||||||
fun init() {
|
|
||||||
circle.reset()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `it generates coordinates`() {
|
|
||||||
circle.next().shouldBe(Pair(0, 0))
|
|
||||||
circle.next().shouldBe(Pair(-1, -1))
|
|
||||||
circle.next().shouldBe(Pair(1, 0))
|
|
||||||
circle.next().shouldBe(Pair(-1, 0))
|
|
||||||
circle.next().shouldBe(Pair(1, -1))
|
|
||||||
circle.next().shouldBe(Pair(-1, 1))
|
|
||||||
circle.next().shouldBe(Pair(0, 1))
|
|
||||||
circle.next().shouldBe(Pair(0, -1))
|
|
||||||
circle.next().shouldBe(Pair(1, 1))
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `it reports when reaching the end`() {
|
|
||||||
for (i in 1..25) {
|
|
||||||
circle.next()
|
|
||||||
}
|
|
||||||
circle.endReached().shouldBeTrue()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `it reports the radius`() {
|
|
||||||
for (i in 1..9) {
|
|
||||||
circle.next()
|
|
||||||
}
|
|
||||||
circle.currentRadius().shouldBe(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `it returns the right edges`() {
|
|
||||||
circle.getShapeEdgeLocations().shouldContainAll(
|
|
||||||
listOf(
|
|
||||||
Pair(2, -1),
|
|
||||||
Pair(2, 0),
|
|
||||||
Pair(2, 1),
|
|
||||||
Pair(1, 2),
|
|
||||||
Pair(0, 2),
|
|
||||||
Pair(-1, 2),
|
|
||||||
Pair(-2, 1),
|
|
||||||
Pair(-2, 0),
|
|
||||||
Pair(-2, -1),
|
|
||||||
Pair(-1, -2),
|
|
||||||
Pair(0, -2),
|
|
||||||
Pair(1, -2),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `it returns the progress`() {
|
|
||||||
circle.progress(2).shouldBe(0)
|
|
||||||
for (i in 1..7) {
|
|
||||||
circle.next()
|
|
||||||
}
|
|
||||||
circle.progress(2).shouldBeBetween(.5, .8, .0)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,62 +0,0 @@
|
|||||||
package net.trivernis.chunkmaster.lib.shapes
|
|
||||||
|
|
||||||
import io.kotest.matchers.booleans.shouldBeTrue
|
|
||||||
import io.kotest.matchers.collections.shouldContainAll
|
|
||||||
import io.kotest.matchers.shouldBe
|
|
||||||
import org.junit.Test
|
|
||||||
import org.junit.jupiter.api.BeforeEach
|
|
||||||
|
|
||||||
class SquareTest {
|
|
||||||
|
|
||||||
private val square = Square(center = Pair(0, 0), radius = 2, start = Pair(0, 0))
|
|
||||||
|
|
||||||
@BeforeEach
|
|
||||||
fun init() {
|
|
||||||
square.reset()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `it generates coordinates`() {
|
|
||||||
square.next().shouldBe(Pair(0, 0))
|
|
||||||
square.next().shouldBe(Pair(0, 1))
|
|
||||||
square.next().shouldBe(Pair(1, 1))
|
|
||||||
square.next().shouldBe(Pair(1, 0))
|
|
||||||
square.next().shouldBe(Pair(1, -1))
|
|
||||||
square.next().shouldBe(Pair(0, -1))
|
|
||||||
square.next().shouldBe(Pair(-1, -1))
|
|
||||||
square.next().shouldBe(Pair(-1, 0))
|
|
||||||
square.next().shouldBe(Pair(-1, 1))
|
|
||||||
square.next().shouldBe(Pair(-1, 2))
|
|
||||||
square.next().shouldBe(Pair(0, 2))
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `it reports when reaching the end`() {
|
|
||||||
for (i in 1..25) {
|
|
||||||
square.next()
|
|
||||||
}
|
|
||||||
square.endReached().shouldBeTrue()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `it reports the radius`() {
|
|
||||||
for (i in 1..9) {
|
|
||||||
square.next()
|
|
||||||
}
|
|
||||||
square.currentRadius().shouldBe(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `it returns the right edges`() {
|
|
||||||
square.getShapeEdgeLocations().shouldContainAll(listOf(Pair(2, 2), Pair(-2, 2), Pair(2, -2), Pair(-2, -2)))
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `it returns the progress`() {
|
|
||||||
square.progress(2).shouldBe(0)
|
|
||||||
for (i in 1..8) {
|
|
||||||
square.next()
|
|
||||||
}
|
|
||||||
square.progress(2).shouldBe(0.5)
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue