diff --git a/README.md b/README.md deleted file mode 100644 index bd7aaad..0000000 --- a/README.md +++ /dev/null @@ -1,3 +0,0 @@ -MCBBS发布帖: https://www.mcbbs.net/thread-1342178-1-1.html - -MineDown: https://github.com/Phoenix616/MineDown diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..cc05680 --- /dev/null +++ b/build.gradle @@ -0,0 +1,96 @@ +plugins { + id 'java' + id 'com.github.johnrengelman.shadow' version '7.1.2' +} + + +group = 'net.momirealms' +version = '1.5.0-SNAPSHOT' + +repositories { + mavenCentral() + maven { + name = 'papermc-repo' + url = 'https://papermc.io/repo/repository/maven-public/' + } + maven { + name = 'sonatype' + url = 'https://oss.sonatype.org/content/groups/public/' + } + maven { + name = "sonatype-oss-snapshots1" + url = "https://s01.oss.sonatype.org/content/repositories/snapshots/" + } + maven { + name = "dmulloy2-repo" + url = "https://repo.dmulloy2.net/repository/public/" + } + maven { + name = "clip-repo" + url = 'https://repo.extendedclip.com/content/repositories/placeholderapi/' + } + maven { + name = "NBT-API" + url = "https://repo.codemc.org/repository/maven-public/" + } + maven { + name = "sk89q-repo" + url = "https://maven.enginehub.org/repo/" + } + maven { + name = "Lumine Releases" + url = "https://mvn.lumine.io/repository/maven-public" + } + maven { + name = "jitpack-repo" + url = "https://jitpack.io" + } +} + +dependencies { + compileOnly 'com.destroystokyo.paper:paper-api:1.16.5-R0.1-SNAPSHOT' + compileOnly group: "com.comphenix.protocol", name: "ProtocolLib", version: "4.8.0" + compileOnly 'me.clip:placeholderapi:2.11.1' + compileOnly 'com.sk89q.worldguard:worldguard-bukkit:7.0.7' + compileOnly 'io.lumine:Mythic-Dist:5.0.3-SNAPSHOT' + compileOnly 'com.github.LoneDev6:api-itemsadder:3.2.0c-beta6' + compileOnly fileTree(dir:'libs',includes:['*jar']) + implementation("net.kyori:adventure-api:4.11.0") + implementation("net.kyori:adventure-platform-bukkit:4.1.1") + implementation("net.kyori:adventure-text-minimessage:4.11.0") + implementation 'de.tr7zw:item-nbt-api:2.10.0' +} + +def targetJavaVersion = 16 +java { + def javaVersion = JavaVersion.toVersion(targetJavaVersion) + sourceCompatibility = javaVersion + targetCompatibility = javaVersion + if (JavaVersion.current() < javaVersion) { + toolchain.languageVersion = JavaLanguageVersion.of(targetJavaVersion) + } +} + +tasks.withType(JavaCompile).configureEach { + if (targetJavaVersion >= 10 || JavaVersion.current().isJava10Compatible()) { + options.release = targetJavaVersion + } +} + +processResources { + def props = [version: version] + inputs.properties props + filteringCharset 'UTF-8' + filesMatching('plugin.yml') { + expand props + } +} + +tasks.withType(JavaCompile) { + options.encoding = "UTF-8" +} + +shadowJar { + relocate 'net.kyori', 'libs.kyori' + relocate 'de.tr7zw', 'libs.tr7zw' +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..e69de29 diff --git a/gradlew b/gradlew new file mode 100644 index 0000000..3da45c1 --- /dev/null +++ b/gradlew @@ -0,0 +1,234 @@ +#!/bin/sh + +# +# Copyright ? 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions ?$var?, ?${var}?, ?${var:-default}?, ?${var+SET}?, +# ?${var#prefix}?, ?${var%suffix}?, and ?$( cmd )?; +# * compound commands having a testable exit status, especially ?case?; +# * various built-in commands including ?command?, ?set?, and ?ulimit?. +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit + +APP_NAME="Gradle" +APP_BASE_NAME=${0##*/} + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..107acd3 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/pom.xml b/pom.xml deleted file mode 100644 index ae6a5de..0000000 --- a/pom.xml +++ /dev/null @@ -1,96 +0,0 @@ - - - 4.0.0 - - net.momirealms - CustomCrops - 1.0-SNAPSHOT - jar - - CustomCrops - - - 16 - UTF-8 - - - - - sk89q-repo - https://maven.enginehub.org/repo/ - - - dmulloy2-repo - https://repo.dmulloy2.net/repository/public/ - - - placeholderapi - https://repo.extendedclip.com/content/repositories/placeholderapi/ - - - sonatype-oss-snapshots1 - https://s01.oss.sonatype.org/content/repositories/snapshots/ - - - papermc-repo - https://papermc.io/repo/repository/maven-public/ - - - jitpack-repo - https://jitpack.io - - - sonatype - https://oss.sonatype.org/content/groups/public/ - - - - - - me.clip - placeholderapi - 2.11.1 - provided - - - io.papermc.paper - paper-api - 1.17.1-R0.1-SNAPSHOT - provided - - - com.github.LoneDev6 - api-itemsadder - 3.1.6 - provided - - - com.sk89q.worldguard - worldguard-bukkit - 7.0.7 - provided - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.8.1 - - ${java.version} - ${java.version} - - - - - - src/main/resources - true - - - - diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..d4b6e37 --- /dev/null +++ b/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'CustomCrops' diff --git a/src/main/java/net/momirealms/customcrops/ConfigReader.java b/src/main/java/net/momirealms/customcrops/ConfigReader.java new file mode 100644 index 0000000..4402765 --- /dev/null +++ b/src/main/java/net/momirealms/customcrops/ConfigReader.java @@ -0,0 +1,432 @@ +package net.momirealms.customcrops; + +import net.momirealms.customcrops.fertilizer.Fertilizer; +import net.momirealms.customcrops.fertilizer.QualityCrop; +import net.momirealms.customcrops.fertilizer.RetainingSoil; +import net.momirealms.customcrops.fertilizer.SpeedGrow; +import net.momirealms.customcrops.integrations.*; +import net.momirealms.customcrops.requirements.Biome; +import net.momirealms.customcrops.requirements.Permission; +import net.momirealms.customcrops.requirements.Requirement; +import net.momirealms.customcrops.requirements.YPos; +import net.momirealms.customcrops.utils.*; +import org.apache.commons.lang.StringUtils; +import org.bukkit.Bukkit; +import org.bukkit.World; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; + +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Set; + +public class ConfigReader { + + public static HashMap CROPS = new HashMap<>(); + public static HashMap FERTILIZERS = new HashMap<>(); + public static HashMap CANS = new HashMap<>(); + public static HashMap SPRINKLERS = new HashMap<>(); + + private static YamlConfiguration getConfig(String configName) { + File file = new File(CustomCrops.instance.getDataFolder(), configName); + if (!file.exists()) { + CustomCrops.instance.saveResource(configName, false); + } + return YamlConfiguration.loadConfiguration(file); + } + + public static void ReloadConfig(){ + Config.loadConfig(); + Message.loadMessage(); + Basic.loadBasic(); + Season.loadSeason(); + cropLoad(); + fertilizerLoad(); + } + + public static class Config{ + + public static List worlds; + public static List worldNames; + public static List cropGrowTimeList; + public static List integration; + public static boolean asyncCheck; +// public static boolean useBoneMeal; +// public static boolean consumeWater; +// public static double boneMealChance; +// public static String success; +// public static String failure; + public static boolean enableLimit; + public static int cropLimit; + public static int sprinklerLimit; + public static int yMin; + public static int yMax; + public static int sprinklerRefill; + public static boolean logTime; + public static boolean onlyLoadedGrow; + public static boolean quality; + public static double quality_1; + public static double quality_2; + + public static void loadConfig(){ + + //存读基本配置文件 + CustomCrops.instance.saveDefaultConfig(); + CustomCrops.instance.reloadConfig(); + FileConfiguration config = CustomCrops.instance.getConfig(); + + //农作物生长时间点 + cropGrowTimeList = config.getLongList("config.grow-time"); + cropGrowTimeList.forEach(time -> { + if(time < 0 || time > 23999){ + AdventureManager.consoleMessage("[CustomCrops] 农作物生长时间点必须位于0-23999之间"); + cropGrowTimeList.remove(time); + } + }); + + //异步读取时间 + asyncCheck = config.getBoolean("config.async-time-check",false); + logTime = config.getBoolean("config.log-time-consume",false); + onlyLoadedGrow = config.getBoolean("config.only-grow-in-loaded-chunks",true); + + //骨粉设置(已废弃) +// useBoneMeal = config.getBoolean("config.bone-meal.enable",false); +// if (useBoneMeal){ +// boneMealChance = config.getDouble("config.bone-meal.chance"); +// consumeWater = config.getBoolean("config.bone-meal.consume-water"); +// success = config.getString("config.bone-meal.particle.success"); +// failure = config.getString("config.bone-meal.particle.failure"); +// } + + //数量与高度限制 + enableLimit = config.getBoolean("config.limit.enable",true); + if (enableLimit){ + cropLimit = config.getInt("config.limit.crop",64); + sprinklerLimit = config.getInt("config.limit.sprinkler",16); + } + if (Bukkit.getServer().getClass().getPackage().getName().contains("16") || Bukkit.getServer().getClass().getPackage().getName().contains("17")){ + yMin = 0; + yMax = 256; + } + if (Bukkit.getServer().getClass().getPackage().getName().contains("18") || Bukkit.getServer().getClass().getPackage().getName().contains("19")){ + yMin = -64; + yMax = 320; + } + + //农作物品质处理 + quality = config.getBoolean("config.quality.enable"); + if (quality){ + String[] split = StringUtils.split(config.getString("config.quality.default-ratio"), "/"); + double[] ratios = new double[3]; + ratios[0] = Double.parseDouble(split[0]); + ratios[1] = Double.parseDouble(split[1]); + ratios[2] = Double.parseDouble(split[2]); + double total = ratios[0] + ratios[1] + ratios[2]; + quality_1 = ratios[0]/total; + quality_2 = 1 - ratios[1]/total; + } + + sprinklerRefill = config.getInt("config.sprinkler-refill",2); + + //农作物生长的白名单世界 + worlds = new ArrayList<>(); + worldNames = config.getStringList("config.whitelist-worlds"); + worldNames.forEach(worldName -> { + World world = Bukkit.getWorld(worldName); + if (world == null){ + worldNames.remove(worldName); + AdventureManager.consoleMessage("[CustomCrops] 世界" + worldName + "" + "不存在"); + }else { + worlds.add(world); + } + }); + + //处理插件兼容性 + integration = new ArrayList<>(); + if(config.getBoolean("config.integration.Residence",false)){ + if(Bukkit.getPluginManager().getPlugin("Residence") == null){ + CustomCrops.instance.getLogger().warning("未检测到插件 Residence!"); + }else { + integration.add(new Residence()); + AdventureManager.consoleMessage("[CustomCrops] 检测到 Residence 已启用保护!"); + } + } + if(config.getBoolean("config.integration.Kingdoms",false)){ + if(Bukkit.getPluginManager().getPlugin("Kingdoms") == null){ + CustomCrops.instance.getLogger().warning("未检测到插件 Kingdoms!"); + }else { + integration.add(new KingdomsX()); + AdventureManager.consoleMessage("[CustomCrops] 检测到 KingdomsX 已启用保护!"); + } + } + if(config.getBoolean("config.integration.WorldGuard",false)){ + if(Bukkit.getPluginManager().getPlugin("WorldGuard") == null){ + CustomCrops.instance.getLogger().warning("未检测到插件 WorldGuard!"); + }else { + integration.add(new WorldGuard()); + AdventureManager.consoleMessage("[CustomCrops] 检测到 WorldGuard 已启用保护!"); + } + } + if(config.getBoolean("config.integration.GriefDefender",false)){ + if(Bukkit.getPluginManager().getPlugin("GriefDefender") == null){ + CustomCrops.instance.getLogger().warning("未检测到插件 GriefDefender!"); + }else { + integration.add(new GriefDefender()); + AdventureManager.consoleMessage("[CustomCrops] 检测到 GriefDefender 已启用保护!"); + } + } + } + } + + public static class Basic{ + + public static String pot; + public static String watered_pot; + public static String glass; + public static String sprinkler_1; + public static String sprinkler_2; + public static String sprinkler_1i; + public static String sprinkler_2i; + public static String dead; + public static String soilDetector; + + public static void loadBasic(){ + YamlConfiguration config = getConfig("basic.yml"); + pot = config.getString("basic.pot"); + watered_pot = config.getString("basic.watered-pot"); + glass = config.getString("basic.greenhouse-glass"); + sprinkler_1 = config.getString("basic.sprinkler-1"); + sprinkler_2 = config.getString("basic.sprinkler-2"); + sprinkler_1i = config.getString("basic.sprinkler-1-item"); + sprinkler_2i = config.getString("basic.sprinkler-2-item"); + dead = config.getString("basic.dead-crop"); + soilDetector = StringUtils.split(config.getString("basic.soil-detector"),":")[1]; + + CANS.clear(); + if (config.contains("water-can")){ + config.getConfigurationSection("water-can").getKeys(false).forEach(key -> { + if (key.equals(StringUtils.split(config.getString("water-can." + key + ".item"),":")[1])){ + int width = config.getInt("water-can." + key + ".width"); + if (width % 2 == 0){ + AdventureManager.consoleMessage("[CustomCrops] 水壶 " + key + " 的浇灌宽度必须为奇数!"); + return; + } + WateringCan wateringCan = new WateringCan(config.getInt("water-can." + key + ".max"), width, config.getInt("water-can." + key + ".length")); + CANS.put(key, wateringCan); + }else { + AdventureManager.consoleMessage("[CustomCrops] 水壶 " + key + " 与ItemsAdder物品ID不一致"); + } + }); + } + + SPRINKLERS.clear(); + if (config.contains("sprinkler")){ + config.getConfigurationSection("sprinkler").getKeys(false).forEach(key -> { + if (key.equals(StringUtils.split(config.getString("sprinkler." + key + ".3Ditem"),":")[1])){ + Sprinkler sprinklerData = new Sprinkler(config.getInt("sprinkler." + key + ".range"), config.getInt("sprinkler." + key + ".max-water")); + sprinklerData.setNamespacedID_2(config.getString("sprinkler." + key + ".3Ditem")); + String twoD = config.getString("sprinkler." + key + ".2Ditem"); + sprinklerData.setNamespacedID_1(twoD); + SPRINKLERS.put(key, sprinklerData); + SPRINKLERS.put(StringUtils.split(twoD,":")[1], sprinklerData); + }else { + AdventureManager.consoleMessage("[CustomCrops] 洒水器 " + key + " 与ItemsAdder物品ID不一致"); + } + }); + } + } + } + + public static class Season{ + + public static boolean enable; + public static boolean greenhouse; + public static boolean seasonChange; + public static int range; + public static int duration; + + public static void loadSeason(){ + YamlConfiguration config = getConfig("season.yml"); + + enable = config.getBoolean("season.enable",false); + if (enable){ + greenhouse = config.getBoolean("season.greenhouse.enable",false); + if (greenhouse) { + range = config.getInt("season.greenhouse.range",7); + } + seasonChange = config.getBoolean("season.auto-season-change.enable",false); + if (seasonChange) { + duration = config.getInt("season.auto-season-change.duration",28); + } + } + } + } + + public static class Message{ + + public static String prefix; + public static String reload; + public static String lackArgs; + public static String noPerm; + public static String spring; + public static String summer; + public static String autumn; + public static String winter; + public static String sprinkler_limit; + public static String crop_limit; + public static String not_configed; + public static String badY; + public static String badBiome; + public static String badWorld; + public static String badPerm; + public static String badSeason; + public static String forceGrow; + public static String forceWater; + public static String backUp; + public static String setSeason; + public static String wrongArgs; + public static String forceSave; + public static boolean hasCropInfo; + public static boolean hasSprinklerInfo; + public static int cropTime; + public static int sprinklerTime; + public static String cropText; + public static String sprinklerLeft; + public static String sprinklerFull; + public static String sprinklerEmpty; + public static String sprinklerRight; + public static double cropOffset; + public static double sprinklerOffset; + + public static void loadMessage(){ + YamlConfiguration config = getConfig("messages.yml"); + prefix = config.getString("messages.prefix"); + reload = config.getString("messages.reload"); + lackArgs = config.getString("messages.lack-args"); + noPerm = config.getString("messages.no-perm"); + spring = config.getString("messages.spring"); + summer = config.getString("messages.summer"); + autumn = config.getString("messages.autumn"); + winter = config.getString("messages.winter"); + sprinkler_limit = config.getString("messages.sprinkler-limit"); + crop_limit = config.getString("messages.crop-limit"); + not_configed = config.getString("messages.not-configed"); + badY = config.getString("messages.bad-Y"); + badBiome = config.getString("messages.bad-biome"); + badWorld = config.getString("messages.bad-world"); + badPerm = config.getString("messages.bad-perm"); + badSeason = config.getString("messages.bad-season"); + forceGrow = config.getString("messages.force-grow"); + forceWater = config.getString("messages.force-water"); + backUp = config.getString("messages.back-up"); + setSeason = config.getString("messages.set-season"); + wrongArgs = config.getString("messages.wrong-args"); + forceSave = config.getString("messages.force-save"); + + hasCropInfo = config.getBoolean("hologram.grow-info.enable"); + if (hasCropInfo){ + cropTime = config.getInt("hologram.grow-info.duration"); + cropText = config.getString("hologram.grow-info.text"); + cropOffset = config.getDouble("hologram.grow-info.y-offset"); + } + hasSprinklerInfo = config.getBoolean("hologram.sprinkler-info.enable"); + if (hasSprinklerInfo){ + sprinklerTime = config.getInt("hologram.sprinkler-info.duration"); + sprinklerLeft = config.getString("hologram.sprinkler-info.left"); + sprinklerFull = config.getString("hologram.sprinkler-info.full"); + sprinklerEmpty = config.getString("hologram.sprinkler-info.empty"); + sprinklerRight = config.getString("hologram.sprinkler-info.right"); + sprinklerOffset = config.getDouble("hologram.sprinkler-info.y-offset"); + } + } + } + + public static void cropLoad(){ + CROPS.clear(); + YamlConfiguration config = getConfig("crops.yml"); + Set keys = config.getConfigurationSection("crops").getKeys(false); + keys.forEach(key -> { + CropInstance cropInstance; + if (config.contains("crops." + key + ".amount")){ + String[] split = StringUtils.split(config.getString("crops." + key + ".amount"),"~"); + cropInstance = new CropInstance(Integer.parseInt(split[0]),Integer.parseInt(split[1])); + }else { + AdventureManager.consoleMessage("[CustomCrops] 未设置农作物 " + key +" 的产物数量!"); + return; + } + if (config.contains("crops." + key + ".gigantic")){ + cropInstance.setGiant(config.getString("crops." + key + ".gigantic.block")); + cropInstance.setGiantChance(config.getDouble("crops." + key + ".gigantic.chance")); + } + if (Season.enable && config.contains("crops." + key + ".season")){ + cropInstance.setSeasons(config.getStringList("crops." + key + ".season")); + } + if (config.contains("crops." + key + ".return")){ + cropInstance.setReturnStage(config.getString("crops." + key + ".return")); + } + if (config.contains("crops." + key + ".requirements")){ + List requirements = new ArrayList<>(); + config.getConfigurationSection("crops." + key + ".requirements").getValues(false).forEach((requirement, value) -> { + switch (requirement){ + case "world" -> requirements.add(new net.momirealms.customcrops.requirements.World((List) value)); + case "yPos" -> requirements.add(new YPos((List) value)); + case "biome" -> requirements.add(new Biome((List) value)); + case "permission" -> requirements.add(new Permission((String) value)); + } + }); + cropInstance.setRequirements(requirements); + } + if (Config.quality){ + cropInstance.setQuality_1(config.getString("crops." + key + ".quality.1")); + cropInstance.setQuality_2(config.getString("crops." + key + ".quality.2")); + cropInstance.setQuality_3(config.getString("crops." + key + ".quality.3")); + } + CROPS.put(key, cropInstance); + }); + } + + public static void fertilizerLoad(){ + FERTILIZERS.clear(); + YamlConfiguration config = getConfig("fertilizer.yml"); + if (config.contains("加速肥料")){ + config.getConfigurationSection("加速肥料").getKeys(false).forEach(key -> { + if (StringUtils.split(config.getString("加速肥料." + key + ".item"), ":")[1].equals(key)){ + SpeedGrow speedGrow = new SpeedGrow(key, config.getInt("加速肥料." + key + ".times"), config.getDouble("加速肥料." + key + ".chance"), config.getBoolean("加速肥料." + key + ".before-plant")); + speedGrow.setName(config.getString("加速肥料." + key + ".name")); + FERTILIZERS.put(key, speedGrow); + }else { + AdventureManager.consoleMessage("[CustomCrops] 肥料 " + key + " 与ItemsAdder物品ID不一致"); + } + }); + } + if (config.contains("保湿肥料")){ + config.getConfigurationSection("保湿肥料").getKeys(false).forEach(key -> { + if (StringUtils.split(config.getString("保湿肥料." + key + ".item"), ":")[1].equals(key)){ + RetainingSoil retainingSoil = new RetainingSoil(key, config.getInt("保湿肥料." + key + ".times"), config.getDouble("保湿肥料." + key + ".chance"), config.getBoolean("保湿肥料." + key + ".before-plant")); + retainingSoil.setName(config.getString("保湿肥料." + key + ".name")); + FERTILIZERS.put(key, retainingSoil); + }else { + AdventureManager.consoleMessage("[CustomCrops] 肥料 " + key + " 与ItemsAdder物品ID不一致"); + } + }); + } + if (config.contains("品质肥料")){ + config.getConfigurationSection("品质肥料").getKeys(false).forEach(key -> { + if (StringUtils.split(config.getString("品质肥料." + key + ".item"), ":")[1].equals(key)){ + String[] split = StringUtils.split(config.getString("品质肥料." + key + ".chance"), "/"); + int[] weight = new int[3]; + weight[0] = Integer.parseInt(split[0]); + weight[1] = Integer.parseInt(split[1]); + weight[2] = Integer.parseInt(split[2]); + QualityCrop qualityCrop = new QualityCrop(key, config.getInt("品质肥料." + key + ".times"), weight, config.getBoolean("品质肥料." + key + ".before-plant")); + qualityCrop.setName(config.getString("品质肥料." + key + ".name")); + FERTILIZERS.put(key, qualityCrop); + }else { + AdventureManager.consoleMessage("[CustomCrops] 肥料 " + key + " 与ItemsAdder物品ID不一致"); + } + }); + } + } +} diff --git a/src/main/java/net/momirealms/customcrops/CustomCrops.java b/src/main/java/net/momirealms/customcrops/CustomCrops.java index fa72830..155db6c 100644 --- a/src/main/java/net/momirealms/customcrops/CustomCrops.java +++ b/src/main/java/net/momirealms/customcrops/CustomCrops.java @@ -1,89 +1,120 @@ package net.momirealms.customcrops; -import net.momirealms.customcrops.commands.CommandHandler; -import net.momirealms.customcrops.commands.CommandTabComplete; +import net.kyori.adventure.platform.bukkit.BukkitAudiences; +import net.momirealms.customcrops.commands.Executor; +import net.momirealms.customcrops.commands.Completer; import net.momirealms.customcrops.datamanager.*; -import net.momirealms.customcrops.listener.BreakCrops; +import net.momirealms.customcrops.listener.BreakBlock; +import net.momirealms.customcrops.listener.InteractEntity; +import net.momirealms.customcrops.listener.ItemSpawn; +import net.momirealms.customcrops.listener.RightClick; import net.momirealms.customcrops.timer.CropTimer; -import net.momirealms.customcrops.listener.BreakCustomBlock; -import net.momirealms.customcrops.listener.RightClickBlock; -import net.momirealms.customcrops.listener.RightClickCustomBlock; +import net.momirealms.customcrops.timer.CropTimerAsync; +import net.momirealms.customcrops.utils.AdventureManager; +import net.momirealms.customcrops.utils.BackUp; +import net.momirealms.customcrops.utils.HoloUtil; import net.momirealms.customcrops.utils.Placeholders; import org.bukkit.Bukkit; import org.bukkit.plugin.java.JavaPlugin; -import java.io.File; -import java.io.IOException; import java.util.Objects; public final class CustomCrops extends JavaPlugin { public static JavaPlugin instance; - public static CropTimer timer; + public static BukkitAudiences adventure; + private CropTimer cropTimer; + private CropTimerAsync cropTimerAsync; + private CropManager cropManager; + private SprinklerManager sprinklerManager; + private SeasonManager seasonManager; + private PotManager potManager; @Override public void onEnable() { + instance = this; + adventure = BukkitAudiences.create(this); + + AdventureManager.consoleMessage("[CustomCrops] Running on " + Bukkit.getVersion()); //加载配置文件 - ConfigManager.Config.ReloadConfig(); + ConfigReader.ReloadConfig(); + + //PAPI + if(Bukkit.getPluginManager().getPlugin("PlaceHolderAPI") != null){ + new Placeholders().register(); + AdventureManager.consoleMessage("[CustomCrops] 检测到 PlaceHolderAPI 已启用变量!"); + } //指令注册 - Objects.requireNonNull(Bukkit.getPluginCommand("customcrops")).setExecutor(new CommandHandler()); - Objects.requireNonNull(Bukkit.getPluginCommand("customcrops")).setTabCompleter(new CommandTabComplete()); - Bukkit.getPluginManager().registerEvents(new RightClickCustomBlock(),this); - Bukkit.getPluginManager().registerEvents(new BreakCustomBlock(),this); - Bukkit.getPluginManager().registerEvents(new RightClickBlock(),this); - Bukkit.getPluginManager().registerEvents(new BreakCrops(),this); + Objects.requireNonNull(Bukkit.getPluginCommand("customcrops")).setExecutor(new Executor(this)); + Objects.requireNonNull(Bukkit.getPluginCommand("customcrops")).setTabCompleter(new Completer()); - //开始计时任务 - CustomCrops.timer = new CropTimer(); + //注册事件 + Bukkit.getPluginManager().registerEvents(new ItemSpawn(), this); + Bukkit.getPluginManager().registerEvents(new RightClick(), this); + Bukkit.getPluginManager().registerEvents(new BreakBlock(), this); + Bukkit.getPluginManager().registerEvents(new InteractEntity(this), this); - //新建data文件 - File crop_file = new File(CustomCrops.instance.getDataFolder(), "crop-data.yml"); - File sprinkler_file = new File(CustomCrops.instance.getDataFolder(), "sprinkler-data.yml"); - if(!crop_file.exists()){ - try { - crop_file.createNewFile(); - } catch (IOException e) { - e.printStackTrace(); - MessageManager.consoleMessage("&c[CustomCrops] 农作物数据文件生成失败!",Bukkit.getConsoleSender()); - } - } - if(!sprinkler_file.exists()){ - try { - sprinkler_file.createNewFile(); - } catch (IOException e) { - e.printStackTrace(); - MessageManager.consoleMessage("&c[CustomCrops] 洒水器数据文件生成失败!",Bukkit.getConsoleSender()); - } + //开始计时器 + if(ConfigReader.Config.asyncCheck){ + this.cropTimerAsync = new CropTimerAsync(this); + }else { + this.cropTimer = new CropTimer(this); } - //载入data数据 - CropManager.loadData(); - SprinklerManager.loadData(); - - //检测papi依赖 - if(Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null){ - new Placeholders(this).register(); - MessageManager.consoleMessage("&#ccfbff-#ef96c5&[CustomCrops] &7检测到 &aPlaceHolderAPI &7已启用季节变量!",Bukkit.getConsoleSender()); + //载入数据 + if (ConfigReader.Season.enable){ + this.seasonManager = new SeasonManager(this); + this.seasonManager.loadData(); } - MessageManager.consoleMessage("&#ccfbff-#ef96c5&[CustomCrops] &7自定义农作物插件已启用!作者:小默米 QQ:3266959688",Bukkit.getConsoleSender()); + this.cropManager = new CropManager(this); + this.cropManager.loadData(); + this.sprinklerManager = new SprinklerManager(this); + this.sprinklerManager.loadData(); + this.potManager = new PotManager(this); + this.potManager.loadData(); + + //启动完成 + AdventureManager.consoleMessage("[CustomCrops] 插件已加载!作者:小默米 QQ:3266959688"); } @Override public void onDisable() { - //关闭定时任务 - if (CustomCrops.timer != null) { - CropTimer.stopTimer(CustomCrops.timer.getTaskID()); + + //保存数据 + this.cropManager.saveData(); + this.sprinklerManager.saveData(); + this.potManager.saveData(); + if (ConfigReader.Season.enable && !ConfigReader.Season.seasonChange){ + this.seasonManager.saveData(); } - //保存缓存中的数据 - CropManager.saveData(); - SprinklerManager.saveData(); + //清除悬浮展示实体 + HoloUtil.cache.keySet().forEach(player -> { + HoloUtil.cache.get(player).remove(); + }); - //备份 + //关闭计时器 + if (cropTimer != null) { + this.cropTimer.stopTimer(cropTimer.getTaskID()); + } + if (cropTimerAsync != null){ + this.cropTimerAsync.stopTimer(cropTimerAsync.getTaskID()); + } + + //备份数据 + AdventureManager.consoleMessage("[CustomCrops] 插件数据自动备份中..."); BackUp.backUpData(); - MessageManager.consoleMessage(("&#ccfbff-#ef96c5&[CustomCrops] &7自定义农作物插件已卸载!作者:小默米 QQ:3266959688"),Bukkit.getConsoleSender()); + AdventureManager.consoleMessage("[CustomCrops] 备份已完成!"); + + //卸载完成 + AdventureManager.consoleMessage("[CustomCrops] 插件已卸载!作者:小默米 QQ:3266959688"); } + + public CropManager getCropManager() { return this.cropManager; } + public SprinklerManager getSprinklerManager() { return sprinklerManager; } + public SeasonManager getSeasonManager() { return seasonManager; } + public PotManager getPotManager() { return potManager; } } diff --git a/src/main/java/net/momirealms/customcrops/commands/CommandHandler.java b/src/main/java/net/momirealms/customcrops/commands/CommandHandler.java deleted file mode 100644 index b22c8db..0000000 --- a/src/main/java/net/momirealms/customcrops/commands/CommandHandler.java +++ /dev/null @@ -1,123 +0,0 @@ -package net.momirealms.customcrops.commands; - -import net.momirealms.customcrops.datamanager.ConfigManager; -import net.momirealms.customcrops.CustomCrops; -import net.momirealms.customcrops.datamanager.MessageManager; -import net.momirealms.customcrops.datamanager.BackUp; -import net.momirealms.customcrops.datamanager.CropManager; -import net.momirealms.customcrops.datamanager.NextSeason; -import net.momirealms.customcrops.datamanager.SprinklerManager; -import org.bukkit.Bukkit; -import org.bukkit.command.Command; -import org.bukkit.command.CommandExecutor; -import org.bukkit.command.CommandSender; -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.entity.Player; - -import javax.annotation.ParametersAreNonnullByDefault; - -public class CommandHandler implements CommandExecutor { - - @Override - @ParametersAreNonnullByDefault - public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { - if(args.length<1) return true; - //重载插件 - if(args[0].equalsIgnoreCase("reload")){ - - ConfigManager.Config.ReloadConfig(); - - if(sender instanceof Player){ - MessageManager.playerMessage(ConfigManager.Config.prefix + ConfigManager.Config.reload, (Player) sender); - }else { - MessageManager.consoleMessage(ConfigManager.Config.prefix + ConfigManager.Config.reload, Bukkit.getConsoleSender()); - } - return true; - } - //设置季节 - if(args[0].equalsIgnoreCase("setseason")){ - if(args.length<2) return true; - if(ConfigManager.Config.season){ - - FileConfiguration config = CustomCrops.instance.getConfig(); - config.set("current-season", args[1]); - CustomCrops.instance.saveConfig(); - ConfigManager.Config.current = args[1]; - - if(sender instanceof Player){ - MessageManager.playerMessage(ConfigManager.Config.prefix + ConfigManager.Config.season_set.replace("{Season}",args[1]) - .replace("spring", ConfigManager.Config.spring) - .replace("summer", ConfigManager.Config.summer) - .replace("autumn", ConfigManager.Config.autumn) - .replace("winter", ConfigManager.Config.winter), (Player) sender); - }else { - MessageManager.consoleMessage(config.getString("messages.prefix") + ConfigManager.Config.season_set.replace("{Season}",args[1]) - .replace("spring", ConfigManager.Config.spring) - .replace("summer", ConfigManager.Config.summer) - .replace("autumn", ConfigManager.Config.autumn) - .replace("winter", ConfigManager.Config.winter), Bukkit.getConsoleSender()); - } - - }else{ - if(sender instanceof Player){ - MessageManager.playerMessage(ConfigManager.Config.prefix + ConfigManager.Config.season_disabled, (Player) sender); - }else { - MessageManager.consoleMessage(ConfigManager.Config.prefix + ConfigManager.Config.season_disabled, Bukkit.getConsoleSender()); - } - } - return true; - } - //强制保存 - if(args[0].equalsIgnoreCase("forcesave")){ - CropManager.saveData(); - SprinklerManager.saveData(); - if(sender instanceof Player){ - MessageManager.playerMessage(ConfigManager.Config.prefix + ConfigManager.Config.force_save, (Player) sender); - }else { - MessageManager.consoleMessage(ConfigManager.Config.prefix + ConfigManager.Config.force_save, Bukkit.getConsoleSender()); - } - return true; - } - //强制生长 - if(args[0].equalsIgnoreCase("forcegrow")){ - if(args.length<2) return true; - Bukkit.getScheduler().runTaskAsynchronously(CustomCrops.instance, () -> CropManager.CropGrow(args[1])); - if(sender instanceof Player){ - MessageManager.playerMessage(ConfigManager.Config.prefix + ConfigManager.Config.force_grow, (Player) sender); - }else { - MessageManager.consoleMessage(ConfigManager.Config.prefix + ConfigManager.Config.force_grow, Bukkit.getConsoleSender()); - } - return true; - } - //强制洒水 - if(args[0].equalsIgnoreCase("forcewater")){ - if(args.length<2) return true; - Bukkit.getScheduler().runTaskAsynchronously(CustomCrops.instance, () -> SprinklerManager.SprinklerWork(args[1])); - if(sender instanceof Player){ - MessageManager.playerMessage(ConfigManager.Config.prefix + ConfigManager.Config.force_water, (Player) sender); - }else { - MessageManager.consoleMessage(ConfigManager.Config.prefix + ConfigManager.Config.force_water, Bukkit.getConsoleSender()); - } - return true; - } - if(args[0].equalsIgnoreCase("backup")){ - BackUp.backUpData(); - if(sender instanceof Player){ - MessageManager.playerMessage(ConfigManager.Config.prefix + ConfigManager.Config.backup, (Player) sender); - }else { - MessageManager.consoleMessage(ConfigManager.Config.prefix + ConfigManager.Config.backup, Bukkit.getConsoleSender()); - } - return true; - } - if(args[0].equalsIgnoreCase("nextseason")){ - NextSeason.changeSeason(); - if(sender instanceof Player){ - MessageManager.playerMessage(ConfigManager.Config.prefix + ConfigManager.Config.nextSeason, (Player) sender); - }else { - MessageManager.consoleMessage(ConfigManager.Config.prefix + ConfigManager.Config.nextSeason, Bukkit.getConsoleSender()); - } - return true; - } - return false; - } -} diff --git a/src/main/java/net/momirealms/customcrops/commands/CommandTabComplete.java b/src/main/java/net/momirealms/customcrops/commands/CommandTabComplete.java deleted file mode 100644 index e7702ad..0000000 --- a/src/main/java/net/momirealms/customcrops/commands/CommandTabComplete.java +++ /dev/null @@ -1,29 +0,0 @@ -package net.momirealms.customcrops.commands; - -import net.momirealms.customcrops.datamanager.ConfigManager; -import org.bukkit.command.Command; -import org.bukkit.command.CommandSender; -import org.bukkit.command.TabCompleter; -import org.jetbrains.annotations.Nullable; - -import javax.annotation.ParametersAreNonnullByDefault; -import java.util.Arrays; -import java.util.List; - -public class CommandTabComplete implements TabCompleter { - - @Override - @ParametersAreNonnullByDefault - public @Nullable List onTabComplete(CommandSender sender, Command command, String alias, String[] args) { - if (args.length == 1) { - return Arrays.asList("backup" , "forcegrow", "forcesave", "forcewater", "reload", "setseason" , "nextseason"); - } - if(args[0].equalsIgnoreCase("setseason")){ - return Arrays.asList("spring","summer","autumn","winter"); - } - if(args[0].equalsIgnoreCase("forcegrow") || args[0].equalsIgnoreCase("forcewater")){ - return ConfigManager.Config.worlds; - } - return null; - } -} diff --git a/src/main/java/net/momirealms/customcrops/commands/Completer.java b/src/main/java/net/momirealms/customcrops/commands/Completer.java new file mode 100644 index 0000000..3b0359c --- /dev/null +++ b/src/main/java/net/momirealms/customcrops/commands/Completer.java @@ -0,0 +1,46 @@ +package net.momirealms.customcrops.commands; + +import net.momirealms.customcrops.ConfigReader; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.command.TabCompleter; +import org.jetbrains.annotations.Nullable; + +import javax.annotation.ParametersAreNonnullByDefault; +import java.util.Arrays; +import java.util.List; + +public class Completer implements TabCompleter { + + @Override + @ParametersAreNonnullByDefault + public @Nullable List onTabComplete(CommandSender sender, Command command, String alias, String[] args) { + if (!(sender.isOp() || sender.hasPermission("customcrops.admin"))){ + return null; + } + if (args.length == 1) { + return Arrays.asList("backup", "forcegrow", "forcesave", "forcewater", "reload", "setseason"); + } + if(args[0].equalsIgnoreCase("setseason") && args.length == 2){ + return ConfigReader.Config.worldNames; + } + if(args[0].equalsIgnoreCase("forcesave") && args.length == 2){ + if (ConfigReader.Season.enable){ + if (ConfigReader.Season.seasonChange){ + return Arrays.asList("all","crop","pot","sprinkler"); + }else{ + return Arrays.asList("all","crop","pot","season","sprinkler"); + } + }else { + return Arrays.asList("all","crop","pot","sprinkler"); + } + } + if(args[0].equalsIgnoreCase("setseason") && args.length == 3){ + return Arrays.asList("spring","summer","autumn","winter"); + } + if(args[0].equalsIgnoreCase("forcegrow") || args[0].equalsIgnoreCase("forcewater")){ + return ConfigReader.Config.worldNames; + } + return null; + } +} diff --git a/src/main/java/net/momirealms/customcrops/commands/Executor.java b/src/main/java/net/momirealms/customcrops/commands/Executor.java new file mode 100644 index 0000000..2fb79ba --- /dev/null +++ b/src/main/java/net/momirealms/customcrops/commands/Executor.java @@ -0,0 +1,164 @@ +package net.momirealms.customcrops.commands; + +import net.momirealms.customcrops.utils.AdventureManager; +import net.momirealms.customcrops.ConfigReader; +import net.momirealms.customcrops.CustomCrops; +import net.momirealms.customcrops.utils.BackUp; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import javax.annotation.ParametersAreNonnullByDefault; + +public class Executor implements CommandExecutor { + + private final CustomCrops plugin; + + public Executor(CustomCrops plugin){ + this.plugin = plugin; + } + + @Override + @ParametersAreNonnullByDefault + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + //权限不足 + if (!(sender.hasPermission("customcrops.admin") || sender.isOp())){ + AdventureManager.playerMessage((Player) sender, ConfigReader.Message.prefix + ConfigReader.Message.noPerm); + return true; + } + //参数不足 + if (args.length < 1) { + lackArgs(sender); + return true; + } + switch (args[0]){ + case "reload" -> { + long time = System.currentTimeMillis(); + ConfigReader.ReloadConfig(); + if(sender instanceof Player){ + AdventureManager.playerMessage((Player) sender,ConfigReader.Message.prefix + ConfigReader.Message.reload.replace("{time}", String.valueOf(System.currentTimeMillis() - time))); + }else { + AdventureManager.consoleMessage(ConfigReader.Message.prefix + ConfigReader.Message.reload.replace("{time}", String.valueOf(System.currentTimeMillis() - time))); + } + return true; + } + case "forcegrow" -> { + if (args.length < 2) { + lackArgs(sender); + return true; + } + plugin.getCropManager().cropGrow(args[1]); + if (sender instanceof Player player){ + AdventureManager.playerMessage(player,ConfigReader.Message.prefix + ConfigReader.Message.forceGrow.replace("{world}",args[1])); + }else { + AdventureManager.consoleMessage(ConfigReader.Message.prefix + ConfigReader.Message.forceGrow.replace("{world}",args[1])); + } + return true; + } + case "forcewater" -> { + if (args.length < 2) { + lackArgs(sender); + return true; + } + plugin.getSprinklerManager().sprinklerWork(args[1]); + if (sender instanceof Player player){ + AdventureManager.playerMessage(player,ConfigReader.Message.prefix + ConfigReader.Message.forceWater.replace("{world}",args[1])); + }else { + AdventureManager.consoleMessage(ConfigReader.Message.prefix + ConfigReader.Message.forceWater.replace("{world}",args[1])); + } + return true; + } + case "forcesave" -> { + if (args.length < 2) { + lackArgs(sender); + return true; + } + switch (args[1]){ + case "all" -> { + plugin.getSprinklerManager().updateData(); + plugin.getSprinklerManager().saveData(); + if (ConfigReader.Season.enable && !ConfigReader.Season.seasonChange){ + plugin.getSeasonManager().saveData(); + } + plugin.getCropManager().updateData(); + plugin.getCropManager().saveData(); + plugin.getPotManager().saveData(); + forceSave(sender); + } + case "crop" -> { + plugin.getCropManager().updateData(); + plugin.getCropManager().saveData(); + forceSave(sender); + } + case "pot" -> { + plugin.getPotManager().saveData(); + forceSave(sender); + } + case "season" -> { + plugin.getSeasonManager().saveData(); + forceSave(sender); + } + case "sprinkler" -> { + plugin.getSprinklerManager().updateData(); + plugin.getSprinklerManager().saveData(); + forceSave(sender); + } + } + } + case "backup" -> { + BackUp.backUpData(); + if (sender instanceof Player player){ + AdventureManager.playerMessage(player,ConfigReader.Message.prefix + ConfigReader.Message.backUp); + }else { + AdventureManager.consoleMessage(ConfigReader.Message.prefix + ConfigReader.Message.backUp); + } + return true; + } + case "setseason" -> { + if (args.length < 3) { + lackArgs(sender); + return true; + } + if (plugin.getSeasonManager().setSeason(args[1], args[2])){ + if (sender instanceof Player player){ + AdventureManager.playerMessage(player,ConfigReader.Message.prefix + ConfigReader.Message.setSeason.replace("{world}",args[1]).replace("{season}",args[2])); + }else { + AdventureManager.consoleMessage(ConfigReader.Message.prefix + ConfigReader.Message.setSeason.replace("{world}",args[1]).replace("{season}",args[2])); + } + }else { + if (sender instanceof Player player){ + AdventureManager.playerMessage(player,ConfigReader.Message.prefix + ConfigReader.Message.wrongArgs); + }else { + AdventureManager.consoleMessage(ConfigReader.Message.prefix + ConfigReader.Message.wrongArgs); + } + } + return true; + } + default -> { + if (sender instanceof Player player){ + AdventureManager.playerMessage(player,""); + }else { + AdventureManager.consoleMessage(""); + } + } + } + return true; + } + + private void lackArgs(CommandSender sender){ + if (sender instanceof Player){ + AdventureManager.playerMessage((Player) sender,ConfigReader.Message.prefix + ConfigReader.Message.lackArgs); + }else { + AdventureManager.consoleMessage(ConfigReader.Message.prefix + ConfigReader.Message.lackArgs); + } + } + + private void forceSave(CommandSender sender){ + if (sender instanceof Player player){ + AdventureManager.playerMessage(player,ConfigReader.Message.prefix + ConfigReader.Message.forceSave); + }else { + AdventureManager.consoleMessage(ConfigReader.Message.prefix + ConfigReader.Message.forceSave); + } + } +} diff --git a/src/main/java/net/momirealms/customcrops/datamanager/ConfigManager.java b/src/main/java/net/momirealms/customcrops/datamanager/ConfigManager.java deleted file mode 100644 index 9d8254c..0000000 --- a/src/main/java/net/momirealms/customcrops/datamanager/ConfigManager.java +++ /dev/null @@ -1,249 +0,0 @@ -package net.momirealms.customcrops.datamanager; - -import net.momirealms.customcrops.CustomCrops; -import net.momirealms.customcrops.utils.Crop; -import org.apache.commons.lang.StringUtils; -import org.bukkit.Bukkit; -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.configuration.file.YamlConfiguration; - -import java.io.File; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Set; - -public class ConfigManager { - - public static HashMap CONFIG; - static { - CONFIG = new HashMap<>(); - } - - public static class Config{ - - public static boolean res; - public static boolean wg; - public static boolean king; - public static boolean gd; - public static boolean season; - public static boolean need_water; - public static boolean greenhouse; - public static boolean limit; - public static boolean log_time; - - public static List worlds; - public static List cropGrowTimeList; - public static List sprinklerWorkTimeList; - - public static String current; - public static String prefix; - public static String bad_place; - public static String reload; - public static String force_save; - public static String nextSeason; - public static String no_such_seed; - public static String wrong_season; - public static String season_set; - public static String season_disabled; - public static String force_grow; - public static String force_water; - public static String limit_crop; - public static String limit_sprinkler; - public static String backup; - public static String spring; - public static String summer; - public static String autumn; - public static String winter; - public static String can_full; - public static String pot; - public static String watered_pot; - public static String watering_can_1; - public static String watering_can_2; - public static String watering_can_3; - public static String glass; - public static String sprinkler_1; - public static String sprinkler_2; - public static String sprinkler_1i; - public static String sprinkler_2i; - public static String dead; - public static String success; - public static String failure; - - public static double bone_chance; - - public static int range; - public static int maxh; - public static int minh; - public static int max_crop; - public static int max_sprinkler; - - public static void ReloadConfig(){ - CustomCrops.instance.saveDefaultConfig(); - CustomCrops.instance.reloadConfig(); - FileConfiguration configuration = CustomCrops.instance.getConfig(); - //处理配置 - Config.res = configuration.getBoolean("config.integration.residence",false); - Config.king = configuration.getBoolean("config.integration.kingdomsX",false); - Config.wg = configuration.getBoolean("config.integration.worldguard",false); - Config.gd = configuration.getBoolean("config.integration.griefdefender",false); - - if(res){ - if(Bukkit.getPluginManager().getPlugin("Residence") == null){ - CustomCrops.instance.getLogger().warning("未检测到插件Residence!"); - res = false; - }else { - MessageManager.consoleMessage("&#ccfbff-#ef96c5&[CustomCrops] &7检测到 &aResidence &7已启用领地保护!",Bukkit.getConsoleSender()); - } - } - if(king){ - if(Bukkit.getPluginManager().getPlugin("Kingdoms") == null){ - CustomCrops.instance.getLogger().warning("未检测到插件KingdomsX!"); - king = false; - }else { - MessageManager.consoleMessage("&#ccfbff-#ef96c5&[CustomCrops] &7检测到 &aKingdomsX &7已启用领地保护!",Bukkit.getConsoleSender()); - } - } - if(wg){ - if(Bukkit.getPluginManager().getPlugin("WorldGuard") == null){ - CustomCrops.instance.getLogger().warning("未检测到插件WorldGuard!"); - wg = false; - }else { - MessageManager.consoleMessage("&#ccfbff-#ef96c5&[CustomCrops] &7检测到 &aWorldGuard &7已启用区域保护!",Bukkit.getConsoleSender()); - } - } - if(gd){ - if(Bukkit.getPluginManager().getPlugin("GriefDefender") == null){ - CustomCrops.instance.getLogger().warning("未检测到插件GriefDefender!"); - gd = false; - }else { - MessageManager.consoleMessage("&#ccfbff-#ef96c5&[CustomCrops] &7检测到 &aGriefDefender &7已启用领地保护!",Bukkit.getConsoleSender()); - } - } - - Config.season = configuration.getBoolean("enable-season"); - Config.need_water = configuration.getBoolean("config.bone-meal-consume-water"); - Config.greenhouse = configuration.getBoolean("config.enable-greenhouse"); - Config.limit = configuration.getBoolean("config.enable-limit"); - Config.log_time = configuration.getBoolean("config.log-time-consume", false); - - Config.bone_chance = configuration.getDouble("config.bone-meal-chance"); - - Config.range = configuration.getInt("config.greenhouse-range"); - Config.maxh = configuration.getInt("config.height.max"); - Config.minh = configuration.getInt("config.height.min"); - Config.max_crop = configuration.getInt("config.max-crops"); - Config.max_sprinkler = configuration.getInt("config.max-sprinklers"); - - Config.current = configuration.getString("current-season"); - Config.pot = configuration.getString("config.pot"); - Config.watered_pot = configuration.getString("config.watered-pot"); - Config.watering_can_1 = configuration.getString("config.watering-can-1"); - Config.watering_can_2 = configuration.getString("config.watering-can-2"); - Config.watering_can_3 = configuration.getString("config.watering-can-3"); - Config.glass = configuration.getString("config.greenhouse-glass"); - Config.sprinkler_1 = configuration.getString("config.sprinkler-1"); - Config.sprinkler_2 = configuration.getString("config.sprinkler-2"); - Config.sprinkler_1i = configuration.getString("config.sprinkler-1-item"); - Config.sprinkler_2i = configuration.getString("config.sprinkler-2-item"); - Config.dead = configuration.getString("config.dead-crop"); - Config.success = configuration.getString("config.particle.success"); - Config.failure = configuration.getString("config.particle.failure"); - - Config.worlds = configuration.getStringList("config.whitelist-worlds"); - Config.cropGrowTimeList = configuration.getLongList("config.grow-time"); - Config.sprinklerWorkTimeList = configuration.getLongList("config.sprinkler-time"); - - //处理消息 - Config.prefix = configuration.getString("messages.prefix"); - Config.bad_place = configuration.getString("messages.not-a-good-place"); - Config.reload = configuration.getString("messages.reload"); - Config.force_save = configuration.getString("messages.force-save"); - Config.nextSeason = configuration.getString("messages.nextseason"); - Config.no_such_seed = configuration.getString("messages.no-such-seed"); - Config.wrong_season = configuration.getString("messages.wrong-season"); - Config.season_set = configuration.getString("messages.season-set"); - Config.season_disabled = configuration.getString("messages.season-disabled"); - Config.force_grow = configuration.getString("messages.force-grow"); - Config.force_water = configuration.getString("messages.force-water"); - Config.limit_crop = configuration.getString("messages.reach-limit-crop"); - Config.limit_sprinkler = configuration.getString("messages.reach-limit-sprinkler"); - Config.can_full = configuration.getString("messages.can-full"); - Config.backup = configuration.getString("messages.backup"); - Config.spring = configuration.getString("messages.spring"); - Config.summer = configuration.getString("messages.summer"); - Config.autumn = configuration.getString("messages.autumn"); - Config.winter = configuration.getString("messages.winter"); - - cropLoad(); - } - - /* - 根据文件名获取配置文件 - */ - public static YamlConfiguration getConfig(String configName) { - - File file = new File(CustomCrops.instance.getDataFolder(), configName); - //文件不存在则生成默认配置 - if (!file.exists()) { - CustomCrops.instance.saveResource(configName, false); - } - return YamlConfiguration.loadConfiguration(file); - } - - /* - 加载农作物数据 - */ - public static void cropLoad(){ - try { - CONFIG.clear(); - YamlConfiguration cropConfig = getConfig("crops.yml"); - Set keys = cropConfig.getConfigurationSection("crops").getKeys(false); - keys.forEach(key -> { - if(cropConfig.getConfigurationSection("crops."+key).contains("grow-chance")){ - double chance = cropConfig.getDouble("crops."+key+".grow-chance"); - Crop crop = new Crop(key, chance); - if(cropConfig.getConfigurationSection("crops."+key).contains("return")){ - crop.setWillReturn(true); - crop.setReturnStage(cropConfig.getString("crops."+key+".return")); - }else { - crop.setWillReturn(false); - } - if(Config.season){ - if(cropConfig.getConfigurationSection("crops."+key).contains("season")){ - crop.setSeasons(StringUtils.split( cropConfig.getString("crops."+key+".season"), ",")); - }else { - MessageManager.consoleMessage("&c[CustomCrops] 错误!在启用季节模式的情况下未设置农作物 &f"+ key +" &c的生长季节!", Bukkit.getConsoleSender()); - return; - } - } - if(cropConfig.getConfigurationSection("crops."+key).contains("gigantic")){ - crop.setWillGiant(true); - crop.setGiant(cropConfig.getString("crops."+key+".gigantic")); - if(cropConfig.getConfigurationSection("crops."+key).contains("gigantic-chance")){ - crop.setGiantChance(cropConfig.getDouble("crops."+key+".gigantic-chance")); - }else { - MessageManager.consoleMessage("&c[CustomCrops] 错误!未设置农作物 &f"+ key +" &c的巨大化概率!", Bukkit.getConsoleSender()); - return; - } - }else { - crop.setWillGiant(false); - } - CONFIG.put(key, crop); - }else { - MessageManager.consoleMessage("&c[CustomCrops] 错误!未设置农作物 &f"+ key +" &c的生长概率!", Bukkit.getConsoleSender()); - } - }); - if(keys.size() == CONFIG.size()){ - MessageManager.consoleMessage("&#ccfbff-#ef96c5&[CustomCrops] &7成功载入 &a" + CONFIG.size() + " &7种农作物", Bukkit.getConsoleSender()); - }else { - MessageManager.consoleMessage("&c[CustomCrops] crops.yml配置存在错误,请根据上述提示仔细检查!", Bukkit.getConsoleSender()); - } - } - catch (Exception e) { - e.printStackTrace(); - CustomCrops.instance.getLogger().warning("crops.yml加载失败!"); - } - } - } -} diff --git a/src/main/java/net/momirealms/customcrops/datamanager/CropManager.java b/src/main/java/net/momirealms/customcrops/datamanager/CropManager.java index fc5a001..9d00b9e 100644 --- a/src/main/java/net/momirealms/customcrops/datamanager/CropManager.java +++ b/src/main/java/net/momirealms/customcrops/datamanager/CropManager.java @@ -1,249 +1,236 @@ package net.momirealms.customcrops.datamanager; import dev.lone.itemsadder.api.CustomBlock; +import net.momirealms.customcrops.fertilizer.QualityCrop; +import net.momirealms.customcrops.utils.AdventureManager; +import net.momirealms.customcrops.ConfigReader; import net.momirealms.customcrops.CustomCrops; -import net.momirealms.customcrops.utils.Crop; +import net.momirealms.customcrops.fertilizer.Fertilizer; +import net.momirealms.customcrops.fertilizer.RetainingSoil; +import net.momirealms.customcrops.fertilizer.SpeedGrow; +import net.momirealms.customcrops.utils.CropInstance; import org.apache.commons.lang.StringUtils; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.World; -import org.bukkit.block.Block; -import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.YamlConfiguration; -import org.bukkit.scheduler.BukkitScheduler; import java.io.File; import java.io.IOException; -import java.util.*; +import java.util.List; import java.util.concurrent.ConcurrentHashMap; public class CropManager { - public static ConcurrentHashMap CROPS; - /* - 开服的时候将文件的数据读入 - */ - public static void loadData() { + private YamlConfiguration data; + private final CustomCrops plugin; + public static ConcurrentHashMap Cache = new ConcurrentHashMap<>(); - File file = new File(CustomCrops.instance.getDataFolder(), "crop-data.yml"); - FileConfiguration data = YamlConfiguration.loadConfiguration(file); + public CropManager(CustomCrops plugin){ + this.plugin = plugin; + } - CROPS = new ConcurrentHashMap<>(); - - for (String world : ConfigManager.Config.worlds) { - //如果数据文件中有相应世界才进行读取 - if(data.contains(world)){ - for (String coordinate : data.getConfigurationSection(world).getKeys(false)) { - Location tempLoc = new Location(Bukkit.getWorld(world), Integer.parseInt(coordinate.split(",")[0]), Integer.parseInt(coordinate.split(",")[1]), Integer.parseInt(coordinate.split(",")[2])); - String cropName = data.getString(world + "." + coordinate); - CROPS.put(tempLoc, cropName); - } + //载入数据 + public void loadData() { + File file = new File(CustomCrops.instance.getDataFolder(), "data" + File.separator + "crop.yml"); + if(!file.exists()){ + try { + file.getParentFile().mkdirs(); + file.createNewFile(); + } catch (IOException e) { + e.printStackTrace(); + AdventureManager.consoleMessage("[CustomCrops] 农作物数据文件生成失败!"); } } + this.data = YamlConfiguration.loadConfiguration(file); } - /* - 保存数据 - */ - public static void saveData(){ - - File file = new File(CustomCrops.instance.getDataFolder(), "crop-data.yml"); - FileConfiguration data; - data = YamlConfiguration.loadConfiguration(file); - - Set> en = CROPS.entrySet(); - for(Map.Entry entry : en){ - Location loc = entry.getKey(); - data.set(loc.getWorld().getName()+"."+ loc.getBlockX() + "," + loc.getBlockY()+ ","+loc.getBlockZ(), entry.getValue()); - } - try { - data.save(file); - } - catch (IOException e) { - e.printStackTrace(); - CustomCrops.instance.getLogger().warning("农作物数据保存出错"); - } - } - /* - 生长部分 - */ - public static void CropGrow(String worldName) { - /* - 阶段1:更新数据 - */ - long start1 = System.currentTimeMillis(); - File file = new File(CustomCrops.instance.getDataFolder(), "crop-data.yml"); - FileConfiguration data = YamlConfiguration.loadConfiguration(file); - BukkitScheduler bukkitScheduler = Bukkit.getScheduler(); - Set> en = CROPS.entrySet(); - for(Map.Entry entry : en){ - Location key = entry.getKey(); - data.set(key.getWorld().getName() + "." + key.getBlockX() + "," + key.getBlockY()+ ","+ key.getBlockZ(), entry.getValue()); - } - long finish1 = System.currentTimeMillis(); - if (ConfigManager.Config.log_time){ - MessageManager.consoleMessage("&#ccfbff-#ef96c5&[CustomCrops] &7农作物数据更新耗时&a" + (finish1 - start1) + "&fms",Bukkit.getConsoleSender()); - } - /* - 阶段2:清理数据内无效的农作物并让有效农作物生长 - */ - long start2 = System.currentTimeMillis(); - if(data.contains(worldName)){ - World world = Bukkit.getWorld(worldName); - data.getConfigurationSection(worldName).getKeys(false).forEach(key ->{ - String[] coordinate = StringUtils.split(key,","); - //先判断区块是否加载,未加载则不进行下一步计算 - if (world.isChunkLoaded(Integer.parseInt(coordinate[0])/16, Integer.parseInt(coordinate[2])/16)){ - Location sLoc = new Location(world,Double.parseDouble(coordinate[0]),Double.parseDouble(coordinate[1]),Double.parseDouble(coordinate[2])); - CustomBlock seedBlock = CustomBlock.byAlreadyPlaced(sLoc.getBlock()); - if(seedBlock == null){ - CROPS.remove(sLoc); - data.set(worldName+"."+coordinate[0]+","+coordinate[1]+","+coordinate[2], null); - }else{ - String namespacedID = seedBlock.getNamespacedID(); - /* - 对之前旧版本的一些兼容 - 以及一些意料之外的情况,防止报错 - */ - if(namespacedID.equalsIgnoreCase(ConfigManager.Config.dead)){ - CROPS.remove(sLoc); - data.set(worldName+"."+coordinate[0]+","+coordinate[1]+","+coordinate[2], null); - return; - } - if(namespacedID.contains("_stage_")){ - Location potLoc = sLoc.clone().subtract(0,1,0); - Block potBlock = potLoc.getBlock(); - CustomBlock pot = CustomBlock.byAlreadyPlaced(potBlock); - if (pot != null){ - String potName = pot.getNamespacedID(); - /* - 是湿润的种植盆吗 - */ - if (potName.equalsIgnoreCase(ConfigManager.Config.watered_pot)){ - String[] split = StringUtils.split(namespacedID,":"); - String[] cropNameList = StringUtils.split(split[1],"_"); - Crop crop = ConfigManager.CONFIG.get(cropNameList[0]); - //季节判断 - Label_out: - if(ConfigManager.Config.season){ - if(ConfigManager.Config.greenhouse){ - for(int i = 1; i <= ConfigManager.Config.range; i++){ - CustomBlock cb = CustomBlock.byAlreadyPlaced(sLoc.clone().add(0,i,0).getBlock()); - if (cb != null){ - if(cb.getNamespacedID().equalsIgnoreCase(ConfigManager.Config.glass)){ - break Label_out; - } - } - } - } - boolean ws = true; - for(String season : crop.getSeasons()){ - if (Objects.equals(season, ConfigManager.Config.current)) { - ws = false; - break; - } - } - if(ws){ - CROPS.remove(sLoc); - data.set(worldName+"."+coordinate[0]+","+coordinate[1]+","+coordinate[2], null); - bukkitScheduler.callSyncMethod(CustomCrops.instance, () -> { - CustomBlock.remove(sLoc); - CustomBlock.place(ConfigManager.Config.dead, sLoc); - return null; - }); - return; - } - } - //下一阶段判断 - int nextStage = Integer.parseInt(cropNameList[2]) + 1; - if (CustomBlock.getInstance(split[0] +":"+cropNameList[0] + "_stage_" + nextStage) != null) { - bukkitScheduler.callSyncMethod(CustomCrops.instance, () ->{ - CustomBlock.remove(potLoc); - CustomBlock.place(ConfigManager.Config.pot, potLoc); - if(Math.random()< crop.getChance()){ - CustomBlock.remove(sLoc); - CustomBlock.place(split[0] + ":" + cropNameList[0] + "_stage_" + nextStage, sLoc); - } - return null; - }); - } - //巨大化判断 - else if(crop.getWillGiant()){ - bukkitScheduler.callSyncMethod(CustomCrops.instance, () ->{ - CustomBlock.remove(potLoc); - CustomBlock.place(ConfigManager.Config.pot, potLoc); - if(crop.getGiantChance() > Math.random()){ - CROPS.remove(sLoc); - data.set(worldName+"."+coordinate[0]+","+coordinate[1]+","+coordinate[2], null); - CustomBlock.remove(sLoc); - CustomBlock.place(crop.getGiant(), sLoc); - } - return null; - }); - } - } - /* - 是干燥的种植盆吗 - */ - else if(potName.equalsIgnoreCase(ConfigManager.Config.pot)){ - if(ConfigManager.Config.season) { - if(ConfigManager.Config.greenhouse){ - for(int i = 1; i <= ConfigManager.Config.range; i++){ - CustomBlock cb = CustomBlock.byAlreadyPlaced(sLoc.clone().add(0,i,0).getBlock()); - if (cb != null){ - if(cb.getNamespacedID().equalsIgnoreCase(ConfigManager.Config.glass)){ - return; - } - } - } - } - boolean ws = true; - Crop crop = ConfigManager.CONFIG.get(StringUtils.split(StringUtils.split(namespacedID,":")[1],"_")[0]); - for (String season : crop.getSeasons()) { - if (Objects.equals(season, ConfigManager.Config.current)) { - ws = false; - break; - } - } - if (ws) { - CROPS.remove(sLoc); - data.set(worldName+"."+coordinate[0]+","+coordinate[1]+","+coordinate[2], null); - bukkitScheduler.callSyncMethod(CustomCrops.instance, () -> { - CustomBlock.remove(sLoc); - CustomBlock.place(ConfigManager.Config.dead, sLoc); - return null; - }); - } - } - } - } - } - else { - CROPS.remove(sLoc); - data.set(worldName+"."+coordinate[0]+","+coordinate[1]+","+coordinate[2], null); - } - } - } - }); - } - long finish2 = System.currentTimeMillis(); - if (ConfigManager.Config.log_time){ - MessageManager.consoleMessage("&#ccfbff-#ef96c5&[CustomCrops] &7农作物生长耗时&a" + (finish2 - start2) + "&fms",Bukkit.getConsoleSender()); - } - - /* - 阶段3:保存文件 - */ - long start3 = System.currentTimeMillis(); + //保存数据 + public void saveData() { + File file = new File(CustomCrops.instance.getDataFolder(), "data" + File.separator + "crop.yml"); try{ data.save(file); }catch (IOException e){ e.printStackTrace(); - CustomCrops.instance.getLogger().warning("crop-data.yml保存出错!"); - } - long finish3 = System.currentTimeMillis(); - if (ConfigManager.Config.log_time){ - MessageManager.consoleMessage("&#ccfbff-#ef96c5&[CustomCrops] &7农作物数据保存耗时&a" + (finish3 - start3) + "&fms",Bukkit.getConsoleSender()); + AdventureManager.consoleMessage("[CustomCrops] crop.yml保存出错!"); } } -} + + //将缓存内新数据更新到data内 + public void updateData(){ + Cache.forEach((location, String) -> { + int x = location.getBlockX(); + int z = location.getBlockZ(); + data.set(location.getWorld().getName() + "." + x / 16 + "," + z / 16 + "." + x + "," + location.getBlockY() + "," + z, String); + }); + Cache.clear(); + } + + //农作物生长 + public void cropGrow(String worldName){ + Long time1 = System.currentTimeMillis(); + updateData(); + Long time2 = System.currentTimeMillis(); + if(ConfigReader.Config.logTime){ + AdventureManager.consoleMessage("性能监测: 农作物数据更新" + (time2-time1) + "ms"); + } + if (data.contains(worldName)){ + data.getConfigurationSection(worldName).getKeys(false).forEach(chunk ->{ + String[] split = StringUtils.split(chunk,","); + World world = Bukkit.getWorld(worldName); + if (ConfigReader.Config.onlyLoadedGrow || world.isChunkLoaded(Integer.parseInt(split[0]), Integer.parseInt(split[1]))){ + data.getConfigurationSection(worldName + "." + chunk).getValues(false).forEach((key, value) -> { + String[] coordinate = StringUtils.split(key, ","); + Location seedLocation = new Location(world,Double.parseDouble(coordinate[0]),Double.parseDouble(coordinate[1]),Double.parseDouble(coordinate[2])); + CustomBlock seedBlock = CustomBlock.byAlreadyPlaced(seedLocation.getBlock()); + StringBuilder stringBuilder = new StringBuilder(); + //需要修改 + stringBuilder.append(worldName).append(".").append(chunk).append(".").append(key); + if(seedBlock == null) { + data.set(stringBuilder.toString(), null); + return; + } + String namespacedID = seedBlock.getNamespacedID(); + String id = seedBlock.getId(); + if(namespacedID.equals(ConfigReader.Basic.dead)) { + data.set(stringBuilder.toString(), null); + return; + } + if(!namespacedID.contains("_stage_")) { + data.set(stringBuilder.toString(), null); + return; + } + Location potLocation = seedLocation.clone().subtract(0,1,0); + CustomBlock pot = CustomBlock.byAlreadyPlaced(potLocation.getBlock()); + if (pot == null) return; + String potNamespacedID = pot.getNamespacedID(); + String[] cropNameList = StringUtils.split(id,"_"); + CropInstance cropInstance = ConfigReader.CROPS.get(cropNameList[0]); + if (potNamespacedID.equals(ConfigReader.Basic.watered_pot)){ + //如果启用季节限制且农作物有季节需求 + if (ConfigReader.Season.enable && cropInstance.getSeasons() != null){ + if (isWrongSeason(seedLocation, cropInstance.getSeasons(), worldName)){ + data.set(stringBuilder.toString(), null); + Bukkit.getScheduler().callSyncMethod(CustomCrops.instance, () -> { + CustomBlock.remove(seedLocation); + CustomBlock.place(ConfigReader.Basic.dead, seedLocation); + return null; + }); + return; + } + } + int nextStage = Integer.parseInt(cropNameList[2]) + 1; + if (CustomBlock.getInstance(StringUtils.chop(namespacedID) + nextStage) != null) { + Fertilizer fertilizer = PotManager.Cache.get(potLocation); + if (fertilizer != null){ + int times = fertilizer.getTimes(); + if (times > 0){ + fertilizer.setTimes(times - 1); + if (fertilizer instanceof SpeedGrow speedGrow){ + if (Math.random() < speedGrow.getChance() && CustomBlock.getInstance(StringUtils.chop(namespacedID) + (nextStage + 1)) != null){ + addStage(potLocation, seedLocation, namespacedID, nextStage + 1); + }else { + addStage(potLocation, seedLocation, namespacedID, nextStage); + } + }else if(fertilizer instanceof RetainingSoil retainingSoil){ + if (Math.random() < retainingSoil.getChance()){ + addStage(seedLocation, namespacedID, nextStage); + }else { + addStage(potLocation, seedLocation, namespacedID, nextStage); + } + }else if(fertilizer instanceof QualityCrop){ + addStage(potLocation, seedLocation, namespacedID, nextStage); + }else { + AdventureManager.consoleMessage("[CustomCrops] 发现未知类型肥料,已自动清除错误数据!"); + PotManager.Cache.remove(potLocation); + } + }else { + PotManager.Cache.remove(potLocation); + } + } + else { + addStage(potLocation, seedLocation, namespacedID, nextStage); + } + } + else if(cropInstance.getGiant() != null){ + Bukkit.getScheduler().callSyncMethod(CustomCrops.instance, () ->{ + CustomBlock.remove(potLocation); + CustomBlock.place(ConfigReader.Basic.pot, potLocation); + if(cropInstance.getGiantChance() > Math.random()){ + data.set(stringBuilder.toString(), null); + CustomBlock.remove(seedLocation); + CustomBlock.place(cropInstance.getGiant(), seedLocation); + } + return null; + }); + }else { + if (cropInstance.getReturnStage() == null && !ConfigReader.Season.enable) data.set(stringBuilder.toString(), null); + Bukkit.getScheduler().callSyncMethod(CustomCrops.instance, () -> { + CustomBlock.remove(potLocation); + CustomBlock.place(ConfigReader.Basic.pot, potLocation); + return null; + }); + } + }else if(potNamespacedID.equals(ConfigReader.Basic.pot)){ + if(!ConfigReader.Season.enable || cropInstance.getSeasons() == null) return; + if(isWrongSeason(seedLocation, cropInstance.getSeasons(), worldName)){ + data.set(stringBuilder.toString(), null); + Bukkit.getScheduler().callSyncMethod(CustomCrops.instance, () -> { + CustomBlock.remove(seedLocation); + CustomBlock.place(ConfigReader.Basic.dead, seedLocation); + return null; + }); + } + } + }); + } + }); + } + Long time3 = System.currentTimeMillis(); + if(ConfigReader.Config.logTime){ + AdventureManager.consoleMessage("性能监测: 农作物生长过程" + (time3-time2) + "ms"); + } + saveData(); + Long time4 = System.currentTimeMillis(); + if(ConfigReader.Config.logTime){ + AdventureManager.consoleMessage("性能监测: 农作物数据保存" + (time4-time3) + "ms"); + } + } + + private boolean isWrongSeason(Location seedLocation, List seasons, String worldName){ + if(ConfigReader.Season.greenhouse){ + for(int i = 1; i <= ConfigReader.Season.range; i++){ + CustomBlock customBlock = CustomBlock.byAlreadyPlaced(seedLocation.clone().add(0,i,0).getBlock()); + if (customBlock != null){ + if(customBlock.getNamespacedID().equals(ConfigReader.Basic.glass)){ + return false; + } + } + } + } + for(String season : seasons){ + if (season.equals(SeasonManager.SEASON.get(worldName))) { + return false; + } + } + return true; + } + + private void addStage(Location potLocation, Location seedLocation, String namespacedID, int nextStage){ + Bukkit.getScheduler().callSyncMethod(CustomCrops.instance, () ->{ + CustomBlock.remove(potLocation); + CustomBlock.place(ConfigReader.Basic.pot, potLocation); + CustomBlock.remove(seedLocation); + CustomBlock.place(StringUtils.chop(namespacedID) + nextStage, seedLocation); + return null; + }); + } + + private void addStage(Location seedLocation, String namespacedID, int nextStage){ + Bukkit.getScheduler().callSyncMethod(CustomCrops.instance, () ->{ + CustomBlock.remove(seedLocation); + CustomBlock.place(StringUtils.chop(namespacedID) + nextStage, seedLocation); + return null; + }); + } +} \ No newline at end of file diff --git a/src/main/java/net/momirealms/customcrops/datamanager/MessageManager.java b/src/main/java/net/momirealms/customcrops/datamanager/MessageManager.java deleted file mode 100644 index 8a5550c..0000000 --- a/src/main/java/net/momirealms/customcrops/datamanager/MessageManager.java +++ /dev/null @@ -1,12 +0,0 @@ -package net.momirealms.customcrops.datamanager; - -import net.momirealms.customcrops.libs.minedown.MineDown; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; - -public class MessageManager { - public static void consoleMessage(String s, CommandSender sender) { sender.spigot().sendMessage(MineDown.parse(s)); } - public static void playerMessage(String s, Player player){ - player.spigot().sendMessage(MineDown.parse(s)); - } -} diff --git a/src/main/java/net/momirealms/customcrops/datamanager/NextSeason.java b/src/main/java/net/momirealms/customcrops/datamanager/NextSeason.java deleted file mode 100644 index b63c72c..0000000 --- a/src/main/java/net/momirealms/customcrops/datamanager/NextSeason.java +++ /dev/null @@ -1,28 +0,0 @@ -package net.momirealms.customcrops.datamanager; - -import net.momirealms.customcrops.CustomCrops; -import org.bukkit.configuration.file.FileConfiguration; - -import java.util.Objects; - -public class NextSeason { - - public static void changeSeason(){ - FileConfiguration config = CustomCrops.instance.getConfig(); - String currentSeason = ConfigManager.Config.current; - String nextSeason = switch (Objects.requireNonNull(currentSeason)) { - case "spring" -> "summer"; - case "summer" -> "autumn"; - case "autumn" -> "winter"; - case "winter" -> "spring"; - default -> null; - }; - if(nextSeason != null){ - config.set("current-season", nextSeason); - ConfigManager.Config.current = nextSeason; - CustomCrops.instance.saveConfig(); - }else { - CustomCrops.instance.getLogger().warning("季节出错!"); - } - } -} \ No newline at end of file diff --git a/src/main/java/net/momirealms/customcrops/datamanager/PotManager.java b/src/main/java/net/momirealms/customcrops/datamanager/PotManager.java new file mode 100644 index 0000000..44e7124 --- /dev/null +++ b/src/main/java/net/momirealms/customcrops/datamanager/PotManager.java @@ -0,0 +1,81 @@ +package net.momirealms.customcrops.datamanager; + +import net.momirealms.customcrops.utils.AdventureManager; +import net.momirealms.customcrops.ConfigReader; +import net.momirealms.customcrops.CustomCrops; +import net.momirealms.customcrops.fertilizer.Fertilizer; +import net.momirealms.customcrops.fertilizer.QualityCrop; +import net.momirealms.customcrops.fertilizer.RetainingSoil; +import net.momirealms.customcrops.fertilizer.SpeedGrow; +import org.apache.commons.lang.StringUtils; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.configuration.MemorySection; +import org.bukkit.configuration.file.YamlConfiguration; + +import java.io.File; +import java.io.IOException; +import java.util.concurrent.ConcurrentHashMap; + +public class PotManager { + + private CustomCrops plugin; + public static ConcurrentHashMap Cache = new ConcurrentHashMap<>(); + + public PotManager(CustomCrops plugin){ + this.plugin = plugin; + } + + public void loadData(){ + File file = new File(CustomCrops.instance.getDataFolder(), "data" + File.separator + "pot.yml"); + if(!file.exists()){ + try { + file.getParentFile().mkdirs(); + file.createNewFile(); + } catch (IOException e) { + e.printStackTrace(); + AdventureManager.consoleMessage("[CustomCrops] 种植盆数据文件生成失败!"); + } + } + YamlConfiguration data = YamlConfiguration.loadConfiguration(file); + data.getKeys(false).forEach(worldName -> { + if (ConfigReader.Config.worldNames.contains(worldName)){ + data.getConfigurationSection(worldName).getValues(false).forEach((key, value) ->{ + String[] split = StringUtils.split(key, ","); + if (value instanceof MemorySection map){ + String name = (String) map.get("fertilizer"); + Fertilizer fertilizer = ConfigReader.FERTILIZERS.get(name); + if (fertilizer == null) return; + if (fertilizer instanceof SpeedGrow speedGrow){ + Cache.put(new Location(Bukkit.getWorld(worldName), Double.parseDouble(split[0]), Double.parseDouble(split[1]), Double.parseDouble(split[2])), new SpeedGrow(name, (int) map.get("times"), speedGrow.getChance(), speedGrow.isBefore())); + }else if (fertilizer instanceof QualityCrop qualityCrop){ + Cache.put(new Location(Bukkit.getWorld(worldName), Double.parseDouble(split[0]), Double.parseDouble(split[1]), Double.parseDouble(split[2])), new QualityCrop(name, (int) map.get("times"), qualityCrop.getChance(), qualityCrop.isBefore())); + }else if (fertilizer instanceof RetainingSoil retainingSoil){ + Cache.put(new Location(Bukkit.getWorld(worldName), Double.parseDouble(split[0]), Double.parseDouble(split[1]), Double.parseDouble(split[2])), new RetainingSoil(name, (int) map.get("times"), retainingSoil.getChance(), retainingSoil.isBefore())); + }else { + AdventureManager.consoleMessage("[CustomCrops] 未知肥料类型错误!"); + } + } + }); + } + }); + } + + public void saveData(){ + File file = new File(CustomCrops.instance.getDataFolder(), "data" + File.separator + "pot.yml"); + YamlConfiguration data = new YamlConfiguration(); + Cache.forEach(((location, fertilizer) -> { + String world = location.getWorld().getName(); + int x = location.getBlockX(); + int y = location.getBlockY(); + int z = location.getBlockZ(); + data.set(world + "." + x + "," + y + "," + z + ".fertilizer", fertilizer.getKey()); + data.set(world + "." + x + "," + y + "," + z + ".times", fertilizer.getTimes()); + })); + try { + data.save(file); + }catch (IOException e){ + e.printStackTrace(); + } + } +} diff --git a/src/main/java/net/momirealms/customcrops/datamanager/SeasonManager.java b/src/main/java/net/momirealms/customcrops/datamanager/SeasonManager.java new file mode 100644 index 0000000..33de245 --- /dev/null +++ b/src/main/java/net/momirealms/customcrops/datamanager/SeasonManager.java @@ -0,0 +1,90 @@ +package net.momirealms.customcrops.datamanager; + +import net.momirealms.customcrops.utils.AdventureManager; +import net.momirealms.customcrops.ConfigReader; +import net.momirealms.customcrops.CustomCrops; +import org.bukkit.Bukkit; +import org.bukkit.World; +import org.bukkit.configuration.file.YamlConfiguration; + +import java.io.File; +import java.io.IOException; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Set; + +public record SeasonManager(CustomCrops plugin) { + + public static HashMap SEASON = new HashMap<>(); + + private YamlConfiguration readData(File file) { + if (!file.exists()) { + try { + file.getParentFile().mkdirs(); + file.createNewFile(); + } catch (IOException e) { + e.printStackTrace(); + AdventureManager.consoleMessage("[CustomCrops] 季节数据文件生成失败!"); + } + } + return YamlConfiguration.loadConfiguration(file); + } + + public void loadData() { + SEASON.clear(); + YamlConfiguration data = readData(new File(CustomCrops.instance.getDataFolder(), "data" + File.separator + "season.yml")); + if (ConfigReader.Season.seasonChange) { + autoSeason(); + } else { + Set set = data.getKeys(false); + ConfigReader.Config.worldNames.forEach(worldName -> { + if (set.contains(worldName)) { + SEASON.put(worldName, data.getString(worldName)); + } else { + getSeason(Bukkit.getWorld(worldName)); + } + }); + } + } + + public void autoSeason() { + ConfigReader.Config.worlds.forEach(this::getSeason); + } + + public void getSeason(World world) { + + int season = (int) ((world.getFullTime() / 24000L) % (ConfigReader.Season.duration * 4)) / ConfigReader.Season.duration; + switch (season) { + case 0 -> SEASON.put(world.getName(), "spring"); + case 1 -> SEASON.put(world.getName(), "summer"); + case 2 -> SEASON.put(world.getName(), "autumn"); + case 3 -> SEASON.put(world.getName(), "winter"); + default -> AdventureManager.consoleMessage("[CustomCrops] 自动季节计算错误!"); + } + } + + public void saveData() { + SEASON.forEach((key, value) -> { + File file = new File(CustomCrops.instance.getDataFolder(), "data" + File.separator + "season.yml"); + YamlConfiguration data = readData(file); + data.set(key, value); + try { + data.save(file); + } catch (IOException e) { + e.printStackTrace(); + AdventureManager.consoleMessage("[CustomCrops] season.yml保存出错!"); + } + }); + } + + public boolean setSeason(String worldName, String season){ + if (!ConfigReader.Config.worldNames.contains(worldName)){ + return false; + } + if (!Arrays.asList("spring","summer","autumn","winter").contains(season)){ + return false; + } + SEASON.put(worldName, season); + return true; + } +} diff --git a/src/main/java/net/momirealms/customcrops/datamanager/SprinklerManager.java b/src/main/java/net/momirealms/customcrops/datamanager/SprinklerManager.java index 52a7906..b515b78 100644 --- a/src/main/java/net/momirealms/customcrops/datamanager/SprinklerManager.java +++ b/src/main/java/net/momirealms/customcrops/datamanager/SprinklerManager.java @@ -1,153 +1,124 @@ package net.momirealms.customcrops.datamanager; import dev.lone.itemsadder.api.CustomBlock; +import net.momirealms.customcrops.utils.AdventureManager; +import net.momirealms.customcrops.ConfigReader; import net.momirealms.customcrops.CustomCrops; import net.momirealms.customcrops.utils.IAFurniture; +import net.momirealms.customcrops.utils.Sprinkler; import org.apache.commons.lang.StringUtils; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.World; -import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.MemorySection; import org.bukkit.configuration.file.YamlConfiguration; -import org.bukkit.scheduler.BukkitScheduler; import java.io.File; import java.io.IOException; -import java.util.*; import java.util.concurrent.ConcurrentHashMap; public class SprinklerManager { - static ConcurrentHashMap SPRINKLERS; - /* - 开服的时候将文件的数据读入 - */ - public static void loadData(){ + public YamlConfiguration data; + private final CustomCrops plugin; + public static ConcurrentHashMap Cache = new ConcurrentHashMap<>(); - SPRINKLERS = new ConcurrentHashMap<>(); + public SprinklerManager(CustomCrops plugin){ + this.plugin = plugin; + } - File file = new File(CustomCrops.instance.getDataFolder(), "sprinkler-data.yml"); - FileConfiguration data = YamlConfiguration.loadConfiguration(file); - - for (String world : ConfigManager.Config.worlds) { - if(data.getConfigurationSection(world) != null){ - for (String coordinate : data.getConfigurationSection(world).getKeys(false)) { - Location tempLocation = new Location(Bukkit.getWorld(world), Integer.parseInt(coordinate.split(",")[0]), Integer.parseInt(coordinate.split(",")[1]), Integer.parseInt(coordinate.split(",")[2])); - String type = data.getString(world + "." + coordinate); - SPRINKLERS.put(tempLocation, type); - } + public void loadData() { + File file = new File(CustomCrops.instance.getDataFolder(), "data" + File.separator + "sprinkler.yml"); + if(!file.exists()){ + try { + file.getParentFile().mkdirs(); + file.createNewFile(); + } catch (IOException e) { + e.printStackTrace(); + AdventureManager.consoleMessage("[CustomCrops] 洒水器数据文件生成失败!"); } } + this.data = YamlConfiguration.loadConfiguration(file); } - /* - 保存数据 - */ - public static void saveData(){ - File file = new File(CustomCrops.instance.getDataFolder(), "sprinkler-data.yml"); - FileConfiguration data = YamlConfiguration.loadConfiguration(file); - - Set> en = SPRINKLERS.entrySet(); - for(Map.Entry entry : en){ - data.set(entry.getKey().getWorld().getName() + "." + entry.getKey().getBlockX() + "," + entry.getKey().getBlockY()+ ","+entry.getKey().getBlockZ(), entry.getValue()); - } - try { + public void saveData(){ + File file = new File(CustomCrops.instance.getDataFolder(), "data" + File.separator + "sprinkler.yml"); + try{ data.save(file); - } - catch (IOException e) { + }catch (IOException e){ e.printStackTrace(); - CustomCrops.instance.getLogger().warning("洒水器数据保存出错"); + AdventureManager.consoleMessage("[CustomCrops] sprinkler.yml保存出错!"); } } - public static void putInstance(Location location, String type) { - SPRINKLERS.put(location, type); + + public void updateData(){ + Cache.forEach((location, sprinklerData) -> { + String world = location.getWorld().getName(); + int x = location.getBlockX(); + int z = location.getBlockZ(); + StringBuilder stringBuilder = new StringBuilder().append(world).append(".").append(x/16).append(",").append(z/16).append(".").append(x).append(",").append(location.getBlockY()).append(",").append(z); + data.set(stringBuilder+".range", sprinklerData.getRange()); + data.set(stringBuilder+".water", sprinklerData.getWater()); + }); + Cache.clear(); } - public static void SprinklerWork(String worldName) { - /* - 阶段1:更新数据 - */ - long start1 = System.currentTimeMillis(); - File file = new File(CustomCrops.instance.getDataFolder(), "sprinkler-data.yml"); - FileConfiguration data; - data = YamlConfiguration.loadConfiguration(file); - BukkitScheduler bukkitScheduler = Bukkit.getScheduler(); - - Set> en = SPRINKLERS.entrySet(); - for(Map.Entry entry : en){ - data.set(entry.getKey().getWorld().getName() + "." + entry.getKey().getBlockX() + "," + entry.getKey().getBlockY()+ ","+entry.getKey().getBlockZ(), entry.getValue()); + public void sprinklerWork(String worldName){ + Long time1 = System.currentTimeMillis(); + updateData(); + Long time2 = System.currentTimeMillis(); + if (ConfigReader.Config.logTime){ + AdventureManager.consoleMessage("性能监测: 洒水器数据更新" + (time2-time1) + "ms"); } - long finish1 = System.currentTimeMillis(); - if (ConfigManager.Config.log_time){ - MessageManager.consoleMessage("&#ccfbff-#ef96c5&[CustomCrops] &7洒水器数据更新耗时&a" + (finish1-start1) + "&fms",Bukkit.getConsoleSender()); - } - /* - 阶段2:清理数据内无效的洒水器并工作 - */ - bukkitScheduler.callSyncMethod(CustomCrops.instance,()->{ - long start2 = System.currentTimeMillis(); - //检测碰撞体积需要同步 - if(data.contains(worldName)){ + if (data.contains(worldName)){ + data.getConfigurationSection(worldName).getKeys(false).forEach(chunk ->{ + String[] split = StringUtils.split(chunk,","); World world = Bukkit.getWorld(worldName); - data.getConfigurationSection(worldName).getKeys(false).forEach(key ->{ - String[] coordinate = StringUtils.split(key,","); - if (world.isChunkLoaded(Integer.parseInt(coordinate[0])/16, Integer.parseInt(coordinate[2])/16)){ - Location tempLoc = new Location(world,Double.parseDouble(coordinate[0])+0.5,Double.parseDouble(coordinate[1])+0.5,Double.parseDouble(coordinate[2])+0.5); - if(!IAFurniture.getFromLocation(tempLoc, world)){ - SPRINKLERS.remove(tempLoc); - data.set(worldName+"."+coordinate[0]+","+coordinate[1]+","+coordinate[2], null); - }else { - String type = data.getString(worldName + "." + coordinate[0] + "," + coordinate[1] + "," + coordinate[2]); - if(type == null){ - MessageManager.consoleMessage("错误数据位于"+ worldName + coordinate[0] + "," + coordinate[1] + "," + coordinate[2], Bukkit.getConsoleSender()); - return; - } - if(type.equalsIgnoreCase("s1")){ - for(int i = -1; i <= 1;i++){ - for (int j = -1; j <= 1; j++){ - waterPot(tempLoc.clone().add(i,-1,j)); + if (ConfigReader.Config.onlyLoadedGrow || world.isChunkLoaded(Integer.parseInt(split[0]), Integer.parseInt(split[1]))) { + data.getConfigurationSection(worldName + "." + chunk).getValues(false).forEach((key, value) -> { + String[] coordinate = StringUtils.split(key, ","); + Location location = new Location(world,Double.parseDouble(coordinate[0])+0.5,Double.parseDouble(coordinate[1])+0.5,Double.parseDouble(coordinate[2])+0.5); + if (value instanceof MemorySection map){ + Bukkit.getScheduler().callSyncMethod(CustomCrops.instance, ()->{ + int water = (int) map.get("water"); + int range = (int) map.get("range"); + if(!IAFurniture.getFromLocation(location, world)){ + data.set(worldName + "." + chunk + "." + key, null); + return null; + } + if (range == 0) data.set(worldName + "." + chunk + "." + key, null); + if (water > 0){ + data.set(worldName + "." + chunk + "." + key + ".water", water - 1); + for(int i = -range; i <= range; i++){ + for (int j = -range; j <= range; j++){ + waterPot(location.clone().add(i,-1,j)); + } } } - }else{ - for(int i = -2; i <= 2;i++){ - for (int j = -2; j <= 2; j++){ - waterPot(tempLoc.clone().add(i,-1,j)); - } - } - } + return null; + }); } - } - }); - } - long finish2 = System.currentTimeMillis(); - if (ConfigManager.Config.log_time){ - MessageManager.consoleMessage("&#ccfbff-#ef96c5&[CustomCrops] &7洒水器工作耗时&a" + (finish2-start2) + "&fms",Bukkit.getConsoleSender()); - } - bukkitScheduler.runTaskAsynchronously(CustomCrops.instance,()->{ - /* - 阶段3:保存数据 - */ - long start3 = System.currentTimeMillis(); - try{ - data.save(file); - }catch (IOException e){ - e.printStackTrace(); - CustomCrops.instance.getLogger().warning("sprinkler-data.yml保存出错!"); - } - long finish3 = System.currentTimeMillis(); - if (ConfigManager.Config.log_time){ - MessageManager.consoleMessage("&#ccfbff-#ef96c5&[CustomCrops] &7洒水器数据保存耗时&a" + (finish3-start3) + "&fms",Bukkit.getConsoleSender()); + }); } }); - return null; - }); + } + Long time3 = System.currentTimeMillis(); + if(ConfigReader.Config.logTime){ + AdventureManager.consoleMessage("性能监测: 洒水器工作过程" + (time3-time2) + "ms"); + } + saveData(); + Long time4 = System.currentTimeMillis(); + if(ConfigReader.Config.logTime){ + AdventureManager.consoleMessage("性能监测: 洒水器数据保存" + (time4-time3) + "ms"); + } } - private static void waterPot(Location tempLoc) { - CustomBlock cb = CustomBlock.byAlreadyPlaced(tempLoc.getBlock()); + + private void waterPot(Location potLoc) { + CustomBlock cb = CustomBlock.byAlreadyPlaced(potLoc.getBlock()); if(cb != null){ - if(cb.getNamespacedID().equalsIgnoreCase(ConfigManager.Config.pot)){ - CustomBlock.remove(tempLoc); - CustomBlock.place((ConfigManager.Config.watered_pot), tempLoc); + if(cb.getNamespacedID().equals(ConfigReader.Basic.pot)){ + CustomBlock.remove(potLoc); + CustomBlock.place(ConfigReader.Basic.watered_pot, potLoc); } } } diff --git a/src/main/java/net/momirealms/customcrops/fertilizer/Fertilizer.java b/src/main/java/net/momirealms/customcrops/fertilizer/Fertilizer.java new file mode 100644 index 0000000..e08b836 --- /dev/null +++ b/src/main/java/net/momirealms/customcrops/fertilizer/Fertilizer.java @@ -0,0 +1,9 @@ +package net.momirealms.customcrops.fertilizer; + +public interface Fertilizer { + String getKey(); + int getTimes(); + void setTimes(int times); + boolean isBefore(); + String getName(); +} diff --git a/src/main/java/net/momirealms/customcrops/fertilizer/QualityCrop.java b/src/main/java/net/momirealms/customcrops/fertilizer/QualityCrop.java new file mode 100644 index 0000000..cf354b7 --- /dev/null +++ b/src/main/java/net/momirealms/customcrops/fertilizer/QualityCrop.java @@ -0,0 +1,58 @@ +package net.momirealms.customcrops.fertilizer; + +public class QualityCrop implements Fertilizer{ + + private int[] chance; + private String key; + private int times; + private boolean before; + private String name; + + public QualityCrop(String key, int times, int[] chance, boolean before) { + this.chance = chance; + this.times = times; + this.before = before; + this.key = key; + } + + @Override + public String getKey() { + return this.key; + } + + @Override + public int getTimes() { + return this.times; + } + + @Override + public void setTimes(int times) { + this.times = times; + } + + @Override + public boolean isBefore() { + return this.before; + } + + @Override + public String getName() { + return this.name; + } + + public void setName(String name) { + this.name = name; + } + + public void setChance(int[] chance) { + this.chance = chance; + } + + public void setKey(String key) { + this.key = key; + } + + public int[] getChance() { + return chance; + } +} diff --git a/src/main/java/net/momirealms/customcrops/fertilizer/RetainingSoil.java b/src/main/java/net/momirealms/customcrops/fertilizer/RetainingSoil.java new file mode 100644 index 0000000..3168cc6 --- /dev/null +++ b/src/main/java/net/momirealms/customcrops/fertilizer/RetainingSoil.java @@ -0,0 +1,58 @@ +package net.momirealms.customcrops.fertilizer; + +public class RetainingSoil implements Fertilizer{ + + private double chance; + private String key; + private int times; + private boolean before; + public String name; + + public RetainingSoil(String key, int times, double chance, boolean before){ + this.times = times; + this.chance = chance; + this.before = before; + this.key = key; + } + + @Override + public String getKey() { + return this.key; + } + + @Override + public int getTimes() { + return this.times; + } + + @Override + public void setTimes(int times) { + this.times = times; + } + + @Override + public boolean isBefore() { + return this.before; + } + + @Override + public String getName() { + return this.name; + } + + public void setName(String name) { + this.name = name; + } + + public void setChance(double chance) { + this.chance = chance; + } + + public void setKey(String key) { + this.key = key; + } + + public double getChance() { + return chance; + } +} diff --git a/src/main/java/net/momirealms/customcrops/fertilizer/SpeedGrow.java b/src/main/java/net/momirealms/customcrops/fertilizer/SpeedGrow.java new file mode 100644 index 0000000..8bcde54 --- /dev/null +++ b/src/main/java/net/momirealms/customcrops/fertilizer/SpeedGrow.java @@ -0,0 +1,58 @@ +package net.momirealms.customcrops.fertilizer; + +public class SpeedGrow implements Fertilizer{ + + private double chance; + private String key; + private int times; + private boolean before; + private String name; + + public SpeedGrow(String key, int times, double chance, boolean before){ + this.chance = chance; + this.times = times; + this.before = before; + this.key = key; + } + + @Override + public String getKey() { + return this.key; + } + + @Override + public int getTimes() { + return this.times; + } + + @Override + public void setTimes(int times) { + this.times = times; + } + + @Override + public boolean isBefore() { + return this.before; + } + + @Override + public String getName() { + return this.name; + } + + public void setName(String name) { + this.name = name; + } + + public double getChance() { + return chance; + } + + public void setChance(double chance) { + this.chance = chance; + } + + public void setKey(String key) { + this.key = key; + } +} diff --git a/src/main/java/net/momirealms/customcrops/integrations/GriefDefender.java b/src/main/java/net/momirealms/customcrops/integrations/GriefDefender.java new file mode 100644 index 0000000..b24eb7e --- /dev/null +++ b/src/main/java/net/momirealms/customcrops/integrations/GriefDefender.java @@ -0,0 +1,17 @@ +package net.momirealms.customcrops.integrations; + +import org.bukkit.Location; +import org.bukkit.entity.Player; + +public record GriefDefender() implements Integration { + + @Override + public boolean canBreak(Location location, Player player) { + return com.griefdefender.api.GriefDefender.getCore().getUser(player.getUniqueId()).canBreak(location); + } + + @Override + public boolean canPlace(Location location, Player player) { + return com.griefdefender.api.GriefDefender.getCore().getUser(player.getUniqueId()).canPlace(player.getInventory().getItemInMainHand(), location); + } +} diff --git a/src/main/java/net/momirealms/customcrops/integrations/GriefDefenderIntegrations.java b/src/main/java/net/momirealms/customcrops/integrations/GriefDefenderIntegrations.java deleted file mode 100644 index 709ac8a..0000000 --- a/src/main/java/net/momirealms/customcrops/integrations/GriefDefenderIntegrations.java +++ /dev/null @@ -1,16 +0,0 @@ -package net.momirealms.customcrops.integrations; - -import com.griefdefender.api.GriefDefender; -import org.bukkit.Location; -import org.bukkit.entity.Player; - -public class GriefDefenderIntegrations { - - public static boolean checkGDBreak(Location location, Player player){ - return GriefDefender.getCore().getUser(player.getUniqueId()).canBreak(location); - } - - public static boolean checkGDBuild(Location location, Player player){ - return GriefDefender.getCore().getUser(player.getUniqueId()).canPlace(player.getInventory().getItemInMainHand(), location); - } -} diff --git a/src/main/java/net/momirealms/customcrops/integrations/Integration.java b/src/main/java/net/momirealms/customcrops/integrations/Integration.java new file mode 100644 index 0000000..8fcccde --- /dev/null +++ b/src/main/java/net/momirealms/customcrops/integrations/Integration.java @@ -0,0 +1,9 @@ +package net.momirealms.customcrops.integrations; + +import org.bukkit.Location; +import org.bukkit.entity.Player; + +public interface Integration { + boolean canBreak(Location location, Player player); + boolean canPlace(Location location, Player player); +} diff --git a/src/main/java/net/momirealms/customcrops/integrations/IntegrationCheck.java b/src/main/java/net/momirealms/customcrops/integrations/IntegrationCheck.java deleted file mode 100644 index 843d915..0000000 --- a/src/main/java/net/momirealms/customcrops/integrations/IntegrationCheck.java +++ /dev/null @@ -1,57 +0,0 @@ -package net.momirealms.customcrops.integrations; - -import net.momirealms.customcrops.datamanager.ConfigManager; -import org.bukkit.Location; -import org.bukkit.entity.Player; - -public class IntegrationCheck { - - //收获权限检测 - public static boolean HarvestCheck(Location location, Player player){ - if(ConfigManager.Config.res){ - if(!ResidenceIntegrations.checkResHarvest(location, player)){ - return false; - } - } - if(ConfigManager.Config.king){ - if(!KingdomsXIntegrations.checkKDBuild(location, player)){ - return false; - } - } - if(ConfigManager.Config.wg){ - if(!WorldGuardIntegrations.checkWGHarvest(location, player)){ - return false; - } - } - if(ConfigManager.Config.gd){ - if(!GriefDefenderIntegrations.checkGDBreak(location, player)){ - return false; - } - } - return true; - } - //种植等权限检测 - public static boolean PlaceCheck(Location location, Player player){ - if(ConfigManager.Config.res){ - if(!ResidenceIntegrations.checkResBuild(location,player)){ - return false; - } - } - if(ConfigManager.Config.king){ - if(!KingdomsXIntegrations.checkKDBuild(location,player)){ - return false; - } - } - if(ConfigManager.Config.wg){ - if(!WorldGuardIntegrations.checkWGBuild(location, player)){ - return false; - } - } - if(ConfigManager.Config.gd){ - if(!GriefDefenderIntegrations.checkGDBuild(location, player)){ - return false; - } - } - return true; - } -} \ No newline at end of file diff --git a/src/main/java/net/momirealms/customcrops/integrations/KingdomsXIntegrations.java b/src/main/java/net/momirealms/customcrops/integrations/KingdomsX.java similarity index 63% rename from src/main/java/net/momirealms/customcrops/integrations/KingdomsXIntegrations.java rename to src/main/java/net/momirealms/customcrops/integrations/KingdomsX.java index 8f01ad9..a7f6c5e 100644 --- a/src/main/java/net/momirealms/customcrops/integrations/KingdomsXIntegrations.java +++ b/src/main/java/net/momirealms/customcrops/integrations/KingdomsX.java @@ -6,8 +6,19 @@ import org.kingdoms.constants.group.Kingdom; import org.kingdoms.constants.land.Land; import org.kingdoms.constants.player.KingdomPlayer; -public class KingdomsXIntegrations { - public static boolean checkKDBuild(Location location, Player player){ +public record KingdomsX() implements Integration { + + @Override + public boolean canBreak(Location location, Player player) { + return kingdomsCheck(location, player); + } + + @Override + public boolean canPlace(Location location, Player player) { + return kingdomsCheck(location, player); + } + + private boolean kingdomsCheck(Location location, Player player) { Land land = Land.getLand(location); if (land == null) return true; if (land.isClaimed()) { @@ -16,7 +27,7 @@ public class KingdomsXIntegrations { if (kp.getKingdom() != null) { Kingdom kingdom = kp.getKingdom(); return kingdom != cropKingdom; - }else { + } else { return false; } } diff --git a/src/main/java/net/momirealms/customcrops/integrations/ResidenceIntegrations.java b/src/main/java/net/momirealms/customcrops/integrations/Residence.java similarity index 81% rename from src/main/java/net/momirealms/customcrops/integrations/ResidenceIntegrations.java rename to src/main/java/net/momirealms/customcrops/integrations/Residence.java index f3bad98..90f7640 100644 --- a/src/main/java/net/momirealms/customcrops/integrations/ResidenceIntegrations.java +++ b/src/main/java/net/momirealms/customcrops/integrations/Residence.java @@ -6,8 +6,10 @@ import com.bekvon.bukkit.residence.protection.ResidencePermissions; import org.bukkit.Location; import org.bukkit.entity.Player; -public class ResidenceIntegrations { - public static boolean checkResBuild(Location location, Player player){ +public record Residence() implements Integration { + + @Override + public boolean canBreak(Location location, Player player) { ClaimedResidence res = com.bekvon.bukkit.residence.Residence.getInstance().getResidenceManager().getByLoc(location); if(res!=null){ ResidencePermissions perms = res.getPermissions(); @@ -15,7 +17,9 @@ public class ResidenceIntegrations { } return true; } - public static boolean checkResHarvest(Location location, Player player){ + + @Override + public boolean canPlace(Location location, Player player) { ClaimedResidence res = com.bekvon.bukkit.residence.Residence.getInstance().getResidenceManager().getByLoc(location); if(res!=null){ ResidencePermissions perms = res.getPermissions(); diff --git a/src/main/java/net/momirealms/customcrops/integrations/WorldGuard.java b/src/main/java/net/momirealms/customcrops/integrations/WorldGuard.java new file mode 100644 index 0000000..5c3fe53 --- /dev/null +++ b/src/main/java/net/momirealms/customcrops/integrations/WorldGuard.java @@ -0,0 +1,42 @@ +package net.momirealms.customcrops.integrations; + +import com.sk89q.worldedit.bukkit.BukkitAdapter; +import com.sk89q.worldguard.LocalPlayer; +import com.sk89q.worldguard.bukkit.WorldGuardPlugin; +import com.sk89q.worldguard.protection.ApplicableRegionSet; +import com.sk89q.worldguard.protection.flags.Flags; +import com.sk89q.worldguard.protection.regions.RegionContainer; +import com.sk89q.worldguard.protection.regions.RegionQuery; +import org.bukkit.Location; +import org.bukkit.entity.Player; + +public record WorldGuard() implements Integration { + + @Override + public boolean canPlace(Location location, Player player) { + LocalPlayer localPlayer = WorldGuardPlugin.inst().wrapPlayer(player); + RegionContainer container = com.sk89q.worldguard.WorldGuard.getInstance().getPlatform().getRegionContainer(); + RegionQuery query = container.createQuery(); + ApplicableRegionSet set = query.getApplicableRegions(BukkitAdapter.adapt(location)); + if (set != null){ + System.out.println(set); + return query.testState(BukkitAdapter.adapt(location), localPlayer, Flags.BUILD); + }else { + return true; + } + } + + @Override + public boolean canBreak(Location location, Player player) { + LocalPlayer localPlayer = WorldGuardPlugin.inst().wrapPlayer(player); + RegionContainer container = com.sk89q.worldguard.WorldGuard.getInstance().getPlatform().getRegionContainer(); + RegionQuery query = container.createQuery(); + ApplicableRegionSet set = query.getApplicableRegions(BukkitAdapter.adapt(location)); + if (set != null){ + System.out.println(set); + return query.testState(BukkitAdapter.adapt(location), localPlayer, Flags.BLOCK_BREAK); + }else { + return true; + } + } +} \ No newline at end of file diff --git a/src/main/java/net/momirealms/customcrops/integrations/WorldGuardIntegrations.java b/src/main/java/net/momirealms/customcrops/integrations/WorldGuardIntegrations.java deleted file mode 100644 index fc415e8..0000000 --- a/src/main/java/net/momirealms/customcrops/integrations/WorldGuardIntegrations.java +++ /dev/null @@ -1,26 +0,0 @@ -package net.momirealms.customcrops.integrations; - -import com.sk89q.worldedit.bukkit.BukkitAdapter; -import com.sk89q.worldguard.LocalPlayer; -import com.sk89q.worldguard.WorldGuard; -import com.sk89q.worldguard.bukkit.WorldGuardPlugin; -import com.sk89q.worldguard.protection.flags.Flags; -import com.sk89q.worldguard.protection.regions.RegionContainer; -import com.sk89q.worldguard.protection.regions.RegionQuery; -import org.bukkit.Location; -import org.bukkit.entity.Player; - -public class WorldGuardIntegrations { - public static boolean checkWGBuild(Location loc,Player player){ - LocalPlayer localPlayer = WorldGuardPlugin.inst().wrapPlayer(player); - RegionContainer container = WorldGuard.getInstance().getPlatform().getRegionContainer(); - RegionQuery query = container.createQuery(); - return query.testState(BukkitAdapter.adapt(loc), localPlayer, Flags.BUILD); - } - public static boolean checkWGHarvest(Location loc,Player player){ - LocalPlayer localPlayer = WorldGuardPlugin.inst().wrapPlayer(player); - RegionContainer container = WorldGuard.getInstance().getPlatform().getRegionContainer(); - RegionQuery query = container.createQuery(); - return query.testState(BukkitAdapter.adapt(loc), localPlayer, Flags.BLOCK_BREAK); - } -} \ No newline at end of file diff --git a/src/main/java/net/momirealms/customcrops/libs/minedown/MineDown.java b/src/main/java/net/momirealms/customcrops/libs/minedown/MineDown.java deleted file mode 100644 index 1e991aa..0000000 --- a/src/main/java/net/momirealms/customcrops/libs/minedown/MineDown.java +++ /dev/null @@ -1,499 +0,0 @@ -package net.momirealms.customcrops.libs.minedown; - -/* - * Copyright (c) 2017 Max Lee (https://github.com/Phoenix616) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -import net.md_5.bungee.api.ChatColor; -import net.md_5.bungee.api.chat.BaseComponent; -import net.md_5.bungee.api.chat.ClickEvent; -import net.md_5.bungee.api.chat.HoverEvent; - -import java.util.Map; - -/** - *

