Initial commit.
commit
f4f043e4d6
|
@ -0,0 +1,60 @@
|
||||||
|
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
kotlin("jvm") version "1.4.32"
|
||||||
|
id("com.github.johnrengelman.shadow") version "5.2.0"
|
||||||
|
}
|
||||||
|
|
||||||
|
group = "nl.kallestruik"
|
||||||
|
version = "1.0"
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
mavenLocal()
|
||||||
|
|
||||||
|
maven("https://papermc.io/repo/repository/maven-public/")
|
||||||
|
maven("https://repo.aikar.co/content/groups/aikar/")
|
||||||
|
maven("https://repo.dmulloy2.net/repository/public/")
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation("co.aikar:acf-paper:0.5.0-SNAPSHOT")
|
||||||
|
compileOnly("com.destroystokyo.paper:paper:1.16.5-R0.1-SNAPSHOT")
|
||||||
|
compileOnly("com.comphenix.protocol:ProtocolLib:4.6.0")
|
||||||
|
compileOnly(kotlin("stdlib-jdk8"))
|
||||||
|
|
||||||
|
compileOnly("nl.kallestruik:DLib:1.0")
|
||||||
|
|
||||||
|
testImplementation(kotlin("test-junit5"))
|
||||||
|
testImplementation("org.junit.jupiter:junit-jupiter-api:5.6.0")
|
||||||
|
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.6.0")
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.compileJava {
|
||||||
|
options.compilerArgs.add("-parameters")
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.compileKotlin {
|
||||||
|
kotlinOptions.javaParameters = true
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.test {
|
||||||
|
useJUnitPlatform()
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.shadowJar {
|
||||||
|
relocate("co.aikar.commands", "nl.kallestruik.dtweaks.acf")
|
||||||
|
relocate("co.aikar.locales", "nl.kallestruik.dtweaks.locales")
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.build {
|
||||||
|
dependsOn(tasks.shadowJar)
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.withType<KotlinCompile> {
|
||||||
|
kotlinOptions.jvmTarget = "11"
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.processResources {
|
||||||
|
expand("version" to project.version)
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
kotlin.code.style=official
|
Binary file not shown.
|
@ -0,0 +1,5 @@
|
||||||
|
distributionBase=GRADLE_USER_HOME
|
||||||
|
distributionPath=wrapper/dists
|
||||||
|
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8-bin.zip
|
||||||
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
zipStorePath=wrapper/dists
|
|
@ -0,0 +1,185 @@
|
||||||
|
#!/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" "$@"
|
|
@ -0,0 +1,89 @@
|
||||||
|
@rem
|
||||||
|
@rem Copyright 2015 the original author or authors.
|
||||||
|
@rem
|
||||||
|
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
@rem you may not use this file except in compliance with the License.
|
||||||
|
@rem You may obtain a copy of the License at
|
||||||
|
@rem
|
||||||
|
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
@rem
|
||||||
|
@rem Unless required by applicable law or agreed to in writing, software
|
||||||
|
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@rem See the License for the specific language governing permissions and
|
||||||
|
@rem limitations under the License.
|
||||||
|
@rem
|
||||||
|
|
||||||
|
@if "%DEBUG%" == "" @echo off
|
||||||
|
@rem ##########################################################################
|
||||||
|
@rem
|
||||||
|
@rem Gradle startup script for Windows
|
||||||
|
@rem
|
||||||
|
@rem ##########################################################################
|
||||||
|
|
||||||
|
@rem Set local scope for the variables with windows NT shell
|
||||||
|
if "%OS%"=="Windows_NT" setlocal
|
||||||
|
|
||||||
|
set DIRNAME=%~dp0
|
||||||
|
if "%DIRNAME%" == "" set DIRNAME=.
|
||||||
|
set APP_BASE_NAME=%~n0
|
||||||
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
|
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||||
|
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||||
|
|
||||||
|
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||||
|
|
||||||
|
@rem Find java.exe
|
||||||
|
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||||
|
|
||||||
|
set JAVA_EXE=java.exe
|
||||||
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
|
if "%ERRORLEVEL%" == "0" goto execute
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
echo.
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
echo location of your Java installation.
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:findJavaFromJavaHome
|
||||||
|
set JAVA_HOME=%JAVA_HOME:"=%
|
||||||
|
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||||
|
|
||||||
|
if exist "%JAVA_EXE%" goto execute
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||||
|
echo.
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
echo location of your Java installation.
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:execute
|
||||||
|
@rem Setup the command line
|
||||||
|
|
||||||
|
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||||
|
|
||||||
|
|
||||||
|
@rem Execute Gradle
|
||||||
|
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||||
|
|
||||||
|
:end
|
||||||
|
@rem End local scope for the variables with windows NT shell
|
||||||
|
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||||
|
|
||||||
|
:fail
|
||||||
|
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||||
|
rem the _cmd.exe /c_ return code!
|
||||||
|
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||||
|
exit /b 1
|
||||||
|
|
||||||
|
:mainEnd
|
||||||
|
if "%OS%"=="Windows_NT" endlocal
|
||||||
|
|
||||||
|
:omega
|
|
@ -0,0 +1,3 @@
|
||||||
|
|
||||||
|
rootProject.name = "DTweaks"
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
package nl.kallestruik.dtweaks
|
||||||
|
|
||||||
|
object Const {
|
||||||
|
const val TRAMPLE_ENABLED_FILE_NAME = "tramplestore.yml"
|
||||||
|
const val TWEAK_STATE_FILE_NAME = "tweak_states.yml"
|
||||||
|
}
|
|
@ -0,0 +1,139 @@
|
||||||
|
package nl.kallestruik.dtweaks
|
||||||
|
|
||||||
|
import co.aikar.commands.ConditionFailedException
|
||||||
|
import co.aikar.commands.PaperCommandManager
|
||||||
|
import nl.kallestruik.dlib.DUtil
|
||||||
|
import nl.kallestruik.dlib.MathHelper
|
||||||
|
import nl.kallestruik.dlib.ReflectionUtil
|
||||||
|
import nl.kallestruik.dtweaks.commands.CommandMobcaps
|
||||||
|
import nl.kallestruik.dtweaks.commands.CommandPlayer
|
||||||
|
import nl.kallestruik.dtweaks.commands.CommandPocketdim
|
||||||
|
import nl.kallestruik.dtweaks.commands.CommandToggletrample
|
||||||
|
import nl.kallestruik.dtweaks.managers.FakePlayerManager
|
||||||
|
import nl.kallestruik.dtweaks.managers.PocketDimensionManager
|
||||||
|
import nl.kallestruik.dtweaks.managers.TrampleManager
|
||||||
|
import nl.kallestruik.dtweaks.managers.TweakManager
|
||||||
|
import nl.kallestruik.dtweaks.tweaks.craftingtweaks.*
|
||||||
|
import nl.kallestruik.dtweaks.tweaks.croptweaks.*
|
||||||
|
import nl.kallestruik.dtweaks.tweaks.dispsensertweaks.DispensersCanPlantSaplings
|
||||||
|
import nl.kallestruik.dtweaks.tweaks.miscellaneoustweaks.ArmorStandArmorSwapping
|
||||||
|
import nl.kallestruik.dtweaks.tweaks.miscellaneoustweaks.CarpetBlockPlacingProtocol
|
||||||
|
import nl.kallestruik.dtweaks.tweaks.miscellaneoustweaks.FakePlayers
|
||||||
|
import nl.kallestruik.dtweaks.tweaks.miscellaneoustweaks.SpaceTimePockets
|
||||||
|
import nl.kallestruik.dtweaks.tweaks.mobtweaks.NoCreeperGrief
|
||||||
|
import nl.kallestruik.dtweaks.tweaks.mobtweaks.NoDoorBreaking
|
||||||
|
import nl.kallestruik.dtweaks.tweaks.mobtweaks.NoEndermanGrief
|
||||||
|
import nl.kallestruik.dtweaks.tweaks.mobtweaks.VillagerInfo
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin
|
||||||
|
import java.io.File
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
|
||||||
|
class DTweaks: JavaPlugin() {
|
||||||
|
companion object {
|
||||||
|
private lateinit var random: Random
|
||||||
|
private lateinit var tweakManager: TweakManager
|
||||||
|
private lateinit var util: DUtil
|
||||||
|
private lateinit var mathHelper: MathHelper
|
||||||
|
lateinit var reflectionUtil: ReflectionUtil
|
||||||
|
private lateinit var trampleManager: TrampleManager
|
||||||
|
private lateinit var commandManager: PaperCommandManager
|
||||||
|
private lateinit var fakePlayerManager: FakePlayerManager
|
||||||
|
private lateinit var pocketDimensionManager: PocketDimensionManager
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onEnable() {
|
||||||
|
/*
|
||||||
|
* Initialize stuff
|
||||||
|
*/
|
||||||
|
random = Random()
|
||||||
|
tweakManager = TweakManager(this)
|
||||||
|
util = DUtil(random)
|
||||||
|
mathHelper = MathHelper()
|
||||||
|
reflectionUtil = ReflectionUtil()
|
||||||
|
trampleManager = TrampleManager()
|
||||||
|
commandManager = PaperCommandManager(this)
|
||||||
|
fakePlayerManager = FakePlayerManager()
|
||||||
|
pocketDimensionManager = PocketDimensionManager(mathHelper)
|
||||||
|
|
||||||
|
// Enable brigadier support on ACF
|
||||||
|
commandManager.enableUnstableAPI("brigadier")
|
||||||
|
|
||||||
|
registerCommandConditions()
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Commands
|
||||||
|
*/
|
||||||
|
commandManager.registerCommand(CommandMobcaps(reflectionUtil))
|
||||||
|
commandManager.registerCommand(CommandPlayer(fakePlayerManager, tweakManager))
|
||||||
|
commandManager.registerCommand(CommandPocketdim(pocketDimensionManager))
|
||||||
|
commandManager.registerCommand(CommandToggletrample(trampleManager))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Load data from disk
|
||||||
|
*/
|
||||||
|
tweakManager.loadFromFile(File(dataFolder, Const.TWEAK_STATE_FILE_NAME))
|
||||||
|
trampleManager.loadFromFile(File(dataFolder, Const.TRAMPLE_ENABLED_FILE_NAME))
|
||||||
|
pocketDimensionManager.loadData()
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Crafting tweaks
|
||||||
|
*/
|
||||||
|
tweakManager.registerTweak(AlternativeDispenserRecipe(this))
|
||||||
|
tweakManager.registerTweak(CraftableDragonsBreath(this))
|
||||||
|
tweakManager.registerTweak(CraftableNametag(this))
|
||||||
|
tweakManager.registerTweak(CraftableSaddle(this))
|
||||||
|
tweakManager.registerTweak(CraftableShulkerShell(this))
|
||||||
|
tweakManager.registerTweak(CraftableSponge(this))
|
||||||
|
tweakManager.registerTweak(IceDecompression(this))
|
||||||
|
tweakManager.registerTweak(LogsToChests(this))
|
||||||
|
tweakManager.registerTweak(WoolToString(this))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Crop Tweaks
|
||||||
|
*/
|
||||||
|
tweakManager.registerTweak(HoeHarvestArea(this))
|
||||||
|
tweakManager.registerTweak(LilypadBonemealing(this, util))
|
||||||
|
tweakManager.registerTweak(MobsCantTrampleCrops(this))
|
||||||
|
tweakManager.registerTweak(PlayersCantTrampleCrops(this, trampleManager))
|
||||||
|
tweakManager.registerTweak(SeedDropPlanting(this))
|
||||||
|
tweakManager.registerTweak(SugarcaneBonemealing(this))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Dispenser Tweaks
|
||||||
|
*/
|
||||||
|
tweakManager.registerTweak(DispensersCanPlantSaplings(this))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Miscellaneous Tweaks
|
||||||
|
*/
|
||||||
|
tweakManager.registerTweak(ArmorStandArmorSwapping(this))
|
||||||
|
tweakManager.registerTweak(CarpetBlockPlacingProtocol(this, mathHelper))
|
||||||
|
tweakManager.registerTweak(FakePlayers(fakePlayerManager))
|
||||||
|
tweakManager.registerTweak(SpaceTimePockets(this, pocketDimensionManager))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Mob Tweaks
|
||||||
|
*/
|
||||||
|
tweakManager.registerTweak(NoCreeperGrief(this))
|
||||||
|
tweakManager.registerTweak(NoDoorBreaking(this))
|
||||||
|
tweakManager.registerTweak(NoEndermanGrief(this))
|
||||||
|
tweakManager.registerTweak(VillagerInfo(this))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDisable() {
|
||||||
|
/*
|
||||||
|
* Save data to disk
|
||||||
|
*/
|
||||||
|
tweakManager.saveToFile(File(dataFolder, Const.TWEAK_STATE_FILE_NAME))
|
||||||
|
trampleManager.saveToFile(File(dataFolder, Const.TRAMPLE_ENABLED_FILE_NAME))
|
||||||
|
pocketDimensionManager.saveData()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun registerCommandConditions() {
|
||||||
|
commandManager.commandConditions.addCondition("tweakEnabled") { context ->
|
||||||
|
if (!tweakManager.isTweakEnabled(context.getConfigValue("tweak", "")))
|
||||||
|
throw ConditionFailedException("The tweak ${context.getConfigValue("tweak", "")} is not enabled!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,75 @@
|
||||||
|
package nl.kallestruik.dtweaks.commands
|
||||||
|
|
||||||
|
import co.aikar.commands.BaseCommand
|
||||||
|
import co.aikar.commands.annotation.*
|
||||||
|
import co.aikar.commands.annotation.Optional
|
||||||
|
import com.mojang.datafixers.util.Pair
|
||||||
|
import it.unimi.dsi.fastutil.objects.Object2IntMap
|
||||||
|
import net.kyori.adventure.text.Component
|
||||||
|
import net.kyori.adventure.text.format.TextColor
|
||||||
|
import net.minecraft.server.v1_16_R3.ChunkMapDistance
|
||||||
|
import net.minecraft.server.v1_16_R3.EnumCreatureType
|
||||||
|
import nl.kallestruik.dlib.ReflectionUtil
|
||||||
|
import org.bukkit.Bukkit
|
||||||
|
import org.bukkit.command.CommandSender
|
||||||
|
import org.bukkit.craftbukkit.v1_16_R3.CraftWorld
|
||||||
|
import org.bukkit.entity.Player
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
@CommandAlias("mobcaps")
|
||||||
|
class CommandMobcaps(
|
||||||
|
private val reflectionUtil: ReflectionUtil
|
||||||
|
): BaseCommand() {
|
||||||
|
|
||||||
|
@Default
|
||||||
|
@Subcommand("view")
|
||||||
|
@CommandCompletion("@worlds")
|
||||||
|
fun onMobcaps(sender: CommandSender, @Optional worldName: String?) {
|
||||||
|
var craftWorld: CraftWorld? = null
|
||||||
|
|
||||||
|
if (sender is Player)
|
||||||
|
craftWorld = (sender.world as CraftWorld)
|
||||||
|
else if (worldName == null)
|
||||||
|
sender.sendMessage(Component.text("ERROR: You need to be a player or supply a world name!").color(TextColor.color(0x660000)))
|
||||||
|
var name = worldName
|
||||||
|
if (worldName == null) {
|
||||||
|
name = craftWorld?.name
|
||||||
|
} else {
|
||||||
|
val bukkitWorld = Bukkit.getWorld(worldName)
|
||||||
|
if (bukkitWorld == null)
|
||||||
|
name = craftWorld?.name
|
||||||
|
else
|
||||||
|
craftWorld = (bukkitWorld as CraftWorld)
|
||||||
|
}
|
||||||
|
|
||||||
|
val world = craftWorld?.handle ?: return
|
||||||
|
|
||||||
|
val chunkMapDistance = (
|
||||||
|
reflectionUtil.getValueFromField(world.getChunkProvider(), "chunkMapDistance")
|
||||||
|
?: return
|
||||||
|
) as ChunkMapDistance
|
||||||
|
|
||||||
|
val chunks = chunkMapDistance.b()
|
||||||
|
|
||||||
|
// world.getChunkManager().getSpawnInfo();
|
||||||
|
val spawnInfo = world.getChunkProvider()?.k() ?: return
|
||||||
|
|
||||||
|
val mobs: Object2IntMap<EnumCreatureType> = spawnInfo.b()
|
||||||
|
val mobcaps = EnumMap<EnumCreatureType, Pair<Int, Int>>(
|
||||||
|
EnumCreatureType::class.java
|
||||||
|
)
|
||||||
|
for (category in EnumCreatureType.values()) {
|
||||||
|
if (category == EnumCreatureType.MISC) continue
|
||||||
|
val cur: Int = mobs[category]?: 0
|
||||||
|
val max = chunks * category.c() / (17 * 17)
|
||||||
|
mobcaps[category] = Pair(cur, max)
|
||||||
|
}
|
||||||
|
|
||||||
|
sender.sendMessage("=============Mobcaps [${name}]=============")
|
||||||
|
for ((key, value) in mobcaps) {
|
||||||
|
val cur = value.first
|
||||||
|
val max = value.second
|
||||||
|
sender.sendMessage("${key.getName()}: ${cur}/${max}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package nl.kallestruik.dtweaks.commands
|
||||||
|
|
||||||
|
import co.aikar.commands.BaseCommand
|
||||||
|
import co.aikar.commands.annotation.*
|
||||||
|
import nl.kallestruik.dtweaks.managers.FakePlayerManager
|
||||||
|
import nl.kallestruik.dtweaks.managers.TweakManager
|
||||||
|
import org.bukkit.command.CommandSender
|
||||||
|
import org.bukkit.entity.Player
|
||||||
|
|
||||||
|
@CommandAlias("player")
|
||||||
|
@Conditions("tweakEnabled:tweak=FakePlayers")
|
||||||
|
class CommandPlayer(
|
||||||
|
private val fakePlayerManager: FakePlayerManager,
|
||||||
|
private val tweakManager: TweakManager
|
||||||
|
): BaseCommand() {
|
||||||
|
|
||||||
|
@Subcommand("spawn")
|
||||||
|
@CommandCompletion("@players")
|
||||||
|
fun onSpawn(sender: Player, @Single playerName: String) {
|
||||||
|
fakePlayerManager.spawnFakePlayer(sender.location, playerName)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subcommand("kill")
|
||||||
|
@CommandCompletion("@players")
|
||||||
|
fun onKill(sender: Player, @Single playerName: String) {
|
||||||
|
fakePlayerManager.killFakePlayer(playerName)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
package nl.kallestruik.dtweaks.commands
|
||||||
|
|
||||||
|
import co.aikar.commands.BaseCommand
|
||||||
|
import co.aikar.commands.annotation.CommandAlias
|
||||||
|
import co.aikar.commands.annotation.Conditions
|
||||||
|
import co.aikar.commands.annotation.Subcommand
|
||||||
|
import nl.kallestruik.dtweaks.managers.PocketDimensionManager
|
||||||
|
import org.bukkit.entity.Player
|
||||||
|
|
||||||
|
@CommandAlias("pocketdim")
|
||||||
|
@Conditions("tweakEnabled:tweak=SpaceTimePockets")
|
||||||
|
class CommandPocketdim(
|
||||||
|
private val pocketDimensionManager: PocketDimensionManager
|
||||||
|
): BaseCommand() {
|
||||||
|
|
||||||
|
@Subcommand("create")
|
||||||
|
fun onCreate(sender: Player) {
|
||||||
|
pocketDimensionManager.createPocketForPlayer(sender)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subcommand("tp")
|
||||||
|
fun onTp(sender: Player) {
|
||||||
|
pocketDimensionManager.teleportPlayerIntoPocket(sender, sender.uniqueId)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
package nl.kallestruik.dtweaks.commands
|
||||||
|
|
||||||
|
import co.aikar.commands.BaseCommand
|
||||||
|
import co.aikar.commands.annotation.CommandAlias
|
||||||
|
import co.aikar.commands.annotation.Conditions
|
||||||
|
import co.aikar.commands.annotation.Default
|
||||||
|
import nl.kallestruik.dtweaks.managers.TrampleManager
|
||||||
|
import org.bukkit.ChatColor
|
||||||
|
import org.bukkit.entity.Player
|
||||||
|
|
||||||
|
@CommandAlias("toggletrample")
|
||||||
|
@Conditions("tweakEnabled:tweak=PlayersCantTrampleCrops")
|
||||||
|
class CommandToggletrample(
|
||||||
|
private val trampleManager: TrampleManager
|
||||||
|
): BaseCommand() {
|
||||||
|
|
||||||
|
@Default
|
||||||
|
fun onToggle(sender: Player) {
|
||||||
|
if (trampleManager.trampleEnabled.remove(sender.uniqueId)) {
|
||||||
|
sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&2Crop Trampling: &4&lDisabled"))
|
||||||
|
} else {
|
||||||
|
trampleManager.trampleEnabled.add(sender.uniqueId)
|
||||||
|
sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&2Crop Trampling: &2&lEnabled"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
package nl.kallestruik.dtweaks.fakeplayer
|
||||||
|
|
||||||
|
import io.netty.util.concurrent.Future
|
||||||
|
import io.netty.util.concurrent.GenericFutureListener
|
||||||
|
import net.minecraft.server.v1_16_R3.EnumProtocolDirection
|
||||||
|
import net.minecraft.server.v1_16_R3.NetworkManager
|
||||||
|
import net.minecraft.server.v1_16_R3.Packet
|
||||||
|
|
||||||
|
class FakeConnection(
|
||||||
|
enumProtocolDirection: EnumProtocolDirection
|
||||||
|
): NetworkManager(enumProtocolDirection) {
|
||||||
|
var open = true
|
||||||
|
|
||||||
|
// isOpen()
|
||||||
|
override fun isConnected(): Boolean {
|
||||||
|
return open
|
||||||
|
}
|
||||||
|
|
||||||
|
// hasChannel()
|
||||||
|
override fun i(): Boolean {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun sendPacket(packet: Packet<*>?, genericfuturelistener: GenericFutureListener<out Future<in Void?>?>?) {}
|
||||||
|
|
||||||
|
// disableAutoRead()
|
||||||
|
override fun stopReading() {}
|
||||||
|
|
||||||
|
override fun handleDisconnection() {}
|
||||||
|
}
|
|
@ -0,0 +1,168 @@
|
||||||
|
package nl.kallestruik.dtweaks.fakeplayer
|
||||||
|
|
||||||
|
import com.mojang.authlib.GameProfile
|
||||||
|
import net.minecraft.server.v1_16_R3.*
|
||||||
|
import nl.kallestruik.dtweaks.DTweaks
|
||||||
|
import org.bukkit.Location
|
||||||
|
import org.bukkit.craftbukkit.v1_16_R3.CraftWorld
|
||||||
|
|
||||||
|
class FakePlayer(
|
||||||
|
minecraftServer: MinecraftServer?,
|
||||||
|
worldServer: WorldServer?,
|
||||||
|
gameProfile: GameProfile?,
|
||||||
|
playerInteractManager: PlayerInteractManager?
|
||||||
|
): EntityPlayer(minecraftServer, worldServer, gameProfile, playerInteractManager) {
|
||||||
|
val locale = "en_US"
|
||||||
|
private var hasStartingPos = false
|
||||||
|
private var startingX = 0.0
|
||||||
|
private var startingY = 0.0
|
||||||
|
private var startingZ = 0.0
|
||||||
|
private var startingYaw = 0f
|
||||||
|
private var startingPitch = 0f
|
||||||
|
|
||||||
|
private constructor(
|
||||||
|
server: MinecraftServer,
|
||||||
|
worldIn: WorldServer,
|
||||||
|
profile: GameProfile?,
|
||||||
|
interactionManagerIn: PlayerInteractManager,
|
||||||
|
x: Double,
|
||||||
|
y: Double,
|
||||||
|
z: Double,
|
||||||
|
yaw: Float,
|
||||||
|
pitch: Float
|
||||||
|
) : this(server, worldIn, profile, interactionManagerIn) {
|
||||||
|
this.hasStartingPos = true
|
||||||
|
this.startingX = x
|
||||||
|
this.startingY = y
|
||||||
|
this.startingZ = z
|
||||||
|
this.startingYaw = yaw
|
||||||
|
this.startingPitch = pitch
|
||||||
|
applyStartingPosition()
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun atLocation(location: Location, name: String?): FakePlayer? {
|
||||||
|
// Split the location into its parts for use later.
|
||||||
|
val x = location.x
|
||||||
|
val y = location.y
|
||||||
|
val z = location.z
|
||||||
|
val yaw = location.yaw.toDouble()
|
||||||
|
val pitch = location.pitch.toDouble()
|
||||||
|
try {
|
||||||
|
// Get the minecraft server instance.
|
||||||
|
val minecraftServer = MinecraftServer.getServer()
|
||||||
|
// Create an empty variable for the world server.
|
||||||
|
val worldServer = (location.world as CraftWorld).handle
|
||||||
|
// Get the game profile from the cache (or retrieve it if it is not cached)
|
||||||
|
var gameProfile = minecraftServer.userCache.getProfile(name) ?: return null
|
||||||
|
if (gameProfile.properties.containsKey("textures")) {
|
||||||
|
gameProfile = TileEntitySkull.b(gameProfile, null, true).get()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a player interact manager using the world server.
|
||||||
|
val playerInteractManager = PlayerInteractManager(worldServer)
|
||||||
|
|
||||||
|
// Create an instance of our fake player.
|
||||||
|
val instance = FakePlayer(
|
||||||
|
minecraftServer, worldServer, gameProfile, playerInteractManager, x, y, z,
|
||||||
|
yaw.toFloat(),
|
||||||
|
pitch.toFloat()
|
||||||
|
)
|
||||||
|
// Create a fake connection for our fake player.
|
||||||
|
val connection = FakeConnection(EnumProtocolDirection.SERVERBOUND)
|
||||||
|
|
||||||
|
// Set access to connected channels so we can add our own connection.
|
||||||
|
val serverConnection = minecraftServer.serverConnection
|
||||||
|
|
||||||
|
(DTweaks.reflectionUtil.getValueFromField(
|
||||||
|
serverConnection!!,
|
||||||
|
"connectedChannels"
|
||||||
|
) as MutableList<NetworkManager?>).add(connection)
|
||||||
|
|
||||||
|
// Connect the fake player to the server using the fake connection.
|
||||||
|
FakePlayerList.a(minecraftServer.playerList, connection, instance)
|
||||||
|
|
||||||
|
// Check if the fake player is not yet in the correct world.
|
||||||
|
if (instance.world.dimensionKey != worldServer.dimensionKey) {
|
||||||
|
// Store the old world of the fake player.
|
||||||
|
val old_world = instance.world as WorldServer
|
||||||
|
// Remove the fake player from the old world.
|
||||||
|
old_world.removePlayer(instance)
|
||||||
|
// Make the fake player not be dead.
|
||||||
|
instance.dead = false
|
||||||
|
// Create the fake player in the new world.
|
||||||
|
worldServer.addEntity(instance)
|
||||||
|
// Spawn the fake player in the new world.
|
||||||
|
instance.spawnIn(worldServer)
|
||||||
|
// Move the fake player to the new world for the server.
|
||||||
|
minecraftServer.playerList.moveToWorld(instance, old_world, true, null, false)
|
||||||
|
// requestTeleport(x, y, z, yaw, pitch)
|
||||||
|
// Request the teleport from the fake player.
|
||||||
|
instance.playerConnection.a(x, y, z, yaw.toFloat(), pitch.toFloat())
|
||||||
|
// Set the fake player's world to the new world.
|
||||||
|
instance.playerInteractManager.world = worldServer
|
||||||
|
instance.teleportTo(worldServer, BlockPosition(x, y, z))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the fake players health to max.
|
||||||
|
instance.health = 20.0f
|
||||||
|
// Make the fake player not be dead.
|
||||||
|
instance.dead = false
|
||||||
|
// a == requestTeleport
|
||||||
|
// Request the teleport from the fake player.
|
||||||
|
instance.playerConnection.a(x, y, z, yaw.toFloat(), pitch.toFloat())
|
||||||
|
// G == stepHeight
|
||||||
|
// Set the fake players step height to 0.6 (The normal value).
|
||||||
|
instance.G = 0.6f
|
||||||
|
// Set the fake players gamemode to survival.
|
||||||
|
playerInteractManager.gameMode = EnumGamemode.SURVIVAL
|
||||||
|
// Tell everyone in the world about the fake player and where he is.
|
||||||
|
minecraftServer.playerList.a(
|
||||||
|
PacketPlayOutEntityHeadRotation(instance, (instance.yaw * 256 / 360).toByte()),
|
||||||
|
instance.world.dimensionKey
|
||||||
|
)
|
||||||
|
minecraftServer.playerList.a(PacketPlayOutEntityTeleport(instance), instance.world.dimensionKey)
|
||||||
|
// Move the fake player for the worlds chunk provider.
|
||||||
|
instance.worldServer.getChunkProvider().movePlayer(instance)
|
||||||
|
// bp == PLAYER_MODEL_PARTS
|
||||||
|
instance.datawatcher.set<Byte>(bj, 0x7f.toByte()) // show all model layers (incl. capes)
|
||||||
|
return instance
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun applyStartingPosition() {
|
||||||
|
if (hasStartingPos) {
|
||||||
|
this.setPositionRotation(startingX, startingY, startingZ, startingYaw, startingPitch)
|
||||||
|
mot = Vec3D(0.0, 0.0, 0.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun killEntity() {
|
||||||
|
server.a(TickTask(server.ai()) { playerConnection.a(ChatComponentText("Killed")) })
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun tick() {
|
||||||
|
super.tick()
|
||||||
|
if (H()) {
|
||||||
|
I()
|
||||||
|
}
|
||||||
|
movementTick()
|
||||||
|
if (server.ai() % 10 == 0) {
|
||||||
|
playerConnection.syncPosition()
|
||||||
|
this.worldServer.getChunkProvider().movePlayer(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun die(cause: DamageSource?) {
|
||||||
|
super.die(cause)
|
||||||
|
health = 20f
|
||||||
|
foodData = FoodMetaData(this)
|
||||||
|
killEntity()
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
package nl.kallestruik.dtweaks.fakeplayer
|
||||||
|
|
||||||
|
import net.minecraft.server.v1_16_R3.*
|
||||||
|
import nl.kallestruik.dtweaks.DTweaks
|
||||||
|
import java.lang.reflect.Field
|
||||||
|
|
||||||
|
class FakePlayerConnection(
|
||||||
|
minecraftServer: MinecraftServer,
|
||||||
|
networkManager: NetworkManager,
|
||||||
|
entityPlayer: EntityPlayer
|
||||||
|
): PlayerConnection(minecraftServer, networkManager, entityPlayer) {
|
||||||
|
override fun sendPacket(packet: Packet<*>?) {
|
||||||
|
if (packet is PacketPlayOutKeepAlive) {
|
||||||
|
val pong = PacketPlayInKeepAlive()
|
||||||
|
try {
|
||||||
|
val pingId: Field = DTweaks.reflectionUtil.getField(PacketPlayOutKeepAlive::class.java, "a")
|
||||||
|
val pongId: Field = DTweaks.reflectionUtil.getField(PacketPlayInKeepAlive::class.java, "a")
|
||||||
|
pingId.isAccessible = true
|
||||||
|
pongId.isAccessible = true
|
||||||
|
pongId[pong] = pingId[packet]
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
this.a(pong)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun disconnect(message: String?) {
|
||||||
|
player.killEntity()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun a(disconnectReason: IChatBaseComponent?) {
|
||||||
|
super.a(disconnectReason)
|
||||||
|
(this.a() as FakeConnection).open = false
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,258 @@
|
||||||
|
package nl.kallestruik.dtweaks.fakeplayer
|
||||||
|
|
||||||
|
import com.mojang.serialization.DataResult
|
||||||
|
import com.mojang.serialization.Dynamic
|
||||||
|
import io.netty.buffer.Unpooled
|
||||||
|
import net.minecraft.server.v1_16_R3.*
|
||||||
|
import nl.kallestruik.dtweaks.DTweaks
|
||||||
|
import org.apache.logging.log4j.Logger
|
||||||
|
import org.bukkit.Bukkit
|
||||||
|
import org.bukkit.craftbukkit.v1_16_R3.CraftWorld
|
||||||
|
import org.bukkit.craftbukkit.v1_16_R3.util.CraftChatMessage
|
||||||
|
import org.bukkit.entity.Player
|
||||||
|
import org.spigotmc.event.player.PlayerSpawnLocationEvent
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
object FakePlayerList {
|
||||||
|
fun a(playerList: PlayerList, networkManager: NetworkManager, entityPlayer: EntityPlayer) {
|
||||||
|
// Setup what are normally class level variables
|
||||||
|
val server = DTweaks.reflectionUtil.getValueFromField(playerList, "server") as MinecraftServer
|
||||||
|
val LOGGER = DTweaks.reflectionUtil.getValueFromField(playerList, "LOGGER") as Logger
|
||||||
|
|
||||||
|
val gameProfile = entityPlayer.profile
|
||||||
|
val userCache = server.userCache
|
||||||
|
val oldGameProfile = userCache.getProfile(gameProfile.id)
|
||||||
|
var oldName = if (oldGameProfile == null) gameProfile.name else oldGameProfile.name
|
||||||
|
|
||||||
|
userCache.a(gameProfile)
|
||||||
|
val playerData = playerList.a(entityPlayer)
|
||||||
|
if (playerData != null && playerData.hasKey("bukkit")) {
|
||||||
|
val bukkit = playerData.getCompound("bukkit")
|
||||||
|
oldName = if (bukkit.hasKeyOfType("lastKnownName", 8)) bukkit.getString("lastKnownName") else oldName
|
||||||
|
}
|
||||||
|
val worldKey: ResourceKey<World> = if (playerData != null) {
|
||||||
|
val dataResult: DataResult<ResourceKey<World>> = DimensionManager.a(
|
||||||
|
Dynamic(
|
||||||
|
DynamicOpsNBT.a,
|
||||||
|
playerData["Dimension"]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
dataResult.resultOrPartial { o -> LOGGER.error(o) }
|
||||||
|
.orElse(World.OVERWORLD) as ResourceKey<World>
|
||||||
|
} else {
|
||||||
|
World.OVERWORLD
|
||||||
|
}
|
||||||
|
var worldServer = server.getWorldServer(worldKey) ?: server.E()
|
||||||
|
|
||||||
|
entityPlayer.spawnIn(worldServer)
|
||||||
|
entityPlayer.playerInteractManager.a(entityPlayer.world as WorldServer)
|
||||||
|
var s1 = "local"
|
||||||
|
if (networkManager.getSocketAddress() != null) {
|
||||||
|
s1 = networkManager.getSocketAddress().toString()
|
||||||
|
}
|
||||||
|
val bukkitPlayer: Player = entityPlayer.bukkitEntity
|
||||||
|
val ev = PlayerSpawnLocationEvent(bukkitPlayer, bukkitPlayer.location)
|
||||||
|
Bukkit.getPluginManager().callEvent(ev)
|
||||||
|
val loc = ev.spawnLocation
|
||||||
|
worldServer = (loc.world as CraftWorld).handle
|
||||||
|
entityPlayer.spawnIn(worldServer)
|
||||||
|
entityPlayer.playerInteractManager.a(entityPlayer.world as WorldServer)
|
||||||
|
entityPlayer.setPosition(loc.x, loc.y, loc.z)
|
||||||
|
|
||||||
|
//entityplayer.setYawPitch(loc.getYaw(), loc.getPitch());
|
||||||
|
try {
|
||||||
|
val setYawPitch = Entity::class.java.getDeclaredMethod(
|
||||||
|
"setYawPitch",
|
||||||
|
Float::class.javaPrimitiveType,
|
||||||
|
Float::class.javaPrimitiveType
|
||||||
|
)
|
||||||
|
setYawPitch.isAccessible = true
|
||||||
|
setYawPitch.invoke(entityPlayer, loc.yaw, loc.pitch)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
val worldData = worldServer.getWorldData()
|
||||||
|
|
||||||
|
//playerList.a(entityplayer, (EntityPlayer)null, worldserver1);
|
||||||
|
try {
|
||||||
|
val a = PlayerList::class.java.getDeclaredMethod(
|
||||||
|
"a",
|
||||||
|
EntityPlayer::class.java,
|
||||||
|
EntityPlayer::class.java,
|
||||||
|
WorldServer::class.java
|
||||||
|
)
|
||||||
|
a.isAccessible = true
|
||||||
|
a.invoke(playerList, entityPlayer, null, worldServer)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
|
||||||
|
//PlayerConnection playerconnection = new PlayerConnection(server, networkmanager, entityplayer);
|
||||||
|
val playerConnection: PlayerConnection =
|
||||||
|
(entityPlayer as? FakePlayer)?.let { FakePlayerConnection(server, networkManager, it) }
|
||||||
|
?: PlayerConnection(server, networkManager, entityPlayer)
|
||||||
|
val gameRules = worldServer.gameRules
|
||||||
|
val doImmediateRespawn = gameRules.getBoolean(GameRules.DO_IMMEDIATE_RESPAWN)
|
||||||
|
val reducedDebugInfo = gameRules.getBoolean(GameRules.REDUCED_DEBUG_INFO)
|
||||||
|
try {
|
||||||
|
playerConnection.sendPacket(
|
||||||
|
PacketPlayOutLogin(
|
||||||
|
entityPlayer.id,
|
||||||
|
entityPlayer.playerInteractManager.gameMode,
|
||||||
|
entityPlayer.playerInteractManager.c(),
|
||||||
|
BiomeManager.a(
|
||||||
|
worldServer.seed
|
||||||
|
),
|
||||||
|
worldData.isHardcore,
|
||||||
|
server.F(),
|
||||||
|
DTweaks.reflectionUtil.getValueFromField(playerList, "s") as IRegistryCustom.Dimension,
|
||||||
|
worldServer.dimensionManager,
|
||||||
|
worldServer.dimensionKey,
|
||||||
|
playerList.maxPlayers,
|
||||||
|
worldServer.spigotConfig.viewDistance,
|
||||||
|
reducedDebugInfo,
|
||||||
|
!doImmediateRespawn,
|
||||||
|
worldServer.isDebugWorld,
|
||||||
|
worldServer.isFlatWorld
|
||||||
|
)
|
||||||
|
)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
entityPlayer.bukkitEntity.sendSupportedChannels()
|
||||||
|
playerConnection.sendPacket(
|
||||||
|
PacketPlayOutCustomPayload(
|
||||||
|
PacketPlayOutCustomPayload.a,
|
||||||
|
PacketDataSerializer(Unpooled.buffer()).a(playerList.server.serverModName)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
playerConnection.sendPacket(PacketPlayOutServerDifficulty(worldData.difficulty, worldData.isDifficultyLocked))
|
||||||
|
playerConnection.sendPacket(PacketPlayOutAbilities(entityPlayer.abilities))
|
||||||
|
playerConnection.sendPacket(PacketPlayOutHeldItemSlot(entityPlayer.inventory.itemInHandIndex))
|
||||||
|
playerConnection.sendPacket(PacketPlayOutRecipeUpdate(server.craftingManager.b()))
|
||||||
|
playerConnection.sendPacket(PacketPlayOutTags(server.tagRegistry))
|
||||||
|
playerList.d(entityPlayer)
|
||||||
|
entityPlayer.statisticManager.c()
|
||||||
|
entityPlayer.recipeBook.a(entityPlayer)
|
||||||
|
playerList.sendScoreboard(worldServer.scoreboard, entityPlayer)
|
||||||
|
server.invalidatePingSample()
|
||||||
|
val chatMessage = if (entityPlayer.profile.name.equals(oldName, ignoreCase = true)) {
|
||||||
|
ChatMessage("multiplayer.player.joined", entityPlayer.scoreboardDisplayName)
|
||||||
|
} else {
|
||||||
|
ChatMessage("multiplayer.player.joined.renamed", entityPlayer.scoreboardDisplayName, oldName)
|
||||||
|
}
|
||||||
|
chatMessage.a(EnumChatFormat.YELLOW)
|
||||||
|
var joinMessage = CraftChatMessage.fromComponent(chatMessage)
|
||||||
|
playerConnection.a(
|
||||||
|
entityPlayer.locX(),
|
||||||
|
entityPlayer.locY(),
|
||||||
|
entityPlayer.locZ(),
|
||||||
|
entityPlayer.yaw,
|
||||||
|
entityPlayer.pitch
|
||||||
|
)
|
||||||
|
playerList.players.add(entityPlayer)
|
||||||
|
|
||||||
|
//playerList.playersByName.put(entityplayer.getName().toLowerCase(Locale.ROOT), entityplayer);
|
||||||
|
val playersByName = DTweaks.reflectionUtil.getValueFromField(playerList, "playersByName") as HashMap<String, EntityPlayer>
|
||||||
|
playersByName[entityPlayer.name.toLowerCase(Locale.ROOT)] = entityPlayer
|
||||||
|
|
||||||
|
//playerList.j.put(entityplayer.getUniqueID(), entityplayer);
|
||||||
|
val playersByUUID = DTweaks.reflectionUtil.getValueFromField(playerList, "j") as HashMap<UUID, EntityPlayer>
|
||||||
|
playersByUUID[entityPlayer.uniqueID] = entityPlayer
|
||||||
|
|
||||||
|
if (entityPlayer.playerConnection.networkManager.isConnected) {
|
||||||
|
var i: Int
|
||||||
|
if (joinMessage != null && joinMessage.isNotEmpty()) {
|
||||||
|
var var27: Array<IChatBaseComponent?>
|
||||||
|
val var26 = CraftChatMessage.fromString(joinMessage).also { var27 = it }.size
|
||||||
|
i = 0
|
||||||
|
while (i < var26) {
|
||||||
|
val line = var27[i]
|
||||||
|
server.playerList.sendAll(PacketPlayOutChat(line, ChatMessageType.SYSTEM, SystemUtils.b))
|
||||||
|
++i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val packet = PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER, entityPlayer)
|
||||||
|
for (player in playerList.players) {
|
||||||
|
if (player.bukkitEntity.canSee(entityPlayer.bukkitEntity)) {
|
||||||
|
player.playerConnection.sendPacket(packet)
|
||||||
|
}
|
||||||
|
if (entityPlayer.bukkitEntity.canSee(player.bukkitEntity)) {
|
||||||
|
entityPlayer.playerConnection.sendPacket(
|
||||||
|
PacketPlayOutPlayerInfo(
|
||||||
|
PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER,
|
||||||
|
player
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
entityPlayer.sentListPacket = true
|
||||||
|
entityPlayer.playerConnection.sendPacket(
|
||||||
|
PacketPlayOutEntityMetadata(
|
||||||
|
entityPlayer.id,
|
||||||
|
DTweaks.reflectionUtil.getValueFromField(entityPlayer, "datawatcher") as DataWatcher, true
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if (entityPlayer.world === worldServer && !worldServer.getPlayers().contains(entityPlayer)) {
|
||||||
|
worldServer.addPlayerJoin(entityPlayer)
|
||||||
|
server.bossBattleCustomData.a(entityPlayer)
|
||||||
|
}
|
||||||
|
|
||||||
|
worldServer = entityPlayer.worldServer
|
||||||
|
playerList.a(entityPlayer, worldServer)
|
||||||
|
if (server.resourcePack.isNotEmpty()) {
|
||||||
|
entityPlayer.setResourcePack(server.resourcePack, server.resourcePackHash)
|
||||||
|
}
|
||||||
|
|
||||||
|
for (mobEffect in entityPlayer.getEffects()) {
|
||||||
|
playerConnection.sendPacket(PacketPlayOutEntityEffect(entityPlayer.id, mobEffect))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (playerData != null && playerData.hasKeyOfType("RootVehicle", 10)) {
|
||||||
|
val rootVehicleData = playerData.getCompound("RootVehicle")
|
||||||
|
val entity = EntityTypes.a(
|
||||||
|
rootVehicleData.getCompound("Entity"), worldServer
|
||||||
|
) { entity1x: Entity? ->
|
||||||
|
if (!worldServer.addEntitySerialized(entity1x)
|
||||||
|
) null else entity1x
|
||||||
|
}
|
||||||
|
if (entity != null) {
|
||||||
|
val uuid: UUID? = if (rootVehicleData.b("Attach")) {
|
||||||
|
rootVehicleData.a("Attach")
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
if (entity.uniqueID == uuid) {
|
||||||
|
entityPlayer.a(entity, true)
|
||||||
|
} else {
|
||||||
|
for (passenger in entity.allPassengers) {
|
||||||
|
if (passenger.uniqueID == uuid) {
|
||||||
|
entityPlayer.a(passenger, true)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!entityPlayer.isPassenger) {
|
||||||
|
LOGGER.warn("Couldn't reattach entity to player")
|
||||||
|
worldServer.removeEntity(entity)
|
||||||
|
for (passenger in entity.allPassengers) {
|
||||||
|
worldServer.removeEntity(passenger)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
entityPlayer.syncInventory()
|
||||||
|
LOGGER.info(
|
||||||
|
"{}[{}] logged in with entity id {} at ([{}]{}, {}, {})",
|
||||||
|
entityPlayer.getDisplayName().string,
|
||||||
|
s1,
|
||||||
|
entityPlayer.id,
|
||||||
|
worldServer?.worldDataServer?.name,
|
||||||
|
entityPlayer.locX(),
|
||||||
|
entityPlayer.locY(),
|
||||||
|
entityPlayer.locZ()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
package nl.kallestruik.dtweaks.managers
|
||||||
|
|
||||||
|
import nl.kallestruik.dtweaks.fakeplayer.FakePlayer
|
||||||
|
import org.bukkit.Bukkit
|
||||||
|
import org.bukkit.Location
|
||||||
|
import org.bukkit.craftbukkit.v1_16_R3.entity.CraftPlayer
|
||||||
|
|
||||||
|
class FakePlayerManager {
|
||||||
|
|
||||||
|
fun spawnFakePlayer(loc: Location, name: String) {
|
||||||
|
val player = Bukkit.getPlayer(name)
|
||||||
|
if (player != null && player.isOnline) return
|
||||||
|
FakePlayer.atLocation(loc, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun killFakePlayer(name: String) {
|
||||||
|
val player = Bukkit.getPlayer(name)
|
||||||
|
if (player == null || !player.isOnline) return
|
||||||
|
val entityPlayer = (player as CraftPlayer).handle as? FakePlayer ?: return
|
||||||
|
entityPlayer.killEntity()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun killAllFakePlayers() {
|
||||||
|
for (player in Bukkit.getOnlinePlayers()) {
|
||||||
|
if (!player.isOnline) continue
|
||||||
|
val entityPlayer = (player as CraftPlayer).handle as? FakePlayer ?: continue
|
||||||
|
entityPlayer.killEntity()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,110 @@
|
||||||
|
package nl.kallestruik.dtweaks.managers
|
||||||
|
|
||||||
|
import net.minecraft.server.v1_16_R3.MathHelper
|
||||||
|
import nl.kallestruik.dlib.MathHelper
|
||||||
|
import nl.kallestruik.dtweaks.spacetimepockets.SpaceTimePocketChunkGenerator
|
||||||
|
import org.bukkit.*
|
||||||
|
import org.bukkit.entity.Player
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
class PocketDimensionManager(
|
||||||
|
private val mathHelper: MathHelper
|
||||||
|
) {
|
||||||
|
val pocketDimension: World = WorldCreator.name("space-time-pockets").generator(SpaceTimePocketChunkGenerator()).createWorld()!!
|
||||||
|
private val data = HashMap<UUID, PocketData>()
|
||||||
|
private var lastCreatedPocket = -1
|
||||||
|
|
||||||
|
fun loadData() {
|
||||||
|
//TODO: Load data from data file on disk.
|
||||||
|
}
|
||||||
|
|
||||||
|
fun saveData() {
|
||||||
|
//TODO: Save data to file on disk.
|
||||||
|
}
|
||||||
|
|
||||||
|
fun teleportPlayerIntoPocket(player: Player, pocketOwner: UUID) {
|
||||||
|
var pocketData = data[pocketOwner]
|
||||||
|
if (pocketData == null) pocketData = if (player.uniqueId == pocketOwner) {
|
||||||
|
createPocketForPlayer(player)
|
||||||
|
} else return
|
||||||
|
player.teleport(
|
||||||
|
Location(
|
||||||
|
pocketDimension, (pocketData.startX + 9).toDouble(), 128.0,
|
||||||
|
(pocketData.startZ + 9).toDouble()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
Bukkit.unloadWorld()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createPocketForPlayer(player: Player): PocketData {
|
||||||
|
// Find a spot
|
||||||
|
val point = findNextFree()
|
||||||
|
|
||||||
|
// Load the chunks
|
||||||
|
for (x in 0..2) {
|
||||||
|
for (y in 0..2) {
|
||||||
|
pocketDimension.loadChunk(point.x / 16 + x, point.z / 16 + y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build the box
|
||||||
|
for (x in 0..17) {
|
||||||
|
for (z in 0..17) {
|
||||||
|
for (y in 0..255) {
|
||||||
|
if (x == 0 || y == 0 || z == 0 || x == 17 || y == 255 || z == 17) {
|
||||||
|
pocketDimension.getBlockAt(point.x + x, y, point.z + z).type = Material.BLACK_CONCRETE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the spawning platform
|
||||||
|
pocketDimension.getBlockAt(point.x + 8, 127, point.z + 8).type = Material.STONE
|
||||||
|
pocketDimension.getBlockAt(point.x + 8, 127, point.z + 9).type = Material.STONE
|
||||||
|
pocketDimension.getBlockAt(point.x + 9, 127, point.z + 8).type = Material.STONE
|
||||||
|
pocketDimension.getBlockAt(point.x + 9, 127, point.z + 9).type = Material.STONE
|
||||||
|
|
||||||
|
// Unload the chunks
|
||||||
|
for (x in 0..2) {
|
||||||
|
for (y in 0..2) {
|
||||||
|
pocketDimension.unloadChunk(point.x / 16 + x, point.z / 16 + y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val pocketData = PocketData(player.uniqueId, point.x, point.z, ArrayList())
|
||||||
|
data[player.uniqueId] = pocketData
|
||||||
|
return pocketData
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun findNextFree(): Point {
|
||||||
|
while (true) {
|
||||||
|
lastCreatedPocket++
|
||||||
|
val toCheck = getXYForIndex(lastCreatedPocket)
|
||||||
|
val chunk = pocketDimension.getChunkAt(
|
||||||
|
Location(
|
||||||
|
pocketDimension,
|
||||||
|
toCheck.x.toDouble(), 0.0, toCheck.z.toDouble()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
val corner = chunk.getBlock(mathHelper.chunkAbs(toCheck.x % 16), 0, mathHelper.chunkAbs(toCheck.z % 16))
|
||||||
|
if (corner.type == Material.AIR) {
|
||||||
|
return toCheck
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getXYForIndex(index: Int): Point {
|
||||||
|
// Space the pockets 256 blocks (16 chunks) from each other with each pocket being 16 blocks (and two for walls)
|
||||||
|
// Also subtract 1 from each point so the interior is chunk aligned.
|
||||||
|
val x = (256 + 16) * (index % 1000) - 1
|
||||||
|
val z = (256 + 16) * (index / 1000) - 1
|
||||||
|
return Point(x, z)
|
||||||
|
}
|
||||||
|
|
||||||
|
class PocketData(var owner: UUID, var startX: Int, var startZ: Int, var queuedGateways: ArrayList<GatewayData?>)
|
||||||
|
|
||||||
|
class GatewayData
|
||||||
|
|
||||||
|
class Point(var x: Int, var y: Int, var z: Int) {
|
||||||
|
constructor(x: Int, z: Int) : this(x, 0, z) {}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
package nl.kallestruik.dtweaks.managers
|
||||||
|
|
||||||
|
import org.bukkit.configuration.InvalidConfigurationException
|
||||||
|
import org.bukkit.configuration.file.YamlConfiguration
|
||||||
|
import java.io.File
|
||||||
|
import java.io.IOException
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
class TrampleManager {
|
||||||
|
var trampleEnabled = HashSet<UUID>()
|
||||||
|
|
||||||
|
@Throws(IOException::class, InvalidConfigurationException::class)
|
||||||
|
fun loadFromFile(file: File) {
|
||||||
|
file.parentFile.mkdirs()
|
||||||
|
file.createNewFile()
|
||||||
|
val config = YamlConfiguration()
|
||||||
|
config.load(file)
|
||||||
|
for (item in config.getStringList("enabled"))
|
||||||
|
trampleEnabled.add(UUID.fromString(item))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Throws(IOException::class, InvalidConfigurationException::class)
|
||||||
|
fun saveToFile(file: File) {
|
||||||
|
file.parentFile.mkdirs()
|
||||||
|
file.createNewFile()
|
||||||
|
val config = YamlConfiguration()
|
||||||
|
config.load(file)
|
||||||
|
val list: MutableList<String> = ArrayList()
|
||||||
|
for (entry in trampleEnabled)
|
||||||
|
list.add(entry.toString())
|
||||||
|
|
||||||
|
config["enabled"] = list
|
||||||
|
config.save(file)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,116 @@
|
||||||
|
package nl.kallestruik.dtweaks.managers
|
||||||
|
|
||||||
|
import nl.kallestruik.dtweaks.Const
|
||||||
|
import nl.kallestruik.dtweaks.tweaks.ITweak
|
||||||
|
import org.bukkit.configuration.InvalidConfigurationException
|
||||||
|
import org.bukkit.configuration.file.YamlConfiguration
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin
|
||||||
|
import java.io.File
|
||||||
|
import java.io.IOException
|
||||||
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
|
|
||||||
|
class TweakManager(
|
||||||
|
private val plugin: JavaPlugin
|
||||||
|
) {
|
||||||
|
|
||||||
|
// A HashMap containing the tweak identifier mapped to the instance of the tweak.
|
||||||
|
private val tweaks: ConcurrentHashMap<String, ITweak> = ConcurrentHashMap<String, ITweak>()
|
||||||
|
|
||||||
|
// A HashMap containing categories and the tweak identifiers that belong to them.
|
||||||
|
private val tweakCategories = HashMap<String, List<String>>()
|
||||||
|
|
||||||
|
// A HashMap containing the sate of all the known tweaks.
|
||||||
|
private val tweakStates = HashMap<String, Boolean>()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a new tweak.
|
||||||
|
*
|
||||||
|
* @param tweak An instance of the tweak.
|
||||||
|
* @return True if the tweak did not yet exist false otherwise.
|
||||||
|
*/
|
||||||
|
fun registerTweak(tweak: ITweak): Boolean {
|
||||||
|
if (tweaks.containsKey(tweak.getIdentifier())) return false
|
||||||
|
tweaks[tweak.getIdentifier()] = tweak
|
||||||
|
tweakCategories[tweak.getIdentifier()] = tweak.getCategories()
|
||||||
|
tweak.onRegister()
|
||||||
|
if (tweakStates.getOrDefault(tweak.getIdentifier(), false)) tweak.onEnable()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unregister a tweak.
|
||||||
|
*
|
||||||
|
* @param identifier The identifier of the tweak to unregister.
|
||||||
|
* @return True if the tweak was successfully unregistered false otherwise.
|
||||||
|
*/
|
||||||
|
fun unRegisterTweak(identifier: String): Boolean {
|
||||||
|
if (!tweaks.containsKey(identifier)) return false
|
||||||
|
val tweak: ITweak? = tweaks[identifier]
|
||||||
|
tweak?.onDisable()
|
||||||
|
tweak?.onUnRegister()
|
||||||
|
tweaks.remove(identifier)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unregister every tweak that is currently registered.
|
||||||
|
*/
|
||||||
|
fun unRegisterAllTweaks() {
|
||||||
|
for (identifier in tweaks.keys) {
|
||||||
|
unRegisterTweak(identifier)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable a tweak.
|
||||||
|
*
|
||||||
|
* @param identifier The identifier of the tweak.
|
||||||
|
* @return True if the tweak exists false otherwise.
|
||||||
|
*/
|
||||||
|
fun enableTweak(identifier: String): Boolean {
|
||||||
|
if (!tweaks.containsKey(identifier)) return false
|
||||||
|
tweakStates[identifier] = true
|
||||||
|
tweaks[identifier]?.onEnable()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disable a tweak.
|
||||||
|
*
|
||||||
|
* @param identifier The identifier of the tweak.
|
||||||
|
* @return True if the tweak exists false otherwise.
|
||||||
|
*/
|
||||||
|
fun disableTweak(identifier: String): Boolean {
|
||||||
|
if (!tweaks.containsKey(identifier)) return false
|
||||||
|
tweakStates[identifier] = false
|
||||||
|
tweaks[identifier]?.onDisable()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
@Throws(IOException::class, InvalidConfigurationException::class)
|
||||||
|
fun loadFromFile(file: File) {
|
||||||
|
if (!file.parentFile.exists()) file.parentFile.mkdirs()
|
||||||
|
if (!file.exists())
|
||||||
|
plugin.saveResource(file.name, false)
|
||||||
|
|
||||||
|
val config = YamlConfiguration()
|
||||||
|
config.load(file)
|
||||||
|
for (key in config.getKeys(false)) {
|
||||||
|
tweakStates[key] = config.getBoolean(key!!)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Throws(IOException::class)
|
||||||
|
fun saveToFile(file: File) {
|
||||||
|
val config = YamlConfiguration()
|
||||||
|
for ((key, value) in tweakStates.entries) {
|
||||||
|
config[key] = value
|
||||||
|
}
|
||||||
|
config.save(file)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isTweakEnabled(tweakId: String): Boolean {
|
||||||
|
return tweakStates[tweakId] ?: false
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
package nl.kallestruik.dtweaks.spacetimepockets
|
||||||
|
|
||||||
|
import org.bukkit.World
|
||||||
|
import org.bukkit.block.Biome
|
||||||
|
import org.bukkit.craftbukkit.v1_16_R3.generator.CraftChunkData
|
||||||
|
import org.bukkit.generator.ChunkGenerator
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
class SpaceTimePocketChunkGenerator: ChunkGenerator() {
|
||||||
|
|
||||||
|
override fun generateChunkData(
|
||||||
|
world: World,
|
||||||
|
random: Random,
|
||||||
|
x: Int,
|
||||||
|
z: Int,
|
||||||
|
biome: BiomeGrid
|
||||||
|
): ChunkData {
|
||||||
|
for (cx in 0..15) {
|
||||||
|
for (cz in 0..15) {
|
||||||
|
for (cy in 0..264) {
|
||||||
|
biome.setBiome(cx, cy, cz, Biome.THE_VOID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return CraftChunkData(world)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
package nl.kallestruik.dtweaks.tweaks
|
||||||
|
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin
|
||||||
|
|
||||||
|
interface ITweak {
|
||||||
|
fun getIdentifier(): String
|
||||||
|
|
||||||
|
fun getCategories(): List<String>
|
||||||
|
|
||||||
|
fun onRegister() {}
|
||||||
|
|
||||||
|
fun onUnRegister() {}
|
||||||
|
|
||||||
|
fun onEnable() {}
|
||||||
|
|
||||||
|
fun onDisable() {}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
package nl.kallestruik.dtweaks.tweaks.craftingtweaks
|
||||||
|
|
||||||
|
import nl.kallestruik.dtweaks.tweaks.ITweak
|
||||||
|
import org.bukkit.Bukkit
|
||||||
|
import org.bukkit.Material
|
||||||
|
import org.bukkit.NamespacedKey
|
||||||
|
import org.bukkit.inventory.ItemStack
|
||||||
|
import org.bukkit.inventory.ShapedRecipe
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin
|
||||||
|
|
||||||
|
class AlternativeDispenserRecipe(
|
||||||
|
private val plugin: JavaPlugin
|
||||||
|
): ITweak {
|
||||||
|
private var recipeKey = NamespacedKey(plugin, "dispenser")
|
||||||
|
|
||||||
|
override fun getIdentifier(): String = "AlternativeDispenserRecipe"
|
||||||
|
override fun getCategories(): List<String> = listOf("crafting", "survival")
|
||||||
|
|
||||||
|
override fun onEnable() {
|
||||||
|
val dispenserRecipe = ShapedRecipe(recipeKey, ItemStack(Material.DISPENSER))
|
||||||
|
dispenserRecipe.shape(" TS", "TDS", " TS")
|
||||||
|
dispenserRecipe.setIngredient('T', Material.STICK)
|
||||||
|
dispenserRecipe.setIngredient('D', Material.DROPPER)
|
||||||
|
dispenserRecipe.setIngredient('S', Material.STRING)
|
||||||
|
|
||||||
|
plugin.server.addRecipe(dispenserRecipe)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDisable() {
|
||||||
|
plugin.server.removeRecipe(recipeKey)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package nl.kallestruik.dtweaks.tweaks.craftingtweaks
|
||||||
|
|
||||||
|
import nl.kallestruik.dtweaks.tweaks.ITweak
|
||||||
|
import org.bukkit.Bukkit
|
||||||
|
import org.bukkit.Material
|
||||||
|
import org.bukkit.NamespacedKey
|
||||||
|
import org.bukkit.inventory.ItemStack
|
||||||
|
import org.bukkit.inventory.ShapedRecipe
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin
|
||||||
|
|
||||||
|
class CraftableDragonsBreath(
|
||||||
|
private val plugin: JavaPlugin
|
||||||
|
): ITweak {
|
||||||
|
private var recipeKey = NamespacedKey(plugin, "dragon_breath")
|
||||||
|
|
||||||
|
override fun getIdentifier(): String = "CraftableDragonsBreath"
|
||||||
|
override fun getCategories(): List<String> = listOf("crafting", "survival")
|
||||||
|
|
||||||
|
override fun onEnable() {
|
||||||
|
val dragonBreathRecipe = ShapedRecipe(recipeKey, ItemStack(Material.DRAGON_BREATH, 3))
|
||||||
|
dragonBreathRecipe.shape("GCG", " G ")
|
||||||
|
dragonBreathRecipe.setIngredient('G', Material.GLASS)
|
||||||
|
dragonBreathRecipe.setIngredient('C', Material.POPPED_CHORUS_FRUIT)
|
||||||
|
|
||||||
|
plugin.server.addRecipe(dragonBreathRecipe)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDisable() {
|
||||||
|
plugin.server.removeRecipe(recipeKey)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
package nl.kallestruik.dtweaks.tweaks.craftingtweaks
|
||||||
|
|
||||||
|
import nl.kallestruik.dtweaks.tweaks.ITweak
|
||||||
|
import org.bukkit.Bukkit
|
||||||
|
import org.bukkit.Material
|
||||||
|
import org.bukkit.NamespacedKey
|
||||||
|
import org.bukkit.inventory.ItemStack
|
||||||
|
import org.bukkit.inventory.ShapedRecipe
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin
|
||||||
|
|
||||||
|
class CraftableNametag(
|
||||||
|
private val plugin: JavaPlugin
|
||||||
|
): ITweak {
|
||||||
|
private var recipeKey = NamespacedKey(plugin, "nametag")
|
||||||
|
|
||||||
|
override fun getIdentifier(): String = "CraftableNametag"
|
||||||
|
override fun getCategories(): List<String> = listOf("crafting", "survival")
|
||||||
|
|
||||||
|
override fun onEnable() {
|
||||||
|
val nametagRecipe = ShapedRecipe(recipeKey, ItemStack(Material.NAME_TAG))
|
||||||
|
nametagRecipe.shape(" IS", " PI", "P ")
|
||||||
|
nametagRecipe.setIngredient('I', Material.IRON_INGOT)
|
||||||
|
nametagRecipe.setIngredient('P', Material.PAPER)
|
||||||
|
nametagRecipe.setIngredient('S', Material.STRING)
|
||||||
|
|
||||||
|
plugin.server.addRecipe(nametagRecipe)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDisable() {
|
||||||
|
plugin.server.removeRecipe(recipeKey)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
package nl.kallestruik.dtweaks.tweaks.craftingtweaks
|
||||||
|
|
||||||
|
import nl.kallestruik.dtweaks.tweaks.ITweak
|
||||||
|
import org.bukkit.Bukkit
|
||||||
|
import org.bukkit.Material
|
||||||
|
import org.bukkit.NamespacedKey
|
||||||
|
import org.bukkit.inventory.ItemStack
|
||||||
|
import org.bukkit.inventory.ShapedRecipe
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin
|
||||||
|
|
||||||
|
class CraftableSaddle(
|
||||||
|
private val plugin: JavaPlugin
|
||||||
|
): ITweak {
|
||||||
|
private var recipeKey = NamespacedKey(plugin, "saddle")
|
||||||
|
|
||||||
|
override fun getIdentifier(): String = "CraftableSaddle"
|
||||||
|
override fun getCategories(): List<String> = listOf("crafting", "survival")
|
||||||
|
|
||||||
|
override fun onEnable() {
|
||||||
|
val saddleRecipe = ShapedRecipe(recipeKey, ItemStack(Material.SADDLE))
|
||||||
|
saddleRecipe.shape("LLL", "S S", "I I")
|
||||||
|
saddleRecipe.setIngredient('L', Material.LEATHER)
|
||||||
|
saddleRecipe.setIngredient('S', Material.STRING)
|
||||||
|
saddleRecipe.setIngredient('I', Material.IRON_INGOT)
|
||||||
|
|
||||||
|
plugin.server.addRecipe(saddleRecipe)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDisable() {
|
||||||
|
plugin.server.removeRecipe(recipeKey)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package nl.kallestruik.dtweaks.tweaks.craftingtweaks
|
||||||
|
|
||||||
|
import nl.kallestruik.dtweaks.tweaks.ITweak
|
||||||
|
import org.bukkit.Bukkit
|
||||||
|
import org.bukkit.Material
|
||||||
|
import org.bukkit.NamespacedKey
|
||||||
|
import org.bukkit.inventory.ItemStack
|
||||||
|
import org.bukkit.inventory.ShapedRecipe
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin
|
||||||
|
|
||||||
|
class CraftableShulkerShell(
|
||||||
|
private val plugin: JavaPlugin
|
||||||
|
): ITweak {
|
||||||
|
private var recipeKey = NamespacedKey(plugin, "shulker_shell")
|
||||||
|
|
||||||
|
override fun getIdentifier(): String = "CraftableShulkerShell"
|
||||||
|
override fun getCategories(): List<String> = listOf("crafting", "survival")
|
||||||
|
|
||||||
|
override fun onEnable() {
|
||||||
|
val shulkerShellRecipe = ShapedRecipe(recipeKey, ItemStack(Material.SHULKER_SHELL))
|
||||||
|
shulkerShellRecipe.shape("BBB", "F F")
|
||||||
|
shulkerShellRecipe.setIngredient('B', Material.PURPUR_SLAB)
|
||||||
|
shulkerShellRecipe.setIngredient('F', Material.POPPED_CHORUS_FRUIT)
|
||||||
|
|
||||||
|
plugin.server.addRecipe(shulkerShellRecipe)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDisable() {
|
||||||
|
plugin.server.removeRecipe(recipeKey)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package nl.kallestruik.dtweaks.tweaks.craftingtweaks
|
||||||
|
|
||||||
|
import nl.kallestruik.dtweaks.tweaks.ITweak
|
||||||
|
import org.bukkit.Bukkit
|
||||||
|
import org.bukkit.Material
|
||||||
|
import org.bukkit.NamespacedKey
|
||||||
|
import org.bukkit.inventory.ItemStack
|
||||||
|
import org.bukkit.inventory.ShapedRecipe
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin
|
||||||
|
|
||||||
|
class CraftableSponge(
|
||||||
|
private val plugin: JavaPlugin
|
||||||
|
): ITweak {
|
||||||
|
private var recipeKey = NamespacedKey(plugin, "sponge")
|
||||||
|
|
||||||
|
override fun getIdentifier(): String = "CraftableSponge"
|
||||||
|
override fun getCategories(): List<String> = listOf("crafting", "survival")
|
||||||
|
|
||||||
|
override fun onEnable() {
|
||||||
|
val spongeRecipe = ShapedRecipe(recipeKey, ItemStack(Material.SPONGE))
|
||||||
|
spongeRecipe.shape("KKK", "KDK", "KKK")
|
||||||
|
spongeRecipe.setIngredient('K', Material.KELP)
|
||||||
|
spongeRecipe.setIngredient('D', Material.YELLOW_DYE)
|
||||||
|
|
||||||
|
plugin.server.addRecipe(spongeRecipe)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDisable() {
|
||||||
|
plugin.server.removeRecipe(recipeKey)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
package nl.kallestruik.dtweaks.tweaks.craftingtweaks
|
||||||
|
|
||||||
|
import nl.kallestruik.dtweaks.tweaks.ITweak
|
||||||
|
import org.bukkit.Bukkit
|
||||||
|
import org.bukkit.Material
|
||||||
|
import org.bukkit.NamespacedKey
|
||||||
|
import org.bukkit.inventory.ItemStack
|
||||||
|
import org.bukkit.inventory.ShapelessRecipe
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin
|
||||||
|
|
||||||
|
class IceDecompression(
|
||||||
|
private val plugin: JavaPlugin
|
||||||
|
): ITweak {
|
||||||
|
private var packedIceKey = NamespacedKey(plugin, "packed_ice")
|
||||||
|
private var iceKey = NamespacedKey(plugin, "ice")
|
||||||
|
|
||||||
|
override fun getIdentifier(): String = "IceDecompression"
|
||||||
|
override fun getCategories(): List<String> = listOf("crafting", "survival")
|
||||||
|
|
||||||
|
override fun onEnable() {
|
||||||
|
// Blue Ice -> Packed Ice
|
||||||
|
val packedIceRecipe = ShapelessRecipe(packedIceKey, ItemStack(Material.PACKED_ICE, 9))
|
||||||
|
packedIceRecipe.addIngredient(Material.BLUE_ICE)
|
||||||
|
plugin.server.addRecipe(packedIceRecipe)
|
||||||
|
|
||||||
|
// Packed Ice -> Ice
|
||||||
|
val iceRecipe = ShapelessRecipe(iceKey, ItemStack(Material.ICE, 9))
|
||||||
|
iceRecipe.addIngredient(Material.PACKED_ICE)
|
||||||
|
plugin.server.addRecipe(iceRecipe)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDisable() {
|
||||||
|
plugin.server.removeRecipe(packedIceKey)
|
||||||
|
plugin.server.removeRecipe(iceKey)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
package nl.kallestruik.dtweaks.tweaks.craftingtweaks
|
||||||
|
|
||||||
|
import nl.kallestruik.dtweaks.tweaks.ITweak
|
||||||
|
import org.bukkit.Bukkit
|
||||||
|
import org.bukkit.Material
|
||||||
|
import org.bukkit.NamespacedKey
|
||||||
|
import org.bukkit.Tag
|
||||||
|
import org.bukkit.inventory.ItemStack
|
||||||
|
import org.bukkit.inventory.RecipeChoice
|
||||||
|
import org.bukkit.inventory.ShapedRecipe
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin
|
||||||
|
|
||||||
|
class LogsToChests(
|
||||||
|
private val plugin: JavaPlugin
|
||||||
|
): ITweak {
|
||||||
|
private var recipeKey = NamespacedKey(plugin, "chest")
|
||||||
|
|
||||||
|
override fun getIdentifier(): String = "LogsToChests"
|
||||||
|
override fun getCategories(): List<String> = listOf("crafting", "survival")
|
||||||
|
|
||||||
|
override fun onEnable() {
|
||||||
|
val chestRecipe = ShapedRecipe(recipeKey, ItemStack(Material.CHEST, 4))
|
||||||
|
chestRecipe.shape("WWW", "W W", "WWW")
|
||||||
|
chestRecipe.setIngredient('W', RecipeChoice.MaterialChoice(Tag.LOGS))
|
||||||
|
|
||||||
|
plugin.server.addRecipe(chestRecipe)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDisable() {
|
||||||
|
plugin.server.removeRecipe(recipeKey)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
package nl.kallestruik.dtweaks.tweaks.craftingtweaks
|
||||||
|
|
||||||
|
import nl.kallestruik.dtweaks.tweaks.ITweak
|
||||||
|
import org.bukkit.Material
|
||||||
|
import org.bukkit.NamespacedKey
|
||||||
|
import org.bukkit.inventory.ItemStack
|
||||||
|
import org.bukkit.inventory.RecipeChoice
|
||||||
|
import org.bukkit.inventory.ShapedRecipe
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin
|
||||||
|
|
||||||
|
class RedyeTerracotta(
|
||||||
|
private val plugin: JavaPlugin
|
||||||
|
): ITweak {
|
||||||
|
private val blackRecipeKey = NamespacedKey(plugin, "black_terracotta")
|
||||||
|
private val blueRecipeKey = NamespacedKey(plugin, "blue_terracotta")
|
||||||
|
private val brownRecipeKey = NamespacedKey(plugin, "brown_terracotta")
|
||||||
|
private val cyanRecipeKey = NamespacedKey(plugin, "cyan_terracotta")
|
||||||
|
private val blueRecipeKey = NamespacedKey(plugin, "blue_terracotta")
|
||||||
|
private val blueRecipeKey = NamespacedKey(plugin, "blue_terracotta")
|
||||||
|
|
||||||
|
private val allTerracotta = RecipeChoice.MaterialChoice(Material.TERRACOTTA, Material.BLACK_TERRACOTTA,
|
||||||
|
Material.BLUE_TERRACOTTA, Material.BROWN_TERRACOTTA, Material.CYAN_TERRACOTTA, Material.GRAY_TERRACOTTA,
|
||||||
|
Material.GREEN_TERRACOTTA, Material.LIGHT_BLUE_TERRACOTTA,
|
||||||
|
Material.LIGHT_GRAY_TERRACOTTA, Material.LIME_TERRACOTTA, Material.MAGENTA_TERRACOTTA,
|
||||||
|
Material.ORANGE_TERRACOTTA, Material.PINK_TERRACOTTA, Material.PURPLE_TERRACOTTA, Material.RED_TERRACOTTA,
|
||||||
|
Material.WHITE_TERRACOTTA, Material.YELLOW_TERRACOTTA)
|
||||||
|
|
||||||
|
override fun getIdentifier(): String = "RedyeTerracotta"
|
||||||
|
override fun getCategories(): List<String> = listOf("crafting", "survival")
|
||||||
|
|
||||||
|
override fun onEnable() {
|
||||||
|
addRecipe(blackRecipeKey, Material.BLACK_TERRACOTTA, Material.BLACK_DYE)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDisable() {
|
||||||
|
plugin.server.removeRecipe(blackRecipeKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addRecipe(key: NamespacedKey, output: Material, dye: Material) {
|
||||||
|
val recipe = ShapedRecipe(key, ItemStack(output))
|
||||||
|
recipe.shape("TTT", "TDT", "TTT")
|
||||||
|
recipe.setIngredient('T', allTerracotta)
|
||||||
|
recipe.setIngredient('D', dye)
|
||||||
|
|
||||||
|
plugin.server.addRecipe(recipe)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package nl.kallestruik.dtweaks.tweaks.craftingtweaks
|
||||||
|
|
||||||
|
import nl.kallestruik.dtweaks.tweaks.ITweak
|
||||||
|
import org.bukkit.Bukkit
|
||||||
|
import org.bukkit.Material
|
||||||
|
import org.bukkit.NamespacedKey
|
||||||
|
import org.bukkit.Tag
|
||||||
|
import org.bukkit.inventory.ItemStack
|
||||||
|
import org.bukkit.inventory.RecipeChoice
|
||||||
|
import org.bukkit.inventory.ShapelessRecipe
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin
|
||||||
|
|
||||||
|
class WoolToString(
|
||||||
|
private val plugin: JavaPlugin
|
||||||
|
): ITweak {
|
||||||
|
private var recipeKey = NamespacedKey(plugin, "string")
|
||||||
|
|
||||||
|
override fun getIdentifier(): String = "WoolToString"
|
||||||
|
override fun getCategories(): List<String> = listOf("crafting", "survival")
|
||||||
|
|
||||||
|
override fun onEnable() {
|
||||||
|
val stringRecipe = ShapelessRecipe(recipeKey, ItemStack(Material.STRING, 4))
|
||||||
|
stringRecipe.addIngredient(RecipeChoice.MaterialChoice(Tag.WOOL))
|
||||||
|
|
||||||
|
plugin.server.addRecipe(stringRecipe)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDisable() {
|
||||||
|
plugin.server.removeRecipe(recipeKey)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
package nl.kallestruik.dtweaks.tweaks.croptweaks
|
||||||
|
|
||||||
|
import nl.kallestruik.dtweaks.tweaks.ITweak
|
||||||
|
import org.bukkit.Material
|
||||||
|
import org.bukkit.block.data.Ageable
|
||||||
|
import org.bukkit.event.EventHandler
|
||||||
|
import org.bukkit.event.HandlerList
|
||||||
|
import org.bukkit.event.Listener
|
||||||
|
import org.bukkit.event.block.BlockBreakEvent
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin
|
||||||
|
|
||||||
|
class HoeHarvestArea(
|
||||||
|
private val plugin: JavaPlugin
|
||||||
|
): ITweak, Listener {
|
||||||
|
override fun getIdentifier(): String = "HoesHarvestArea"
|
||||||
|
override fun getCategories(): List<String> = listOf("crops", "survival")
|
||||||
|
|
||||||
|
override fun onEnable() {
|
||||||
|
plugin.server.pluginManager.registerEvents(this, plugin)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDisable() {
|
||||||
|
HandlerList.unregisterAll(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
fun onHoeBreaksBlock(event: BlockBreakEvent) {
|
||||||
|
val player = event.player
|
||||||
|
val block = event.block
|
||||||
|
val world = block.world
|
||||||
|
val itemInHand = player.inventory.itemInMainHand
|
||||||
|
val range = when(itemInHand.type) {
|
||||||
|
Material.WOODEN_HOE -> 1
|
||||||
|
Material.STONE_HOE -> 1
|
||||||
|
Material.IRON_HOE -> 1
|
||||||
|
Material.GOLDEN_HOE -> 1
|
||||||
|
Material.DIAMOND_HOE -> 2
|
||||||
|
Material.NETHERITE_HOE -> 2
|
||||||
|
else -> return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isCrop(block.type)) return
|
||||||
|
|
||||||
|
val startLocation = block.location
|
||||||
|
for (x in -range..range) {
|
||||||
|
for (z in -range..range) {
|
||||||
|
val b = world.getBlockAt(startLocation.clone().add(x.toDouble(), 0.0, z.toDouble()))
|
||||||
|
if (isCrop(b.type)) {
|
||||||
|
val ageable = b.blockData as Ageable
|
||||||
|
if (ageable.age == ageable.maximumAge) {
|
||||||
|
b.breakNaturally()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun isCrop(material: Material): Boolean {
|
||||||
|
return material == Material.WHEAT || material == Material.BEETROOTS || material == Material.CARROTS || material == Material.POTATOES
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
package nl.kallestruik.dtweaks.tweaks.croptweaks
|
||||||
|
|
||||||
|
import nl.kallestruik.dlib.DUtil
|
||||||
|
import nl.kallestruik.dtweaks.tweaks.ITweak
|
||||||
|
import org.bukkit.Location
|
||||||
|
import org.bukkit.Material
|
||||||
|
import org.bukkit.Particle
|
||||||
|
import org.bukkit.event.EventHandler
|
||||||
|
import org.bukkit.event.HandlerList
|
||||||
|
import org.bukkit.event.Listener
|
||||||
|
import org.bukkit.event.block.Action
|
||||||
|
import org.bukkit.event.player.PlayerInteractEvent
|
||||||
|
import org.bukkit.inventory.EquipmentSlot
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin
|
||||||
|
|
||||||
|
class LilypadBonemealing(
|
||||||
|
private val plugin: JavaPlugin,
|
||||||
|
private val util: DUtil
|
||||||
|
): ITweak, Listener {
|
||||||
|
override fun getIdentifier(): String = "LilypadBonemealing"
|
||||||
|
override fun getCategories(): List<String> = listOf("crops", "survival")
|
||||||
|
|
||||||
|
override fun onEnable() {
|
||||||
|
plugin.server.pluginManager.registerEvents(this, plugin)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDisable() {
|
||||||
|
HandlerList.unregisterAll(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
fun onRightClickBlock(event: PlayerInteractEvent) {
|
||||||
|
val player = event.player
|
||||||
|
if (event.hand != EquipmentSlot.HAND) return
|
||||||
|
if (event.action != Action.RIGHT_CLICK_BLOCK) return
|
||||||
|
if (event.clickedBlock == null) return
|
||||||
|
if (event.clickedBlock!!.type != Material.LILY_PAD) return
|
||||||
|
|
||||||
|
val itemInHand = player.inventory.itemInMainHand
|
||||||
|
if (itemInHand.type != Material.BONE_MEAL) return
|
||||||
|
|
||||||
|
val world = event.clickedBlock!!.world
|
||||||
|
val origin = event.clickedBlock!!.location
|
||||||
|
for (i in 0..5) {
|
||||||
|
val newPos: Location = origin.clone().add(util.getRandomLocationOffset(0, 3, false))
|
||||||
|
val newBlock = world.getBlockAt(newPos)
|
||||||
|
if (newBlock.type != Material.AIR) continue
|
||||||
|
if (newBlock.getRelative(0, -1, 0).type != Material.WATER) continue
|
||||||
|
newBlock.type = Material.LILY_PAD
|
||||||
|
world.spawnParticle(Particle.VILLAGER_HAPPY, newPos, 5, 0.5, 0.5, 0.5)
|
||||||
|
}
|
||||||
|
itemInHand.amount = itemInHand.amount - 1
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
package nl.kallestruik.dtweaks.tweaks.croptweaks
|
||||||
|
|
||||||
|
import nl.kallestruik.dtweaks.tweaks.ITweak
|
||||||
|
import org.bukkit.Material
|
||||||
|
import org.bukkit.entity.Player
|
||||||
|
import org.bukkit.event.EventHandler
|
||||||
|
import org.bukkit.event.HandlerList
|
||||||
|
import org.bukkit.event.Listener
|
||||||
|
import org.bukkit.event.entity.EntityChangeBlockEvent
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin
|
||||||
|
|
||||||
|
class MobsCantTrampleCrops(
|
||||||
|
private val plugin: JavaPlugin
|
||||||
|
): ITweak, Listener {
|
||||||
|
override fun getIdentifier(): String = "MobsCantTrampleCrops"
|
||||||
|
override fun getCategories(): List<String> = listOf("crops", "mobs", "survival")
|
||||||
|
|
||||||
|
override fun onEnable() {
|
||||||
|
plugin.server.pluginManager.registerEvents(this, plugin)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDisable() {
|
||||||
|
HandlerList.unregisterAll(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
fun onBlockBreak(event: EntityChangeBlockEvent) {
|
||||||
|
if (event.block.type != Material.FARMLAND) return
|
||||||
|
if (event.entity is Player) return
|
||||||
|
event.isCancelled = true
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
package nl.kallestruik.dtweaks.tweaks.croptweaks
|
||||||
|
|
||||||
|
import nl.kallestruik.dtweaks.managers.TrampleManager
|
||||||
|
import nl.kallestruik.dtweaks.tweaks.ITweak
|
||||||
|
import org.bukkit.Material
|
||||||
|
import org.bukkit.entity.Player
|
||||||
|
import org.bukkit.event.EventHandler
|
||||||
|
import org.bukkit.event.HandlerList
|
||||||
|
import org.bukkit.event.Listener
|
||||||
|
import org.bukkit.event.entity.EntityChangeBlockEvent
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin
|
||||||
|
|
||||||
|
class PlayersCantTrampleCrops(
|
||||||
|
private val plugin: JavaPlugin,
|
||||||
|
private val trampleManager: TrampleManager
|
||||||
|
): ITweak, Listener {
|
||||||
|
override fun getIdentifier(): String = "PlayersCantTrampleCrops"
|
||||||
|
override fun getCategories(): List<String> = listOf("crops", "survival", "players")
|
||||||
|
|
||||||
|
override fun onEnable() {
|
||||||
|
plugin.server.pluginManager.registerEvents(this, plugin)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDisable() {
|
||||||
|
HandlerList.unregisterAll(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
fun onBlockBreak(event: EntityChangeBlockEvent) {
|
||||||
|
if (event.block.type != Material.FARMLAND) return
|
||||||
|
if (event.entity !is Player) return
|
||||||
|
if (trampleManager.trampleEnabled.contains(event.entity.uniqueId)) return
|
||||||
|
event.isCancelled = true
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,65 @@
|
||||||
|
package nl.kallestruik.dtweaks.tweaks.croptweaks
|
||||||
|
|
||||||
|
import nl.kallestruik.dtweaks.tweaks.ITweak
|
||||||
|
import org.bukkit.Bukkit
|
||||||
|
import org.bukkit.Material
|
||||||
|
import org.bukkit.Particle
|
||||||
|
import org.bukkit.World
|
||||||
|
import org.bukkit.block.Block
|
||||||
|
import org.bukkit.entity.Item
|
||||||
|
import org.bukkit.event.Listener
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin
|
||||||
|
import org.bukkit.scheduler.BukkitTask
|
||||||
|
|
||||||
|
class SeedDropPlanting(
|
||||||
|
private val plugin: JavaPlugin
|
||||||
|
): ITweak, Listener {
|
||||||
|
private lateinit var task: BukkitTask
|
||||||
|
|
||||||
|
override fun getIdentifier(): String = "SeedDropPlanting"
|
||||||
|
override fun getCategories(): List<String> = listOf("crops", "survival")
|
||||||
|
|
||||||
|
override fun onEnable() {
|
||||||
|
task = Bukkit.getScheduler().runTaskTimer(plugin, SeedPlantTask(plugin), (20 * 10).toLong(), (20 * 10).toLong())
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDisable() {
|
||||||
|
task.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
private class SeedPlantTask(
|
||||||
|
private val plugin: JavaPlugin
|
||||||
|
): Runnable {
|
||||||
|
override fun run() {
|
||||||
|
for (world in plugin.server.worlds) {
|
||||||
|
for (entity in world.entities) {
|
||||||
|
if (entity is Item) {
|
||||||
|
val b = world.getBlockAt(entity.location)
|
||||||
|
val above = world.getBlockAt(entity.location.add(0.0, 1.0, 0.0))
|
||||||
|
if (b.type == Material.FARMLAND && above.type == Material.AIR) {
|
||||||
|
when (entity.itemStack.type) {
|
||||||
|
Material.WHEAT_SEEDS -> plantSeed(entity, world, above, Material.WHEAT)
|
||||||
|
Material.BEETROOT_SEEDS -> plantSeed(entity, world, above, Material.BEETROOTS)
|
||||||
|
Material.MELON_SEEDS -> plantSeed(entity, world, above, Material.MELON_STEM)
|
||||||
|
Material.PUMPKIN_SEEDS -> plantSeed(entity, world, above, Material.PUMPKIN_STEM)
|
||||||
|
Material.POTATO -> plantSeed(entity, world, above, Material.POTATOES)
|
||||||
|
Material.CARROT -> plantSeed(entity, world, above, Material.CARROTS)
|
||||||
|
else -> continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun plantSeed(entity: Item, world: World, block: Block, material: Material) {
|
||||||
|
block.type = material
|
||||||
|
world.spawnParticle(Particle.VILLAGER_HAPPY, entity.location, 10)
|
||||||
|
if (entity.itemStack.amount == 1) {
|
||||||
|
entity.remove()
|
||||||
|
} else {
|
||||||
|
entity.itemStack.amount = entity.itemStack.amount - 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
package nl.kallestruik.dtweaks.tweaks.croptweaks
|
||||||
|
|
||||||
|
import nl.kallestruik.dtweaks.tweaks.ITweak
|
||||||
|
import org.bukkit.Material
|
||||||
|
import org.bukkit.Particle
|
||||||
|
import org.bukkit.event.EventHandler
|
||||||
|
import org.bukkit.event.HandlerList
|
||||||
|
import org.bukkit.event.Listener
|
||||||
|
import org.bukkit.event.block.Action
|
||||||
|
import org.bukkit.event.player.PlayerInteractEvent
|
||||||
|
import org.bukkit.inventory.EquipmentSlot
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin
|
||||||
|
|
||||||
|
class SugarcaneBonemealing(
|
||||||
|
private val plugin: JavaPlugin
|
||||||
|
): ITweak, Listener {
|
||||||
|
override fun getIdentifier(): String = "SugarcaneBonemealing"
|
||||||
|
override fun getCategories(): List<String> = listOf("crops", "survival")
|
||||||
|
|
||||||
|
override fun onEnable() {
|
||||||
|
plugin.server.pluginManager.registerEvents(this, plugin)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDisable() {
|
||||||
|
HandlerList.unregisterAll(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
fun onRightClickBlock(event: PlayerInteractEvent) {
|
||||||
|
val player = event.player
|
||||||
|
|
||||||
|
if (event.hand != EquipmentSlot.HAND) return
|
||||||
|
if (event.action != Action.RIGHT_CLICK_BLOCK) return
|
||||||
|
if (event.clickedBlock == null) return
|
||||||
|
if (event.clickedBlock!!.type != Material.SUGAR_CANE) return
|
||||||
|
val itemInHand = player.inventory.itemInMainHand
|
||||||
|
if (itemInHand.type != Material.BONE_MEAL) return
|
||||||
|
|
||||||
|
val world = event.clickedBlock!!.world
|
||||||
|
val origin = event.clickedBlock!!.location
|
||||||
|
|
||||||
|
for (i in 0..3) {
|
||||||
|
val newPos = origin.clone().add(0.0, i.toDouble(), 0.0)
|
||||||
|
val newBlock = world.getBlockAt(newPos)
|
||||||
|
if (newBlock.type != Material.AIR) continue
|
||||||
|
if (newBlock.getRelative(0, -1, 0).type != Material.SUGAR_CANE) continue
|
||||||
|
newBlock.type = Material.SUGAR_CANE
|
||||||
|
world.spawnParticle(Particle.VILLAGER_HAPPY, newPos, 5, 0.5, 0.5, 0.5)
|
||||||
|
itemInHand.amount = itemInHand.amount - 1
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
package nl.kallestruik.dtweaks.tweaks.dispsensertweaks
|
||||||
|
|
||||||
|
import nl.kallestruik.dtweaks.tweaks.ITweak
|
||||||
|
import org.bukkit.Material
|
||||||
|
import org.bukkit.Particle
|
||||||
|
import org.bukkit.Tag
|
||||||
|
import org.bukkit.block.BlockFace
|
||||||
|
import org.bukkit.block.data.type.Dispenser
|
||||||
|
import org.bukkit.event.EventHandler
|
||||||
|
import org.bukkit.event.HandlerList
|
||||||
|
import org.bukkit.event.Listener
|
||||||
|
import org.bukkit.event.block.BlockDispenseEvent
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin
|
||||||
|
|
||||||
|
class DispensersCanPlantSaplings(
|
||||||
|
private val plugin: JavaPlugin
|
||||||
|
): ITweak, Listener {
|
||||||
|
private val treePlantable = setOf(Material.DIRT, Material.COARSE_DIRT, Material.GRASS_BLOCK, Material.PODZOL, Material.MYCELIUM)
|
||||||
|
|
||||||
|
override fun getIdentifier(): String = "DispensersCanPlantSaplings"
|
||||||
|
override fun getCategories(): List<String> = listOf("dispenser", "survival")
|
||||||
|
|
||||||
|
override fun onEnable() {
|
||||||
|
plugin.server.pluginManager.registerEvents(this, plugin)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDisable() {
|
||||||
|
HandlerList.unregisterAll(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
fun onDispenserDispense(event: BlockDispenseEvent) {
|
||||||
|
if (event.block.type != Material.DISPENSER) return
|
||||||
|
if (Tag.SAPLINGS.isTagged(event.item.type)) {
|
||||||
|
val dispenser = event.block.blockData as Dispenser
|
||||||
|
val facing = dispenser.facing
|
||||||
|
val targetBlock = if (facing == BlockFace.UP) {
|
||||||
|
event.block.world.getBlockAt(event.block.location.add(0.0, 2.0, 0.0))
|
||||||
|
} else {
|
||||||
|
event.block.world.getBlockAt(
|
||||||
|
event.block.location.add(
|
||||||
|
facing.modX.toDouble(),
|
||||||
|
facing.modY.toDouble(),
|
||||||
|
facing.modZ.toDouble()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (targetBlock.type == Material.AIR
|
||||||
|
&& treePlantable.contains(
|
||||||
|
event.block.world.getBlockAt(
|
||||||
|
targetBlock.location.add(
|
||||||
|
0.0,
|
||||||
|
-1.0,
|
||||||
|
0.0
|
||||||
|
)
|
||||||
|
).type
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
targetBlock.type = event.item.type
|
||||||
|
event.isCancelled = true
|
||||||
|
val dispenserInventory = (event.block.state as org.bukkit.block.Dispenser).inventory
|
||||||
|
var slot = 0
|
||||||
|
for (`is` in dispenserInventory.contents) {
|
||||||
|
if (`is` != null && `is`.type == event.item.type) break
|
||||||
|
slot++
|
||||||
|
}
|
||||||
|
val newItemStack = dispenserInventory.getItem(slot)
|
||||||
|
newItemStack!!.amount = newItemStack.amount - 1
|
||||||
|
dispenserInventory.setItem(slot, newItemStack)
|
||||||
|
event.block.world.spawnParticle(Particle.VILLAGER_HAPPY, targetBlock.location, 5)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
package nl.kallestruik.dtweaks.tweaks.miscellaneoustweaks
|
||||||
|
|
||||||
|
import nl.kallestruik.dtweaks.tweaks.ITweak
|
||||||
|
import org.bukkit.entity.ArmorStand
|
||||||
|
import org.bukkit.event.EventHandler
|
||||||
|
import org.bukkit.event.HandlerList
|
||||||
|
import org.bukkit.event.Listener
|
||||||
|
import org.bukkit.event.player.PlayerInteractAtEntityEvent
|
||||||
|
import org.bukkit.inventory.EquipmentSlot
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin
|
||||||
|
|
||||||
|
class ArmorStandArmorSwapping(
|
||||||
|
private val plugin: JavaPlugin
|
||||||
|
): ITweak, Listener {
|
||||||
|
override fun getIdentifier(): String = "ArmorStandArmorSwapping"
|
||||||
|
override fun getCategories(): List<String> = listOf("miscellaneous", "survival")
|
||||||
|
|
||||||
|
override fun onEnable() {
|
||||||
|
plugin.server.pluginManager.registerEvents(this, plugin)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDisable() {
|
||||||
|
HandlerList.unregisterAll(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
fun onClickEntity(event: PlayerInteractAtEntityEvent) {
|
||||||
|
if (event.player.isSneaking) {
|
||||||
|
if (event.rightClicked is ArmorStand) {
|
||||||
|
val armorStand = event.rightClicked as ArmorStand
|
||||||
|
val standEquipment = armorStand.equipment
|
||||||
|
val player = event.player
|
||||||
|
val playerEquipment = player.equipment
|
||||||
|
if (standEquipment == null || playerEquipment == null) return
|
||||||
|
|
||||||
|
val playerHelmet = playerEquipment.helmet
|
||||||
|
val playerChestplate = playerEquipment.chestplate
|
||||||
|
val playerLeggings = playerEquipment.leggings
|
||||||
|
val playerBoots = playerEquipment.boots
|
||||||
|
player.inventory.helmet = standEquipment.helmet
|
||||||
|
player.inventory.chestplate = standEquipment.chestplate
|
||||||
|
player.inventory.leggings = standEquipment.leggings
|
||||||
|
player.inventory.boots = standEquipment.boots
|
||||||
|
armorStand.setItem(EquipmentSlot.HEAD, playerHelmet)
|
||||||
|
armorStand.setItem(EquipmentSlot.CHEST, playerChestplate)
|
||||||
|
armorStand.setItem(EquipmentSlot.LEGS, playerLeggings)
|
||||||
|
armorStand.setItem(EquipmentSlot.FEET, playerBoots)
|
||||||
|
event.isCancelled = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,151 @@
|
||||||
|
package nl.kallestruik.dtweaks.tweaks.miscellaneoustweaks
|
||||||
|
|
||||||
|
import com.comphenix.protocol.PacketType
|
||||||
|
import com.comphenix.protocol.ProtocolLibrary
|
||||||
|
import com.comphenix.protocol.events.PacketAdapter
|
||||||
|
import com.comphenix.protocol.events.PacketEvent
|
||||||
|
import com.comphenix.protocol.wrappers.BlockPosition
|
||||||
|
import com.comphenix.protocol.wrappers.EnumWrappers.Hand
|
||||||
|
import nl.kallestruik.dlib.MathHelper
|
||||||
|
import nl.kallestruik.dtweaks.tweaks.ITweak
|
||||||
|
import org.bukkit.Bukkit
|
||||||
|
import org.bukkit.block.BlockFace
|
||||||
|
import org.bukkit.block.data.Bisected
|
||||||
|
import org.bukkit.block.data.BlockData
|
||||||
|
import org.bukkit.block.data.Directional
|
||||||
|
import org.bukkit.block.data.type.Comparator
|
||||||
|
import org.bukkit.block.data.type.Repeater
|
||||||
|
import org.bukkit.block.data.type.Stairs
|
||||||
|
import org.bukkit.block.data.type.TrapDoor
|
||||||
|
import org.bukkit.entity.Player
|
||||||
|
import org.bukkit.event.Listener
|
||||||
|
import org.bukkit.inventory.ItemStack
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin
|
||||||
|
|
||||||
|
class CarpetBlockPlacingProtocol(
|
||||||
|
private val plugin: JavaPlugin,
|
||||||
|
private val mathHelper: MathHelper
|
||||||
|
): ITweak, Listener {
|
||||||
|
private val protocolManager = ProtocolLibrary.getProtocolManager()
|
||||||
|
private var packetListener: PacketListener? = null
|
||||||
|
|
||||||
|
override fun getIdentifier(): String = "CarpetBlockPlacingProtocol"
|
||||||
|
override fun getCategories(): List<String> = listOf("player", "survival")
|
||||||
|
|
||||||
|
override fun onEnable() {
|
||||||
|
this.packetListener = PacketListener(plugin, PacketType.Play.Client.USE_ITEM, mathHelper)
|
||||||
|
protocolManager.addPacketListener(this.packetListener)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDisable() {
|
||||||
|
protocolManager.removePacketListener(this.packetListener)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class PacketListener(
|
||||||
|
plugin: JavaPlugin?,
|
||||||
|
packetType: PacketType?,
|
||||||
|
private val mathHelper: MathHelper
|
||||||
|
): PacketAdapter(plugin, packetType) {
|
||||||
|
override fun onPacketReceiving(event: PacketEvent) {
|
||||||
|
// Make sure the packet is the one we expect.
|
||||||
|
if (event.packetType !== PacketType.Play.Client.USE_ITEM) return
|
||||||
|
|
||||||
|
// Get the hand that the player used.
|
||||||
|
val hand = event.packet.hands.values[0] ?: return
|
||||||
|
|
||||||
|
// Get the MovingObjectPositionBlock and make sure it is not null.
|
||||||
|
val mopd = event.packet.movingBlockPositions.values[0] ?: return
|
||||||
|
val player = event.player
|
||||||
|
|
||||||
|
// Get the item stack that was clicked with.
|
||||||
|
val itemStack =
|
||||||
|
if (hand == Hand.MAIN_HAND) player.inventory.itemInMainHand else player.inventory.itemInOffHand
|
||||||
|
|
||||||
|
// Get the hitPos and BlockPos from the mopd.
|
||||||
|
val hitPos = mopd.posVector
|
||||||
|
val pos = mopd.blockPosition
|
||||||
|
|
||||||
|
// Calculate hitX.
|
||||||
|
val hitX = hitPos.x - pos.x
|
||||||
|
|
||||||
|
// Nothing special so ignore this packet.
|
||||||
|
if (hitX < 2) return
|
||||||
|
val code = (hitX - 2).toInt() / 2
|
||||||
|
val blockData: BlockData = getBlockDataFromCode(code, itemStack, player, pos) ?: return
|
||||||
|
Bukkit.getScheduler().runTask(plugin, Runnable {
|
||||||
|
val blockToChange = player.world.getBlockAt(pos.x, pos.y, pos.z)
|
||||||
|
blockToChange.blockData = blockData
|
||||||
|
|
||||||
|
// Cancel any further processing
|
||||||
|
event.isCancelled = true
|
||||||
|
|
||||||
|
// Take one item from the players inventory.
|
||||||
|
itemStack.amount = itemStack.amount - 1
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getBlockDataFromCode(code: Int, itemStack: ItemStack, player: Player, pos: BlockPosition): BlockData? {
|
||||||
|
val blockData = Bukkit.createBlockData(itemStack.type)
|
||||||
|
if (blockData is Repeater) {
|
||||||
|
val repeater = blockData
|
||||||
|
val delay: Int = mathHelper.clamp(code shr 4, 1, 4)
|
||||||
|
repeater.facing = horizontalBlockFaceFromCode(code and 0xF, player)!!
|
||||||
|
repeater.delay = delay
|
||||||
|
return repeater
|
||||||
|
} else if (blockData is TrapDoor) {
|
||||||
|
val trapDoor = blockData
|
||||||
|
val block = player.world.getBlockAt(pos.x, pos.y, pos.z)
|
||||||
|
trapDoor.facing = blockFaceFromCode(code and 0xF)
|
||||||
|
trapDoor.half = if (code > 0xF) Bisected.Half.TOP else Bisected.Half.BOTTOM
|
||||||
|
trapDoor.isOpen = block.isBlockPowered || block.isBlockIndirectlyPowered
|
||||||
|
return trapDoor
|
||||||
|
} else if (blockData is Comparator) {
|
||||||
|
val comparator = blockData
|
||||||
|
val mode = if (code > 0xF) Comparator.Mode.SUBTRACT else Comparator.Mode.COMPARE
|
||||||
|
comparator.facing = horizontalBlockFaceFromCode(code and 0xF, player)!!
|
||||||
|
comparator.mode = mode
|
||||||
|
return comparator
|
||||||
|
} else if (blockData is Stairs) {
|
||||||
|
val stairs = blockData
|
||||||
|
stairs.facing = blockFaceFromCode(code and 0xF)
|
||||||
|
stairs.half = if (code > 0xF) Bisected.Half.TOP else Bisected.Half.BOTTOM
|
||||||
|
return stairs
|
||||||
|
} else if (blockData is Directional) {
|
||||||
|
val directional = blockData
|
||||||
|
val possibilities = directional.faces
|
||||||
|
|
||||||
|
// Check what type of directional we are dealing with.
|
||||||
|
if (possibilities.contains(BlockFace.UP)) {
|
||||||
|
directional.facing = blockFaceFromCode(code)
|
||||||
|
} else {
|
||||||
|
directional.facing = horizontalBlockFaceFromCode(code, player)!!
|
||||||
|
}
|
||||||
|
return directional
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun blockFaceFromCode(code: Int): BlockFace {
|
||||||
|
return when (code) {
|
||||||
|
0 -> BlockFace.DOWN
|
||||||
|
1 -> BlockFace.UP
|
||||||
|
2 -> BlockFace.NORTH
|
||||||
|
3 -> BlockFace.SOUTH
|
||||||
|
4 -> BlockFace.WEST
|
||||||
|
5 -> BlockFace.EAST
|
||||||
|
else -> BlockFace.SELF
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun blockFaceFromRotation(rotation: Float): BlockFace? {
|
||||||
|
return if (rotation < 45 && rotation >= -45) BlockFace.SOUTH else if (rotation < 135 && rotation >= 45) BlockFace.WEST else if (rotation >= 135 && rotation < -135) BlockFace.NORTH else BlockFace.EAST
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun horizontalBlockFaceFromCode(code: Int, player: Player): BlockFace? {
|
||||||
|
val face = blockFaceFromCode(code)
|
||||||
|
return if (face == BlockFace.UP || face == BlockFace.DOWN) {
|
||||||
|
blockFaceFromRotation(player.location.yaw)
|
||||||
|
} else face
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package nl.kallestruik.dtweaks.tweaks.miscellaneoustweaks
|
||||||
|
|
||||||
|
import nl.kallestruik.dtweaks.managers.FakePlayerManager
|
||||||
|
import nl.kallestruik.dtweaks.tweaks.ITweak
|
||||||
|
|
||||||
|
class FakePlayers(
|
||||||
|
private val fakePlayerManager: FakePlayerManager
|
||||||
|
): ITweak {
|
||||||
|
override fun getIdentifier(): String = "FakePlayers"
|
||||||
|
override fun getCategories(): List<String> = listOf("players")
|
||||||
|
|
||||||
|
override fun onDisable() {
|
||||||
|
fakePlayerManager.killAllFakePlayers()
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,70 @@
|
||||||
|
package nl.kallestruik.dtweaks.tweaks.miscellaneoustweaks
|
||||||
|
|
||||||
|
import nl.kallestruik.dtweaks.managers.PocketDimensionManager
|
||||||
|
import nl.kallestruik.dtweaks.tweaks.ITweak
|
||||||
|
import org.bukkit.entity.Player
|
||||||
|
import org.bukkit.event.EventHandler
|
||||||
|
import org.bukkit.event.HandlerList
|
||||||
|
import org.bukkit.event.Listener
|
||||||
|
import org.bukkit.event.block.BlockBreakEvent
|
||||||
|
import org.bukkit.event.entity.CreatureSpawnEvent
|
||||||
|
import org.bukkit.event.entity.EntityDamageEvent
|
||||||
|
import org.bukkit.event.player.PlayerMoveEvent
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin
|
||||||
|
|
||||||
|
class SpaceTimePockets(
|
||||||
|
private val plugin: JavaPlugin,
|
||||||
|
private val pocketDimensionManager: PocketDimensionManager
|
||||||
|
): ITweak, Listener {
|
||||||
|
override fun getIdentifier(): String = "SpaceTimePockets"
|
||||||
|
override fun getCategories(): List<String> = listOf("miscellaneous", "survival")
|
||||||
|
|
||||||
|
override fun onRegister() {
|
||||||
|
plugin.server.pluginManager.registerEvents(this, plugin)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onUnRegister() {
|
||||||
|
HandlerList.unregisterAll(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
fun onBlockBreak(event: BlockBreakEvent) {
|
||||||
|
if (event.player.world != pocketDimensionManager.pocketDimension) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (event.block.location.chunk == event.player.location.chunk && event.block.y != 0 && event.block.y != 255) return
|
||||||
|
event.isCancelled = true
|
||||||
|
event.player.sendMessage("It seems like a bad idea to break the only thing keeping you from getting lost into the endlessness around you.")
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
fun onMobSpawn(event: CreatureSpawnEvent) {
|
||||||
|
if (pocketDimensionManager.pocketDimension != event.location.world) return
|
||||||
|
event.isCancelled = true
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
fun onPlayerDamage(event: EntityDamageEvent) {
|
||||||
|
if (event.entity !is Player) return
|
||||||
|
if (pocketDimensionManager.pocketDimension != event.entity.world) return
|
||||||
|
event.isCancelled = true
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
fun onPlayerFall(event: PlayerMoveEvent) {
|
||||||
|
if (pocketDimensionManager.pocketDimension != event.from.world
|
||||||
|
|| pocketDimensionManager.pocketDimension != event.to.world
|
||||||
|
) return
|
||||||
|
if (event.from.chunk != event.to.chunk) {
|
||||||
|
event.player.sendMessage("Something pulls you back from the darkness.")
|
||||||
|
event.isCancelled = true
|
||||||
|
}
|
||||||
|
if (event.to.blockY < 0 || event.to.blockY > 256) {
|
||||||
|
event.player.sendMessage("Something pulls you back from the darkness.")
|
||||||
|
val safeLocation = event.player.location
|
||||||
|
safeLocation.y = 128.0
|
||||||
|
event.player.teleport(safeLocation)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
package nl.kallestruik.dtweaks.tweaks.mobtweaks
|
||||||
|
|
||||||
|
import nl.kallestruik.dtweaks.tweaks.ITweak
|
||||||
|
import org.bukkit.entity.Creeper
|
||||||
|
import org.bukkit.entity.EntityType
|
||||||
|
import org.bukkit.event.EventHandler
|
||||||
|
import org.bukkit.event.HandlerList
|
||||||
|
import org.bukkit.event.Listener
|
||||||
|
import org.bukkit.event.entity.EntityExplodeEvent
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin
|
||||||
|
|
||||||
|
class NoCreeperGrief(
|
||||||
|
private val plugin: JavaPlugin
|
||||||
|
): ITweak, Listener {
|
||||||
|
override fun getIdentifier(): String = "NoCreeperGrief"
|
||||||
|
override fun getCategories(): List<String> = listOf("mobs", "survival")
|
||||||
|
|
||||||
|
override fun onEnable() {
|
||||||
|
plugin.server.pluginManager.registerEvents(this, plugin)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDisable() {
|
||||||
|
HandlerList.unregisterAll(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
fun onCreeperExplode(event: EntityExplodeEvent) {
|
||||||
|
if (event.entityType != EntityType.CREEPER) return
|
||||||
|
val creeper = event.entity as Creeper
|
||||||
|
creeper.world.createExplosion(creeper.location, event.yield, false, false)
|
||||||
|
event.isCancelled = true
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package nl.kallestruik.dtweaks.tweaks.mobtweaks
|
||||||
|
|
||||||
|
import nl.kallestruik.dtweaks.tweaks.ITweak
|
||||||
|
import org.bukkit.event.EventHandler
|
||||||
|
import org.bukkit.event.HandlerList
|
||||||
|
import org.bukkit.event.Listener
|
||||||
|
import org.bukkit.event.entity.EntityBreakDoorEvent
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin
|
||||||
|
|
||||||
|
class NoDoorBreaking(
|
||||||
|
private val plugin: JavaPlugin
|
||||||
|
): ITweak, Listener {
|
||||||
|
override fun getIdentifier(): String = "NoDoorBreaking"
|
||||||
|
override fun getCategories(): List<String> = listOf("mobs", "survival")
|
||||||
|
|
||||||
|
override fun onEnable() {
|
||||||
|
plugin.server.pluginManager.registerEvents(this, plugin)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDisable() {
|
||||||
|
HandlerList.unregisterAll(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
fun onDoorBreak(event: EntityBreakDoorEvent) {
|
||||||
|
event.isCancelled = true
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
package nl.kallestruik.dtweaks.tweaks.mobtweaks
|
||||||
|
|
||||||
|
import nl.kallestruik.dtweaks.tweaks.ITweak
|
||||||
|
import org.bukkit.entity.EntityType
|
||||||
|
import org.bukkit.event.EventHandler
|
||||||
|
import org.bukkit.event.HandlerList
|
||||||
|
import org.bukkit.event.Listener
|
||||||
|
import org.bukkit.event.entity.EntityChangeBlockEvent
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin
|
||||||
|
|
||||||
|
class NoEndermanGrief(
|
||||||
|
private val plugin: JavaPlugin
|
||||||
|
): ITweak, Listener {
|
||||||
|
override fun getIdentifier(): String = "NoEndermanGrief"
|
||||||
|
override fun getCategories(): List<String> = listOf("mobs", "survival")
|
||||||
|
|
||||||
|
override fun onEnable() {
|
||||||
|
plugin.server.pluginManager.registerEvents(this, plugin)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDisable() {
|
||||||
|
HandlerList.unregisterAll(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
fun onEndermanPickupBlock(event: EntityChangeBlockEvent) {
|
||||||
|
if (event.entityType != EntityType.ENDERMAN) return
|
||||||
|
event.isCancelled = true
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,112 @@
|
||||||
|
package nl.kallestruik.dtweaks.tweaks.mobtweaks
|
||||||
|
|
||||||
|
import net.minecraft.server.v1_16_R3.Activity
|
||||||
|
import net.minecraft.server.v1_16_R3.EntityVillager
|
||||||
|
import net.minecraft.server.v1_16_R3.GlobalPos
|
||||||
|
import net.minecraft.server.v1_16_R3.MemoryModuleType
|
||||||
|
import nl.kallestruik.dtweaks.tweaks.ITweak
|
||||||
|
import org.bukkit.craftbukkit.v1_16_R3.entity.CraftVillager
|
||||||
|
import org.bukkit.entity.Villager
|
||||||
|
import org.bukkit.event.EventHandler
|
||||||
|
import org.bukkit.event.HandlerList
|
||||||
|
import org.bukkit.event.Listener
|
||||||
|
import org.bukkit.event.player.PlayerInteractEntityEvent
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin
|
||||||
|
import java.util.concurrent.atomic.AtomicReference
|
||||||
|
|
||||||
|
class VillagerInfo(
|
||||||
|
private val plugin: JavaPlugin
|
||||||
|
): ITweak, Listener {
|
||||||
|
override fun getIdentifier(): String = "VillagerInfo"
|
||||||
|
override fun getCategories(): List<String> = listOf("mobs")
|
||||||
|
|
||||||
|
override fun onEnable() {
|
||||||
|
plugin.server.pluginManager.registerEvents(this, plugin)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDisable() {
|
||||||
|
HandlerList.unregisterAll(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
fun onInteractEvent(event: PlayerInteractEntityEvent) {
|
||||||
|
if (!event.player.isSneaking) return
|
||||||
|
val clicked = event.rightClicked as? Villager ?: return
|
||||||
|
val eVillager: EntityVillager = (clicked as CraftVillager).handle
|
||||||
|
val homePos: AtomicReference<GlobalPos?> = AtomicReference(null)
|
||||||
|
eVillager.behaviorController.getMemory(MemoryModuleType.HOME)
|
||||||
|
.ifPresent { newValue -> homePos.set(newValue) }
|
||||||
|
val workPos: AtomicReference<GlobalPos?> = AtomicReference(null)
|
||||||
|
eVillager.behaviorController.getMemory(MemoryModuleType.JOB_SITE).ifPresent { newValue ->
|
||||||
|
workPos.set(
|
||||||
|
newValue
|
||||||
|
)
|
||||||
|
}
|
||||||
|
val meetingPos: AtomicReference<GlobalPos?> = AtomicReference(null)
|
||||||
|
eVillager.behaviorController.getMemory(MemoryModuleType.MEETING_POINT).ifPresent { newValue ->
|
||||||
|
meetingPos.set(
|
||||||
|
newValue
|
||||||
|
)
|
||||||
|
}
|
||||||
|
val lastWork: AtomicReference<Long?> = AtomicReference(null)
|
||||||
|
eVillager.behaviorController.getMemory(MemoryModuleType.LAST_WORKED_AT_POI).ifPresent { newValue ->
|
||||||
|
lastWork.set(
|
||||||
|
newValue
|
||||||
|
)
|
||||||
|
}
|
||||||
|
val lastSleep: AtomicReference<Long?> = AtomicReference(null)
|
||||||
|
eVillager.behaviorController.getMemory(MemoryModuleType.LAST_SLEPT).ifPresent { newValue ->
|
||||||
|
lastSleep.set(
|
||||||
|
newValue
|
||||||
|
)
|
||||||
|
}
|
||||||
|
val seenIGRecently: AtomicReference<Boolean?> = AtomicReference(null)
|
||||||
|
eVillager.behaviorController.getMemory(MemoryModuleType.GOLEM_DETECTED_RECENTLY).ifPresent { newValue ->
|
||||||
|
seenIGRecently.set(
|
||||||
|
newValue
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
val isPanicking: Boolean = eVillager.behaviorController.c(Activity.PANIC)
|
||||||
|
val player = event.player
|
||||||
|
|
||||||
|
player.sendMessage("=====Villager Info=====")
|
||||||
|
player.sendMessage("Type: " + clicked.villagerType)
|
||||||
|
player.sendMessage("Profession: " + clicked.profession)
|
||||||
|
player.sendMessage("Level: " + clicked.villagerLevel + "(" + clicked.villagerExperience + " xp)")
|
||||||
|
player.sendMessage("Panic: $isPanicking")
|
||||||
|
|
||||||
|
if (homePos.get() != null) player.sendMessage(
|
||||||
|
java.lang.String.format(
|
||||||
|
"Home: %s, %s, %s",
|
||||||
|
homePos.get()?.blockPosition?.x,
|
||||||
|
homePos.get()?.blockPosition?.y,
|
||||||
|
homePos.get()?.blockPosition?.z
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if (workPos.get() != null) player.sendMessage(
|
||||||
|
java.lang.String.format(
|
||||||
|
"Work: %s, %s, %s",
|
||||||
|
workPos.get()?.blockPosition?.x,
|
||||||
|
workPos.get()?.blockPosition?.y,
|
||||||
|
workPos.get()?.blockPosition?.z
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if (homePos.get() != null) player.sendMessage(
|
||||||
|
java.lang.String.format(
|
||||||
|
"Meeting point: %s, %s, %s",
|
||||||
|
meetingPos.get()?.blockPosition?.x,
|
||||||
|
meetingPos.get()?.blockPosition?.y,
|
||||||
|
meetingPos.get()?.blockPosition?.z
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if (lastSleep.get() != null)
|
||||||
|
player.sendMessage("Last slept: ${lastSleep.get()}")
|
||||||
|
|
||||||
|
if (seenIGRecently.get() != null)
|
||||||
|
player.sendMessage("Seen iron golem Recently: ${seenIGRecently.get()}")
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
name: DTweaks
|
||||||
|
version: ${version}
|
||||||
|
main: nl.kallestruik.dtweaks.DTweaks
|
||||||
|
api-version: 1.16
|
||||||
|
depend:
|
||||||
|
- "ProtocolLib"
|
||||||
|
- "DLib"
|
||||||
|
commands:
|
||||||
|
toggletrample:
|
||||||
|
description: "Toggles whether you can trample crops."
|
||||||
|
player:
|
||||||
|
description: "Interact with fake players."
|
||||||
|
permission: op
|
||||||
|
mobcaps:
|
||||||
|
description: "Display mobcap information from your current dimension."
|
||||||
|
pocketdim:
|
||||||
|
description: "Interact with pocket dimensions. Testing command."
|
|
@ -0,0 +1,24 @@
|
||||||
|
CraftableNametag: true
|
||||||
|
CraftableSaddle: true
|
||||||
|
AlternativeDispenserRecipe: true
|
||||||
|
DispensersCanPlantSaplings: true
|
||||||
|
CraftableShulkerShell: true
|
||||||
|
IceDecompression: true
|
||||||
|
LogsToChests: true
|
||||||
|
CraftableSponge: true
|
||||||
|
PlayersCantTrampleCrops: true
|
||||||
|
WoolToString: true
|
||||||
|
LilypadBonemealing: true
|
||||||
|
SeedDropPlanting: true
|
||||||
|
MobsCantTrampleCrops: true
|
||||||
|
CraftableDragonsBreath: true
|
||||||
|
ArmorSwapping: true
|
||||||
|
HoesHarvestArea: true
|
||||||
|
FakePlayers: true
|
||||||
|
CarpetBlockPlacingProtocol: true
|
||||||
|
NoDoorBreaking: true
|
||||||
|
NoCreeperGrief: true
|
||||||
|
NoEndermanGrief: true
|
||||||
|
SugarcaneBonemealing: true
|
||||||
|
SpaceTimePockets: true
|
||||||
|
VillagerInfo: true
|
Loading…
Reference in New Issue