9
0
mirror of https://github.com/Xiao-MoMi/Custom-Crops.git synced 2025-12-22 16:39:36 +00:00

1.5.9-SNAPSHOT

This commit is contained in:
Xiao-MoMi
2022-07-14 19:48:37 +08:00
parent 213e3ab178
commit 10f2479449
21 changed files with 870 additions and 85 deletions

View File

@@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

View File

@@ -13,7 +13,6 @@ import net.momirealms.customcrops.requirements.YPos;
import net.momirealms.customcrops.utils.*; import net.momirealms.customcrops.utils.*;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Sound;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.configuration.file.YamlConfiguration;
@@ -53,11 +52,6 @@ public class ConfigReader {
public static List<Long> cropGrowTimeList; public static List<Long> cropGrowTimeList;
public static List<Integration> integration; public static List<Integration> integration;
public static boolean asyncCheck; 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 boolean enableLimit;
public static int cropLimit; public static int cropLimit;
public static int sprinklerLimit; public static int sprinklerLimit;
@@ -71,6 +65,7 @@ public class ConfigReader {
public static boolean onlyLoadedGrow; public static boolean onlyLoadedGrow;
public static boolean quality; public static boolean quality;
public static boolean canAddWater; public static boolean canAddWater;
public static boolean allWorld;
public static double quality_1; public static double quality_1;
public static double quality_2; public static double quality_2;
@@ -92,19 +87,10 @@ public class ConfigReader {
timeToGrow = config.getInt("config.time-to-grow",60)*20; timeToGrow = config.getInt("config.time-to-grow",60)*20;
timeToWork = config.getInt("config.time-to-work",30)*20; timeToWork = config.getInt("config.time-to-work",30)*20;
//异步读取时间
asyncCheck = config.getBoolean("config.async-time-check",false); asyncCheck = config.getBoolean("config.async-time-check",false);
logTime = config.getBoolean("config.log-time-consume",false); logTime = config.getBoolean("config.log-time-consume",false);
onlyLoadedGrow = !config.getBoolean("config.only-grow-in-loaded-chunks",true); onlyLoadedGrow = !config.getBoolean("config.only-grow-in-loaded-chunks",true);
allWorld = config.getBoolean("config.all-world-grow",false);
//骨粉设置(已废弃)
// 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); enableLimit = config.getBoolean("config.limit.enable",true);
@@ -121,7 +107,7 @@ public class ConfigReader {
yMax = 320; yMax = 320;
} }
//农作物品质处理 //农作物品质
quality = config.getBoolean("config.quality.enable",true); quality = config.getBoolean("config.quality.enable",true);
if (quality){ if (quality){
String[] split = StringUtils.split(config.getString("config.quality.default-ratio","17/2/1"), "/"); String[] split = StringUtils.split(config.getString("config.quality.default-ratio","17/2/1"), "/");

View File

@@ -4,6 +4,7 @@ import net.kyori.adventure.platform.bukkit.BukkitAudiences;
import net.momirealms.customcrops.commands.Executor; import net.momirealms.customcrops.commands.Executor;
import net.momirealms.customcrops.commands.Completer; import net.momirealms.customcrops.commands.Completer;
import net.momirealms.customcrops.datamanager.*; import net.momirealms.customcrops.datamanager.*;
import net.momirealms.customcrops.helper.LibraryLoader;
import net.momirealms.customcrops.listener.BreakBlock; import net.momirealms.customcrops.listener.BreakBlock;
import net.momirealms.customcrops.listener.InteractEntity; import net.momirealms.customcrops.listener.InteractEntity;
import net.momirealms.customcrops.listener.ItemSpawn; import net.momirealms.customcrops.listener.ItemSpawn;
@@ -31,10 +32,25 @@ public final class CustomCrops extends JavaPlugin {
private PotManager potManager; private PotManager potManager;
@Override @Override
public void onEnable() { public void onLoad(){
instance = this; instance = this;
adventure = BukkitAudiences.create(this); LibraryLoader.load("net.kyori","adventure-api","4.11.0","https://oss.sonatype.org/content/groups/public");
LibraryLoader.load("net.kyori","adventure-platform-api","4.1.1","https://oss.sonatype.org/content/groups/public");
LibraryLoader.load("net.kyori","adventure-platform-bukkit","4.1.1","https://oss.sonatype.org/content/groups/public");
LibraryLoader.load("net.kyori","adventure-platform-facet","4.1.1","https://oss.sonatype.org/content/groups/public");
LibraryLoader.load("net.kyori","adventure-text-minimessage","4.10.1","https://oss.sonatype.org/content/groups/public");
LibraryLoader.load("net.kyori","adventure-text-serializer-gson","4.11.0","https://oss.sonatype.org/content/groups/public");
LibraryLoader.load("net.kyori","adventure-text-serializer-plain","4.11.0","https://oss.sonatype.org/content/groups/public");
LibraryLoader.load("net.kyori","adventure-text-serializer-gson-legacy-impl","4.11.0","https://oss.sonatype.org/content/groups/public");
LibraryLoader.load("net.kyori","adventure-nbt","4.11.0","https://oss.sonatype.org/content/groups/public");
LibraryLoader.load("net.kyori","adventure-key","4.11.0","https://oss.sonatype.org/content/groups/public");
}
@Override
public void onEnable() {
adventure = BukkitAudiences.create(instance);
AdventureManager.consoleMessage("<gradient:#ff206c:#fdee55>[CustomCrops] </gradient><color:#FFEBCD>Running on " + Bukkit.getVersion()); AdventureManager.consoleMessage("<gradient:#ff206c:#fdee55>[CustomCrops] </gradient><color:#FFEBCD>Running on " + Bukkit.getVersion());

View File

@@ -84,6 +84,7 @@ public class CropManager {
//农作物生长 //农作物生长
public void cropGrow(String worldName){ public void cropGrow(String worldName){
Long time1 = System.currentTimeMillis(); Long time1 = System.currentTimeMillis();
updateData(); updateData();
Long time2 = System.currentTimeMillis(); Long time2 = System.currentTimeMillis();
@@ -209,6 +210,135 @@ public class CropManager {
} }
} }
//农作物生长
public void cropGrowAll(){
Long time1 = System.currentTimeMillis();
updateData();
Long time2 = System.currentTimeMillis();
if(ConfigReader.Config.logTime){
AdventureManager.consoleMessage("性能监测: 农作物数据更新" + (time2-time1) + "ms");
}
Bukkit.getWorlds().forEach(world -> {
String worldName = world.getName();
if (data.contains(worldName)){
data.getConfigurationSection(worldName).getKeys(false).forEach(chunk ->{
String[] split = StringUtils.split(chunk,",");
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]);
int random = new Random().nextInt(ConfigReader.Config.timeToGrow);
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);
bukkitScheduler.runTaskLater(CustomCrops.instance, () -> {
CustomBlock.remove(seedLocation);
CustomBlock.place(ConfigReader.Basic.dead, seedLocation);
}, random);
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, random);
}else {
addStage(potLocation, seedLocation, namespacedID, nextStage, random);
}
}else if(fertilizer instanceof RetainingSoil retainingSoil){
if (Math.random() < retainingSoil.getChance()){
addStage(seedLocation, namespacedID, nextStage, random);
}else {
addStage(potLocation, seedLocation, namespacedID, nextStage, random);
}
}else if(fertilizer instanceof QualityCrop){
addStage(potLocation, seedLocation, namespacedID, nextStage, random);
}else {
AdventureManager.consoleMessage("<red>[CustomCrops] 发现未知类型肥料,已自动清除错误数据!</red>");
PotManager.Cache.remove(potLocation);
}
}else {
PotManager.Cache.remove(potLocation);
}
}
else {
addStage(potLocation, seedLocation, namespacedID, nextStage, random);
}
}
else if(cropInstance.getGiant() != null){
bukkitScheduler.runTaskLater(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);
}
}, random);
}else {
if (cropInstance.getReturnStage() == null && !ConfigReader.Season.enable) data.set(stringBuilder.toString(), null);
bukkitScheduler.runTaskLater(CustomCrops.instance, () -> {
CustomBlock.remove(potLocation);
CustomBlock.place(ConfigReader.Basic.pot, potLocation);
}, random);
}
}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);
bukkitScheduler.runTaskLater(CustomCrops.instance, () -> {
CustomBlock.remove(seedLocation);
CustomBlock.place(ConfigReader.Basic.dead, seedLocation);
}, random);
}
}
});
}
});
}
});
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<String> seasons, String worldName){ private boolean isWrongSeason(Location seedLocation, List<String> seasons, String worldName){
if(ConfigReader.Season.greenhouse){ if(ConfigReader.Season.greenhouse){
for(int i = 1; i <= ConfigReader.Season.range; i++){ for(int i = 1; i <= ConfigReader.Season.range; i++){

View File

@@ -129,6 +129,62 @@ public class SprinklerManager {
} }
} }
public void sprinklerWorkAll(){
Long time1 = System.currentTimeMillis();
updateData();
Long time2 = System.currentTimeMillis();
if (ConfigReader.Config.logTime){
AdventureManager.consoleMessage("性能监测: 洒水器数据更新" + (time2-time1) + "ms");
}
Bukkit.getWorlds().forEach(world -> {
String worldName = world.getName();
if (data.contains(worldName)){
BukkitScheduler bukkitScheduler = Bukkit.getScheduler();
data.getConfigurationSection(worldName).getKeys(false).forEach(chunk ->{
String[] split = StringUtils.split(chunk,",");
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);
int random = new Random().nextInt(ConfigReader.Config.timeToWork);
if (value instanceof MemorySection map){
bukkitScheduler.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 (water > 0){
data.set(worldName + "." + chunk + "." + key + ".water", water - 1);
bukkitScheduler.runTaskLater(CustomCrops.instance, ()-> {
for(int i = -range; i <= range; i++){
for (int j = -range; j <= range; j++){
waterPot(location.clone().add(i,-1,j));
}
}
}, random);
}
if (range == 0) data.set(worldName + "." + chunk + "." + key, null);
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 void waterPot(Location potLoc) { private void waterPot(Location potLoc) {
CustomBlock cb = CustomBlock.byAlreadyPlaced(potLoc.getBlock()); CustomBlock cb = CustomBlock.byAlreadyPlaced(potLoc.getBlock());
if(cb != null){ if(cb != null){

View File

@@ -5,7 +5,7 @@ public class QualityCrop implements Fertilizer{
private int[] chance; private int[] chance;
private String key; private String key;
private int times; private int times;
private boolean before; private final boolean before;
private String name; private String name;
public QualityCrop(String key, int times, int[] chance, boolean before) { public QualityCrop(String key, int times, int[] chance, boolean before) {

View File

@@ -5,7 +5,7 @@ public class SpeedGrow implements Fertilizer{
private double chance; private double chance;
private String key; private String key;
private int times; private int times;
private boolean before; private final boolean before;
private String name; private String name;
public SpeedGrow(String key, int times, double chance, boolean before){ public SpeedGrow(String key, int times, double chance, boolean before){

View File

@@ -0,0 +1,196 @@
/*
* This file is part of helper, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* 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.
*/
package net.momirealms.customcrops.helper;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import net.momirealms.customcrops.CustomCrops;
import org.apache.commons.lang.StringUtils;
import java.io.File;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Files;
import java.util.Objects;
/**
* Resolves {@link MavenLibrary} annotations for a class, and loads the dependency
* into the classloader.
*/
@NonnullByDefault
public final class LibraryLoader {
@SuppressWarnings("Guava")
private static final Supplier<URLClassLoaderAccess> URL_INJECTOR = Suppliers.memoize(() -> URLClassLoaderAccess.create((URLClassLoader) CustomCrops.instance.getClass().getClassLoader()));
/**
* Resolves all {@link MavenLibrary} annotations on the given object.
*
* @param object the object to load libraries for.
*/
public static void loadAll(Object object) {
loadAll(object.getClass());
}
/**
* Resolves all {@link MavenLibrary} annotations on the given class.
*
* @param clazz the class to load libraries for.
*/
public static void loadAll(Class<?> clazz) {
MavenLibrary[] libs = clazz.getDeclaredAnnotationsByType(MavenLibrary.class);
if (libs == null) {
return;
}
for (MavenLibrary lib : libs) {
load(lib.groupId(), lib.artifactId(), lib.version(), lib.repo().url());
}
}
public static void load(String groupId, String artifactId, String version, String repoUrl) {
load(new Dependency(groupId, artifactId, version, repoUrl));
}
public static void load(Dependency d) {
//Log.info(String.format("Loading dependency %s:%s:%s from %s", d.getGroupId(), d.getArtifactId(), d.getVersion(), d.getRepoUrl()));
String name = d.getArtifactId() + "-" + d.getVersion();
File saveLocation = new File(getLibFolder(d), name + ".jar");
if (!saveLocation.exists()) {
try {
Log.info("Dependency '" + name + "' is not already in the libraries folder. Attempting to download...");
URL url = d.getUrl();
try (InputStream is = url.openStream()) {
Files.copy(is, saveLocation.toPath());
Log.info("Dependency '" + name + "' successfully downloaded.");
}
} catch (Exception e) {
e.printStackTrace();
}
}
if (!saveLocation.exists()) {
throw new RuntimeException("Unable to download dependency: " + d.toString());
}
try {
URL_INJECTOR.get().addURL(saveLocation.toURI().toURL());
} catch (Exception e) {
throw new RuntimeException("Unable to load dependency: " + saveLocation.toString(), e);
}
}
private static File getLibFolder(Dependency dependency) {
File pluginDataFolder = CustomCrops.instance.getDataFolder();
File serverDir = pluginDataFolder.getParentFile().getParentFile();
File helperDir = new File(serverDir, "libraries");
String[] split = StringUtils.split(dependency.getGroupId(), ".");
File jarDir = new File(helperDir, split[0] + File.separator + split[1] + File.separator + dependency.artifactId + File.separator + dependency.version );
jarDir.mkdirs();
return jarDir;
}
@NonnullByDefault
public static final class Dependency {
private final String groupId;
private final String artifactId;
private final String version;
private final String repoUrl;
public Dependency(String groupId, String artifactId, String version, String repoUrl) {
this.groupId = Objects.requireNonNull(groupId, "groupId");
this.artifactId = Objects.requireNonNull(artifactId, "artifactId");
this.version = Objects.requireNonNull(version, "version");
this.repoUrl = Objects.requireNonNull(repoUrl, "repoUrl");
}
public String getGroupId() {
return this.groupId;
}
public String getArtifactId() {
return this.artifactId;
}
public String getVersion() {
return this.version;
}
public String getRepoUrl() {
return this.repoUrl;
}
public URL getUrl() throws MalformedURLException {
String repo = this.repoUrl;
if (!repo.endsWith("/")) {
repo += "/";
}
repo += "%s/%s/%s/%s-%s.jar";
String url = String.format(repo, this.groupId.replace(".", "/"), this.artifactId, this.version, this.artifactId, this.version);
return new URL(url);
}
@Override
public boolean equals(Object o) {
if (o == this) return true;
if (!(o instanceof Dependency)) return false;
final Dependency other = (Dependency) o;
return this.getGroupId().equals(other.getGroupId()) &&
this.getArtifactId().equals(other.getArtifactId()) &&
this.getVersion().equals(other.getVersion()) &&
this.getRepoUrl().equals(other.getRepoUrl());
}
@Override
public int hashCode() {
final int PRIME = 59;
int result = 1;
result = result * PRIME + this.getGroupId().hashCode();
result = result * PRIME + this.getArtifactId().hashCode();
result = result * PRIME + this.getVersion().hashCode();
result = result * PRIME + this.getRepoUrl().hashCode();
return result;
}
@Override
public String toString() {
return "LibraryLoader.Dependency(" +
"groupId=" + this.getGroupId() + ", " +
"artifactId=" + this.getArtifactId() + ", " +
"version=" + this.getVersion() + ", " +
"repoUrl=" + this.getRepoUrl() + ")";
}
}
}

View File

@@ -0,0 +1,64 @@
/*
* This file is part of helper, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* 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.
*/
package net.momirealms.customcrops.helper;
import net.momirealms.customcrops.CustomCrops;
import org.bukkit.Bukkit;
import java.util.logging.Level;
import javax.annotation.Nonnull;
/**
* Utility for quickly accessing a logger instance without using {@link Bukkit#getLogger()}
*/
public final class Log {
public static void info(@Nonnull String s) {
CustomCrops.instance.getLogger().info(s);
}
public static void warn(@Nonnull String s) {
CustomCrops.instance.getLogger().warning(s);
}
public static void severe(@Nonnull String s) {
CustomCrops.instance.getLogger().severe(s);
}
public static void warn(@Nonnull String s, Throwable t) {
CustomCrops.instance.getLogger().log(Level.WARNING, s, t);
}
public static void severe(@Nonnull String s, Throwable t) {
CustomCrops.instance.getLogger().log(Level.SEVERE, s, t);
}
private Log() {
throw new UnsupportedOperationException("This class cannot be instantiated");
}
}

View File

@@ -0,0 +1,47 @@
/*
* This file is part of helper, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* 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.
*/
package net.momirealms.customcrops.helper;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.annotation.Nonnull;
/**
* Annotation to indicate the required libraries for a class.
*/
@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MavenLibraries {
@Nonnull
MavenLibrary[] value() default {};
}

View File

@@ -0,0 +1,78 @@
/*
* This file is part of helper, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* 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.
*/
package net.momirealms.customcrops.helper;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.annotation.Nonnull;
/**
* Annotation to indicate a required library for a class.
*/
@Documented
@Repeatable(MavenLibraries.class)
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MavenLibrary {
/**
* The group id of the library
*
* @return the group id of the library
*/
@Nonnull
String groupId();
/**
* The artifact id of the library
*
* @return the artifact id of the library
*/
@Nonnull
String artifactId();
/**
* The version of the library
*
* @return the version of the library
*/
@Nonnull
String version();
/**
* The repo where the library can be obtained from
*
* @return the repo where the library can be obtained from
*/
@Nonnull
Repository repo() default @Repository(url = "https://repo1.maven.org/maven2");
}

View File

@@ -0,0 +1,46 @@
/*
* This file is part of helper, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* 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.
*/
package net.momirealms.customcrops.helper;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import javax.annotation.Nonnull;
import javax.annotation.meta.TypeQualifierDefault;
@Nonnull
@Documented
@TypeQualifierDefault({
ElementType.FIELD,
ElementType.METHOD,
ElementType.PARAMETER
})
@Retention(RetentionPolicy.RUNTIME)
public @interface NonnullByDefault {
}

View File

@@ -0,0 +1,52 @@
/*
* This file is part of helper, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* 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.
*/
package net.momirealms.customcrops.helper;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.annotation.Nonnull;
/**
* Represents a maven repository.
*/
@Documented
@Target(ElementType.LOCAL_VARIABLE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Repository {
/**
* Gets the base url of the repository.
*
* @return the base url of the repository
*/
@Nonnull
String url();
}

View File

@@ -0,0 +1,139 @@
/*
* This file is part of helper, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* 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.
*/
package net.momirealms.customcrops.helper;
import java.lang.reflect.Field;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Collection;
import javax.annotation.Nonnull;
/**
* Provides access to {@link URLClassLoader}#addURL.
*/
public abstract class URLClassLoaderAccess {
/**
* Creates a {@link URLClassLoaderAccess} for the given class loader.
*
* @param classLoader the class loader
* @return the access object
*/
static URLClassLoaderAccess create(URLClassLoader classLoader) {
if (Unsafe.isSupported()) {
return new Unsafe(classLoader);
} else {
return Noop.INSTANCE;
}
}
private final URLClassLoader classLoader;
protected URLClassLoaderAccess(URLClassLoader classLoader) {
this.classLoader = classLoader;
}
/**
* Adds the given URL to the class loader.
*
* @param url the URL to add
*/
public abstract void addURL(@Nonnull URL url);
/**
* Accesses using sun.misc.Unsafe, supported on Java 9+.
*
* @author Vaishnav Anil (https://github.com/slimjar/slimjar)
*/
private static class Unsafe extends URLClassLoaderAccess {
private static final sun.misc.Unsafe UNSAFE;
static {
sun.misc.Unsafe unsafe;
try {
Field unsafeField = sun.misc.Unsafe.class.getDeclaredField("theUnsafe");
unsafeField.setAccessible(true);
unsafe = (sun.misc.Unsafe) unsafeField.get(null);
} catch (Throwable t) {
unsafe = null;
}
UNSAFE = unsafe;
}
private static boolean isSupported() {
return UNSAFE != null;
}
private final Collection<URL> unopenedURLs;
private final Collection<URL> pathURLs;
@SuppressWarnings("unchecked")
Unsafe(URLClassLoader classLoader) {
super(classLoader);
Collection<URL> unopenedURLs;
Collection<URL> pathURLs;
try {
Object ucp = fetchField(URLClassLoader.class, classLoader, "ucp");
unopenedURLs = (Collection<URL>) fetchField(ucp.getClass(), ucp, "unopenedUrls");
pathURLs = (Collection<URL>) fetchField(ucp.getClass(), ucp, "path");
} catch (Throwable e) {
unopenedURLs = null;
pathURLs = null;
}
this.unopenedURLs = unopenedURLs;
this.pathURLs = pathURLs;
}
private static Object fetchField(final Class<?> clazz, final Object object, final String name) throws NoSuchFieldException {
Field field = clazz.getDeclaredField(name);
long offset = UNSAFE.objectFieldOffset(field);
return UNSAFE.getObject(object, offset);
}
@Override
public void addURL(@Nonnull URL url) {
this.unopenedURLs.add(url);
this.pathURLs.add(url);
}
}
private static class Noop extends URLClassLoaderAccess {
private static final Noop INSTANCE = new Noop();
private Noop() {
super(null);
}
@Override
public void addURL(@Nonnull URL url) {
throw new UnsupportedOperationException();
}
}
}

View File

@@ -23,12 +23,21 @@ public class TimeCheck extends BukkitRunnable {
} }
} }
if(time == cropGrowTime){ if(time == cropGrowTime){
Bukkit.getScheduler().runTaskAsynchronously(CustomCrops.instance, () -> { if (ConfigReader.Config.allWorld){
plugin.getCropManager().cropGrow(world.getName()); Bukkit.getScheduler().runTaskAsynchronously(CustomCrops.instance, () -> {
}); plugin.getCropManager().cropGrowAll();
Bukkit.getScheduler().runTaskLaterAsynchronously(CustomCrops.instance, ()->{ });
plugin.getSprinklerManager().sprinklerWork(world.getName()); Bukkit.getScheduler().runTaskLaterAsynchronously(CustomCrops.instance, ()->{
}, ConfigReader.Config.timeToGrow); plugin.getSprinklerManager().sprinklerWorkAll();
}, ConfigReader.Config.timeToGrow);
}else {
Bukkit.getScheduler().runTaskAsynchronously(CustomCrops.instance, () -> {
plugin.getCropManager().cropGrow(world.getName());
});
Bukkit.getScheduler().runTaskLaterAsynchronously(CustomCrops.instance, ()->{
plugin.getSprinklerManager().sprinklerWork(world.getName());
}, ConfigReader.Config.timeToGrow);
}
} }
}); });
}); });

View File

@@ -31,43 +31,18 @@ public class CropInstance {
public double getGiantChance() { return this.giantChance; } public double getGiantChance() { return this.giantChance; }
public List<Requirement> getRequirements() {return requirements;} public List<Requirement> getRequirements() {return requirements;}
public List<String> getSeasons() {return seasons;} public List<String> getSeasons() {return seasons;}
public String getQuality_1() { return quality_1; }
public String getQuality_2() { return quality_2; }
public String getQuality_3() { return quality_3; }
public int getMax() { return max; }
public int getMin() { return min; }
public String getQuality_1() { public void setReturnStage(String stage){ this.returnStage = stage; }
return quality_1; public void setGiant(String giant) { this.giant = giant; }
}
public String getQuality_2() {
return quality_2;
}
public String getQuality_3() {
return quality_3;
}
public int getMax() {
return max;
}
public int getMin() {
return min;
}
public void setReturnStage(String stage){
this.returnStage = stage;
}
public void setGiant(String giant) {this.giant = giant; }
public void setGiantChance(double giantChance) { this.giantChance = giantChance; } public void setGiantChance(double giantChance) { this.giantChance = giantChance; }
public void setRequirements(List<Requirement> requirements) { this.requirements = requirements; } public void setRequirements(List<Requirement> requirements) { this.requirements = requirements; }
public void setSeasons(List<String> seasons) { this.seasons = seasons; } public void setSeasons(List<String> seasons) { this.seasons = seasons; }
public void setQuality_1(String quality_1) { this.quality_1 = quality_1; }
public void setQuality_1(String quality_1) { public void setQuality_2(String quality_2) { this.quality_2 = quality_2; }
this.quality_1 = quality_1; public void setQuality_3(String quality_3) { this.quality_3 = quality_3; }
}
public void setQuality_2(String quality_2) {
this.quality_2 = quality_2;
}
public void setQuality_3(String quality_3) {
this.quality_3 = quality_3;
}
} }

View File

@@ -9,12 +9,10 @@ import org.bukkit.entity.Entity;
public class IAFurniture { public class IAFurniture {
//放置IA自定义家具
public static void placeFurniture(String name, Location location){ public static void placeFurniture(String name, Location location){
CustomFurniture.spawn(name, location.getBlock()); CustomFurniture.spawn(name, location.getBlock());
} }
//根据位置获取盔甲架如果是洒水器返回true否则返回false
public static boolean getFromLocation(Location location, World world){ public static boolean getFromLocation(Location location, World world){
for(Entity entity : world.getNearbyEntities(location,0,0,0)){ for(Entity entity : world.getNearbyEntities(location,0,0,0)){
if(entity instanceof ArmorStand armorStand){ if(entity instanceof ArmorStand armorStand){

View File

@@ -4,9 +4,7 @@ public class Sprinkler {
private int water; private int water;
private int range; private int range;
//2D
private String namespacedID_1; private String namespacedID_1;
//3D
private String namespacedID_2; private String namespacedID_2;
public Sprinkler(int range, int water){ public Sprinkler(int range, int water){
@@ -17,15 +15,12 @@ public class Sprinkler {
public int getWater() { public int getWater() {
return water; return water;
} }
public String getNamespacedID_1() { public String getNamespacedID_1() {
return namespacedID_1; return namespacedID_1;
} }
public String getNamespacedID_2() { public String getNamespacedID_2() {
return namespacedID_2; return namespacedID_2;
} }
public int getRange() { public int getRange() {
return range; return range;
} }
@@ -33,15 +28,12 @@ public class Sprinkler {
public void setRange(int range) { public void setRange(int range) {
this.range = range; this.range = range;
} }
public void setNamespacedID_2(String namespacedID_2) { public void setNamespacedID_2(String namespacedID_2) {
this.namespacedID_2 = namespacedID_2; this.namespacedID_2 = namespacedID_2;
} }
public void setNamespacedID_1(String namespacedID_1) { public void setNamespacedID_1(String namespacedID_1) {
this.namespacedID_1 = namespacedID_1; this.namespacedID_1 = namespacedID_1;
} }
public void setWater(int water) { public void setWater(int water) {
this.water = water; this.water = water;
} }

View File

@@ -2,15 +2,8 @@ package net.momirealms.customcrops.utils;
public record WateringCan(int max, int width, int length) { public record WateringCan(int max, int width, int length) {
public int getMax() { public int getMax() { return max; }
return max; public int getLength() { return length; }
} public int getWidth() { return width; }
public int getLength() {
return length;
}
public int getWidth() {
return width;
}
} }

View File

@@ -67,3 +67,6 @@ config:
#否则农作物生长到最后一阶段不会从数据中清除,过大的数据量 #否则农作物生长到最后一阶段不会从数据中清除,过大的数据量
#可能会导致服务器严重卡顿 #可能会导致服务器严重卡顿
only-grow-in-loaded-chunks: true only-grow-in-loaded-chunks: true
#在此模式下白名单世界将作为触发所有世界农作物生长的时间标准
all-world-grow: true

View File

@@ -1,7 +1,8 @@
name: CustomCrops name: CustomCrops
version: '1.5.8' version: '${version}'
main: net.momirealms.customcrops.CustomCrops main: net.momirealms.customcrops.CustomCrops
api-version: 1.16 api-version: 1.16
authors: [ XiaoMoMi ]
depend: depend:
- ItemsAdder - ItemsAdder
- ProtocolLib - ProtocolLib
@@ -14,7 +15,6 @@ softdepend:
- PlotSquared - PlotSquared
- Towny - Towny
- Lands - Lands
authors: [ XiaoMoMi ]
commands: commands:
customcrops: customcrops:
usage: /customcrops <args> usage: /customcrops <args>