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:
5
gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
5
gradle/wrapper/gradle-wrapper.properties
vendored
Normal 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
|
||||||
@@ -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"), "/");
|
||||||
|
|||||||
@@ -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());
|
||||||
|
|
||||||
|
|||||||
@@ -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++){
|
||||||
|
|||||||
@@ -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){
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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){
|
||||||
|
|||||||
@@ -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() + ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
64
src/main/java/net/momirealms/customcrops/helper/Log.java
Normal file
64
src/main/java/net/momirealms/customcrops/helper/Log.java
Normal 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");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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 {};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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");
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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 {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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();
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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){
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,4 +66,7 @@ config:
|
|||||||
#如果你使用上述三个特性中的任意一个,请不要设置为false
|
#如果你使用上述三个特性中的任意一个,请不要设置为false
|
||||||
#否则农作物生长到最后一阶段不会从数据中清除,过大的数据量
|
#否则农作物生长到最后一阶段不会从数据中清除,过大的数据量
|
||||||
#可能会导致服务器严重卡顿
|
#可能会导致服务器严重卡顿
|
||||||
only-grow-in-loaded-chunks: true
|
only-grow-in-loaded-chunks: true
|
||||||
|
|
||||||
|
#在此模式下白名单世界将作为触发所有世界农作物生长的时间标准
|
||||||
|
all-world-grow: true
|
||||||
@@ -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>
|
||||||
Reference in New Issue
Block a user