MineDown

- * A MarkDown inspired markup for Minecraft chat components - *

- * This lets you convert string messages into chat components by using a custom mark up syntax - * which is loosely based on MarkDown while still supporting legacy formatting codes. - * - * - * - * - * - * - * - * - * - * - * - * - *
Inline Formatting
Color legacy &6Text {@link ChatColor} codes
Color &gold&Text {@link ChatColor} codes
RGB Hex Color &ff00ff&Text Full hexadecimal format
RGB Hex Color &f0f&Text Short format (equivalent to long one)
Bold **Text**
Italic ##Text##
Underlined __Text__
Strikethrough ~~Text~~
Obfuscated ??Text??
- * - *

Events

- * You can define click and hover events with the commonly used MarkDown link syntax. - *

- * - * - * - * - * - * - * - *
Simple Syntax
General syntax [Text](text-color text-formatting... link hover text)
Simple Link [Text](https://example.com)
Simple Command [Text](/command to run)
Link + Hover [Text](https://example.com Hover Text)
Text formatting + Link + Hover [Text](blue underline https://example.com Hover Text)
- *

- * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
Advanced Syntax
General syntax [Text](action=value) {@link ClickEvent.Action}, {@link HoverEvent.Action}
Link [Text](open_url=https://example.com)
Color [Text](color=red)
RGB Hex Color [Text](color=#ff00ff) Full hexadecimal format
RGB Hex Color [Text](color=#f0f) Short format (equivalent to long one)
Formatting [Text](format=underline,bold)
Font [Text](format=underline,bold)
Run Command [Text](run_command=/command string)
Suggest Command [Text](suggest_command=/command)
Simple Hover [Text](hover=Hover Text)
Hover Text [Text](show_text=Hover Text)
Hover Entity Info [Text](show_entity=uuid:pig Name)
Hover Item Info [Text](show_item=stone*2 nbt...)
- *

- * All advanced settings can be chained/included in a event definition. - * You can't however add multiple different colors or click and hover actions! - */ -public class MineDown { - public static final String FONT_PREFIX = "font="; - public static final String COLOR_PREFIX = "color="; - public static final String FORMAT_PREFIX = "format="; - public static final String HOVER_PREFIX = "hover="; - public static final String INSERTION_PREFIX = "insert="; - - private String message; - private final Replacer replacer = new Replacer(); - private final MineDownParser parser = new MineDownParser(); - private BaseComponent[] baseComponents = null; - private boolean replaceFirst = Boolean.getBoolean("de.themoep.minedown.replacefirst"); - - /** - * Create a new MineDown builder with a certain message - * @param message The message to parse - */ - public MineDown(String message) { - this.message = message; - } - - /** - * Parse a MineDown string to components - * @param message The message to translate - * @param replacements Optional placeholder replacements - * @return The parsed components - */ - public static BaseComponent[] parse(String message, String... replacements) { - return new MineDown(message).replace(replacements).toComponent(); - } - - /** - * Convert components to a MineDown string - * @param components The components to convert - * @return The components represented as a MineDown string - */ - public static String stringify(BaseComponent[] components) { - return new MineDownStringifier().stringify(components); - } - - /** - * Parse and convert the message to the component - * @return The parsed component message - */ - public BaseComponent[] toComponent() { - if (baseComponents() == null) { - if (replaceFirst()) { - Replacer componentReplacer = new Replacer(); - for (Map.Entry entry : replacer().componentReplacements().entrySet()) { - componentReplacer.replace(entry.getKey(), stringify(entry.getValue())); - } - baseComponents = parser().parse(componentReplacer.replaceIn(replacer().replaceIn(message()))).create(); - } else { - baseComponents = replacer().replaceIn(parser().parse(message()).create()); - } - } - return baseComponents(); - } - - /** - * Remove a cached component and re-parse the next time {@link #toComponent} is called - */ - private void reset() { - baseComponents = null; - } - - /** - * Set whether or not replacements should be replaced before or after the components are created. - * When replacing first it will not replace any placeholders with component replacement values! - * Default is after. (replaceFirst = false) - * @param replaceFirst Whether or not to replace first or parse first - * @return The MineDown instance - */ - public MineDown replaceFirst(boolean replaceFirst) { - reset(); - this.replaceFirst = replaceFirst; - return this; - } - - /** - * Get whether or not replacements should be replaced before or after the components are created. - * When replacing first it will not replace any placeholders with component replacement values! - * Default is after. (replaceFirst = false) - * @return Whether or not to replace first or parse first - */ - public boolean replaceFirst() { - return replaceFirst; - } - - /** - * Add an array with placeholders and values that should get replaced in the message - * @param replacements The replacements, nth element is the placeholder, n+1th the value - * @return The MineDown instance - */ - public MineDown replace(String... replacements) { - reset(); - replacer().replace(replacements); - return this; - } - - /** - * Add a map with placeholders and values that should get replaced in the message - * @param replacements The replacements mapped placeholder to value - * @return The MineDown instance - */ - public MineDown replace(Map replacements) { - reset(); - replacer().replace(replacements); - return this; - } - - /** - * Add a placeholder to component mapping that should get replaced in the message - * @param placeholder The placeholder to replace - * @param replacement The replacement components - * @return The Replacer instance - */ - public MineDown replace(String placeholder, BaseComponent... replacement) { - reset(); - replacer().replace(placeholder,replacement); - return this; - } - - /** - * Set the placeholder indicator for both prefix and suffix - * @param placeholderIndicator The character to use as a placeholder indicator - * @return The MineDown instance - */ - public MineDown placeholderIndicator(String placeholderIndicator) { - placeholderPrefix(placeholderIndicator); - placeholderSuffix(placeholderIndicator); - return this; - } - - /** - * Set the placeholder indicator's prefix character - * @param placeholderPrefix The character to use as the placeholder indicator's prefix - * @return The MineDown instance - */ - public MineDown placeholderPrefix(String placeholderPrefix) { - reset(); - replacer().placeholderPrefix(placeholderPrefix); - return this; - } - - /** - * Get the placeholder indicator's prefix character - * @return The placeholder indicator's prefix character - */ - public String placeholderPrefix() { - return replacer().placeholderPrefix(); - } - - /** - * Set the placeholder indicator's suffix character - * @param placeholderSuffix The character to use as the placeholder indicator's suffix - * @return The MineDown instance - */ - public MineDown placeholderSuffix(String placeholderSuffix) { - reset(); - replacer().placeholderSuffix(placeholderSuffix); - return this; - } - - /** - * Get the placeholder indicator's suffix character - * @return The placeholder indicator's suffix character - */ - public String placeholderSuffix() { - return replacer().placeholderSuffix(); - } - - /** - * Set whether or not the case of the placeholder should be ignored when replacing - * @param ignorePlaceholderCase Whether or not to ignore the case of the placeholders - * @return The MineDown instance - */ - public MineDown ignorePlaceholderCase(boolean ignorePlaceholderCase) { - reset(); - replacer().ignorePlaceholderCase(ignorePlaceholderCase); - return this; - } - - /** - * Get whether or not the case of the placeholder should be ignored when replacing - * @return Whether or not to ignore the case of the placeholders - */ - public boolean ignorePlaceholderCase() { - return replacer().ignorePlaceholderCase(); - } - - /** - * Enable or disable the translation of legacy color codes - * @param translateLegacyColors Whether or not to translate legacy color codes (Default: true) - * @return The MineDown instance - * @deprecated Use {@link #enable(MineDownParser.Option)} and {@link #disable(MineDownParser.Option)} - */ - @Deprecated - public MineDown translateLegacyColors(boolean translateLegacyColors) { - reset(); - parser().translateLegacyColors(translateLegacyColors); - return this; - } - - /** - * Detect urls in strings and add events to them? (Default: true) - * @param enabled Whether or not to detect URLs and add events to them - * @return The MineDown instance - */ - public MineDown urlDetection(boolean enabled) { - reset(); - parser().urlDetection(enabled); - return this; - } - - /** - * Automatically add http to values of open_url when there doesn't exist any? (Default: true) - * @param enabled Whether or not to automatically add http when missing - * @return The MineDown instance - */ - public MineDown autoAddUrlPrefix(boolean enabled) { - reset(); - parser().autoAddUrlPrefix(enabled); - return this; - } - - /** - * The text to display when hovering over an URL - * @param text The text to display when hovering over an URL - * @return The MineDown instance - */ - public MineDown urlHoverText(String text) { - reset(); - parser().urlHoverText(text); - return this; - } - - /** - * Set the max width the hover text should have. - * Minecraft itself will wrap after 60 characters. - * Won't apply if the text already includes new lines. - * @param hoverTextWidth The url hover text length - * @return The MineDown instance - */ - public MineDown hoverTextWidth(int hoverTextWidth) { - reset(); - parser().hoverTextWidth(hoverTextWidth); - return this; - } - - /** - * Enable an option. Unfilter it if you filtered it before. - * @param option The option to enable - * @return The MineDown instance - */ - public MineDown enable(MineDownParser.Option option) { - reset(); - parser().enable(option); - return this; - } - - /** - * Disable an option. Disabling an option will stop the parser from replacing - * this option's chars in the string. Use {@link #filter(MineDownParser.Option)} to completely - * remove the characters used by this option from the message instead. - * @param option The option to disable - * @return The MineDown instance - */ - public MineDown disable(MineDownParser.Option option) { - reset(); - parser().disable(option); - return this; - } - - /** - * Filter an option. This completely removes the characters of this option from - * the string ignoring whether the option is enabled or not. - * @param option The option to add to the filter - * @return The MineDown instance - */ - public MineDown filter(MineDownParser.Option option) { - reset(); - parser().filter(option); - return this; - } - - /** - * Unfilter an option. Does not enable it! - * @param option The option to remove from the filter - * @return The MineDown instance - */ - public MineDown unfilter(MineDownParser.Option option) { - reset(); - parser().unfilter(option); - return this; - } - - /** - * Set a special character to replace color codes by if translating legacy colors is enabled. - * @param colorChar The character to use as a special color code. (Default: ampersand &) - * @return The MineDown instance - */ - public MineDown colorChar(char colorChar) { - reset(); - parser().colorChar(colorChar); - return this; - } - - /** - * Get the set message that is to be parsed - * @return The to be parsed message - */ - public String message() { - return this.message; - } - - /** - * Set the message that is to be parsed - * @param message The message to be parsed - * @return The MineDown instance - */ - public MineDown message(String message) { - this.message = message; - reset(); - return this; - } - - /** - * Get the replacer instance that is currently used - * @return The currently used replacer instance - */ - public Replacer replacer() { - return this.replacer; - } - - /** - * Get the parser instance that is currently used - * @return The currently used parser instance - */ - public MineDownParser parser() { - return this.parser; - } - - protected BaseComponent[] baseComponents() { - return this.baseComponents; - } - - /** - * Copy all MineDown settings to a new instance - * @return The new MineDown instance with all settings copied - */ - public MineDown copy() { - return new MineDown(message()).copy(this); - } - - /** - * Copy all MineDown settings from another one - * @param from The MineDown to copy from - * @return This MineDown instance - */ - public MineDown copy(MineDown from) { - replacer().copy(from.replacer()); - parser().copy(from.parser()); - return this; - } - - /** - * Get the string that represents the format in MineDown - * @param format The format - * @return The MineDown string or an empty one if it's not a format - */ - public static String getFormatString(ChatColor format) { - if (format == ChatColor.BOLD) { - return "**"; - } else if (format == ChatColor.ITALIC) { - return "##"; - } else if (format == ChatColor.UNDERLINE) { - return "__"; - } else if (format == ChatColor.STRIKETHROUGH) { - return "~~"; - } else if (format == ChatColor.MAGIC) { - return "??"; - } - return ""; - } - - /** - * Get the ChatColor format from a MineDown string - * @param c The character - * @return The ChatColor of that format or null it none was found - */ - public static ChatColor getFormatFromChar(char c) { - switch (c) { - case '~': - return ChatColor.STRIKETHROUGH; - case '_': - return ChatColor.UNDERLINE; - case '*': - return ChatColor.BOLD; - case '#': - return ChatColor.ITALIC; - case '?': - return ChatColor.MAGIC; - } - return null; - } - - /** - * Escape all MineDown formatting in a string. This will escape backslashes too! - * @param string The string to escape in - * @return The string with formatting escaped - */ - public static String escape(String string) { - return new MineDown(string).parser().escape(string); - } -} diff --git a/src/main/java/net/momirealms/customcrops/libs/minedown/MineDownParser.java b/src/main/java/net/momirealms/customcrops/libs/minedown/MineDownParser.java deleted file mode 100644 index 7dc51fe..0000000 --- a/src/main/java/net/momirealms/customcrops/libs/minedown/MineDownParser.java +++ /dev/null @@ -1,1241 +0,0 @@ -package net.momirealms.customcrops.libs.minedown; - -/* - * Copyright (c) 2017 Max Lee (https://github.com/Phoenix616) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -import net.md_5.bungee.api.ChatColor; -import net.md_5.bungee.api.chat.BaseComponent; -import net.md_5.bungee.api.chat.ClickEvent; -import net.md_5.bungee.api.chat.ComponentBuilder; -import net.md_5.bungee.api.chat.HoverEvent; -import net.md_5.bungee.api.chat.ItemTag; -import net.md_5.bungee.api.chat.TextComponent; -import net.md_5.bungee.api.chat.hover.content.Entity; -import net.md_5.bungee.api.chat.hover.content.Item; -import net.md_5.bungee.api.chat.hover.content.Text; - -import java.awt.Color; -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.Collections; -import java.util.EnumSet; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.PrimitiveIterator; -import java.util.Set; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Collectors; - -import static net.momirealms.customcrops.libs.minedown.MineDown.COLOR_PREFIX; -import static net.momirealms.customcrops.libs.minedown.MineDown.FONT_PREFIX; -import static net.momirealms.customcrops.libs.minedown.MineDown.FORMAT_PREFIX; -import static net.momirealms.customcrops.libs.minedown.MineDown.HOVER_PREFIX; -import static net.momirealms.customcrops.libs.minedown.MineDown.INSERTION_PREFIX; - -public class MineDownParser { - private static final String RAINBOW = "rainbow"; - - private static final boolean HAS_APPEND_SUPPORT = Util.hasMethod(ComponentBuilder.class, "append", BaseComponent[].class); - private static final boolean HAS_RGB_SUPPORT = Util.hasMethod(ChatColor.class, "of", String.class); - private static final boolean HAS_FONT_SUPPORT = Util.hasMethod(ComponentBuilder.class, "font", String.class); - private static final boolean HAS_INSERTION_SUPPORT = Util.hasMethod(ComponentBuilder.class, "insertion", String.class); - private static final boolean HAS_HOVER_CONTENT_SUPPORT = Util.hasMethod(HoverEvent.class, "getContents"); - - /** - * The character to use as a special color code. (Default: ampersand &) - */ - private char colorChar = '&'; - - /** - * All enabled options - */ - private Set