mirror of
https://github.com/Xiao-MoMi/Custom-Crops.git
synced 2025-12-22 08:29:35 +00:00
1.6.0
This commit is contained in:
@@ -5,7 +5,7 @@ plugins {
|
||||
|
||||
|
||||
group = 'net.momirealms'
|
||||
version = '1.5.26.4'
|
||||
version = '1.6.0'
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
|
||||
@@ -75,10 +75,8 @@ public class ConfigReader {
|
||||
public static List<Integration> integration;
|
||||
public static String referenceWorld;
|
||||
public static String lang;
|
||||
public static boolean asyncCheck;
|
||||
public static boolean enableLimit;
|
||||
public static boolean hasParticle;
|
||||
public static boolean rightClickHarvest;
|
||||
public static String version;
|
||||
public static String cropMode;
|
||||
public static int cropLimit;
|
||||
public static int sprinklerLimit;
|
||||
public static int yMin;
|
||||
@@ -87,8 +85,11 @@ public class ConfigReader {
|
||||
public static int waterCanRefill;
|
||||
public static int timeToGrow;
|
||||
public static int timeToWork;
|
||||
public static boolean logTime;
|
||||
public static int growMode;
|
||||
public static boolean asyncCheck;
|
||||
public static boolean enableLimit;
|
||||
public static boolean hasParticle;
|
||||
public static boolean rightClickHarvest;
|
||||
public static boolean quality;
|
||||
public static boolean canAddWater;
|
||||
public static boolean allWorld;
|
||||
@@ -97,12 +98,14 @@ public class ConfigReader {
|
||||
public static boolean needEmptyHand;
|
||||
public static boolean boneMeal;
|
||||
public static boolean realisticSeason;
|
||||
public static Particle boneMealSuccess;
|
||||
public static boolean rotation;
|
||||
public static boolean variant4;
|
||||
public static boolean oneTry;
|
||||
public static double boneMealChance;
|
||||
public static double quality_1;
|
||||
public static double quality_2;
|
||||
public static SkillXP skillXP;
|
||||
public static String version;
|
||||
public static Particle boneMealSuccess;
|
||||
|
||||
public static void loadConfig(){
|
||||
|
||||
@@ -117,7 +120,6 @@ public class ConfigReader {
|
||||
timeToGrow = config.getInt("config.time-to-grow",60)*20;
|
||||
timeToWork = config.getInt("config.time-to-work",30)*20;
|
||||
asyncCheck = config.getBoolean("config.async-time-check",false);
|
||||
logTime = config.getBoolean("config.log-time-consume",false);
|
||||
growMode = config.getInt("config.grow-mode",3); if (growMode > 4 || growMode < 1) growMode = 3;
|
||||
allWorld = config.getBoolean("config.all-world-grow",false);
|
||||
hasParticle = config.getBoolean("config.water-particles", true);
|
||||
@@ -125,6 +127,9 @@ public class ConfigReader {
|
||||
needEmptyHand = config.getBoolean("config.harvest-with-empty-hand", true);
|
||||
pwSeason = config.getBoolean("config.prevent-plant-if-wrong-season", true);
|
||||
nwSeason = config.getBoolean("config.should-notify-if-wrong-season", true);
|
||||
rotation = config.getBoolean("config.rotation.enable", false);
|
||||
oneTry = config.getBoolean("config.gigantic-only-one-try", false);
|
||||
variant4 = config.getInt("config.rotation.variant", 4) == 4;
|
||||
|
||||
boneMeal = config.getBoolean("config.bone-meal.enable", true);
|
||||
if (boneMeal){
|
||||
@@ -160,6 +165,7 @@ public class ConfigReader {
|
||||
sprinklerRefill = config.getInt("config.sprinkler-refill",2);
|
||||
waterCanRefill = config.getInt("config.water-can-refill",1);
|
||||
version = config.getString("config-version");
|
||||
cropMode = config.getString("config.crop-mode","tripwire");
|
||||
canAddWater = config.getBoolean("config.water-can-add-water-to-sprinkler",true);
|
||||
|
||||
if (allWorld){
|
||||
@@ -438,12 +444,21 @@ public class ConfigReader {
|
||||
}
|
||||
cropInstance.setGrowChance(config.getDouble("crops." + key + ".grow-chance", 1));
|
||||
if (config.contains("crops." + key + ".gigantic"))
|
||||
if (config.contains("crops." + key + ".gigantic.block")){
|
||||
cropInstance.setGiant(config.getString("crops." + key + ".gigantic.block"));
|
||||
cropInstance.setGiantChance(config.getDouble("crops." + key + ".gigantic.chance"));
|
||||
cropInstance.setIsBlock(true);
|
||||
}
|
||||
if (config.contains("crops." + key + ".gigantic.furniture")){
|
||||
cropInstance.setGiant(config.getString("crops." + key + ".gigantic.furniture"));
|
||||
cropInstance.setIsBlock(false);
|
||||
}
|
||||
cropInstance.setGiantChance(config.getDouble("crops." + key + ".gigantic.chance",0.01));
|
||||
if (Season.enable && config.contains("crops." + key + ".season"))
|
||||
cropInstance.setSeasons(config.getStringList("crops." + key + ".season"));
|
||||
if (config.contains("crops." + key + ".return"))
|
||||
cropInstance.setReturnStage(config.getString("crops." + key + ".return"));
|
||||
if (config.contains("crops." + key + ".drop-other-loots"))
|
||||
cropInstance.setOtherLoots(config.getStringList("crops." + key + ".drop-other-loots"));
|
||||
if (config.contains("crops." + key + ".commands"))
|
||||
cropInstance.setCommands(config.getStringList("crops." + key + ".commands"));
|
||||
if (config.contains("crops." + key + ".skill-xp"))
|
||||
@@ -555,8 +570,7 @@ public class ConfigReader {
|
||||
public static void tryEnableJedis(){
|
||||
YamlConfiguration configuration = ConfigReader.getConfig("redis.yml");
|
||||
JedisUtil.useRedis = configuration.getBoolean("redis.enable", false);
|
||||
if (JedisUtil.useRedis)
|
||||
JedisUtil.initializeRedis(configuration);
|
||||
if (JedisUtil.useRedis) JedisUtil.initializeRedis(configuration);
|
||||
}
|
||||
|
||||
private static void hookMessage(String plugin){
|
||||
|
||||
@@ -26,6 +26,14 @@ import net.momirealms.customcrops.datamanager.SprinklerManager;
|
||||
import net.momirealms.customcrops.helper.LibraryLoader;
|
||||
import net.momirealms.customcrops.hook.Placeholders;
|
||||
import net.momirealms.customcrops.listener.*;
|
||||
import net.momirealms.customcrops.listener.itemframe.BreakBlockI;
|
||||
import net.momirealms.customcrops.listener.itemframe.BreakFurnitureI;
|
||||
import net.momirealms.customcrops.listener.itemframe.InteractFurnitureI;
|
||||
import net.momirealms.customcrops.listener.itemframe.RightClickI;
|
||||
import net.momirealms.customcrops.listener.tripwire.BreakBlockT;
|
||||
import net.momirealms.customcrops.listener.tripwire.BreakFurnitureT;
|
||||
import net.momirealms.customcrops.listener.tripwire.InteractFurnitureT;
|
||||
import net.momirealms.customcrops.listener.tripwire.RightClickT;
|
||||
import net.momirealms.customcrops.timer.CropTimer;
|
||||
import net.momirealms.customcrops.utils.*;
|
||||
import org.bukkit.Bukkit;
|
||||
@@ -66,7 +74,11 @@ public final class CustomCrops extends JavaPlugin {
|
||||
|
||||
adventure = BukkitAudiences.create(plugin);
|
||||
AdventureManager.consoleMessage("<gradient:#ff206c:#fdee55>[CustomCrops] </gradient><color:#FFEBCD>Running on " + Bukkit.getVersion());
|
||||
|
||||
ConfigReader.reloadConfig();
|
||||
if (!Objects.equals(ConfigReader.Config.version, "3")){
|
||||
ConfigUtil.update();
|
||||
}
|
||||
|
||||
if(Bukkit.getPluginManager().getPlugin("PlaceHolderAPI") != null){
|
||||
placeholders = new Placeholders();
|
||||
@@ -82,28 +94,34 @@ public final class CustomCrops extends JavaPlugin {
|
||||
Bukkit.getPluginManager().registerEvents(new ItemSpawn(), this);
|
||||
Bukkit.getPluginManager().registerEvents(new JoinAndQuit(), this);
|
||||
|
||||
Bukkit.getPluginManager().registerEvents(new RightClick(), this);
|
||||
Bukkit.getPluginManager().registerEvents(new BreakBlock(), this);
|
||||
Bukkit.getPluginManager().registerEvents(new BreakFurniture(), this);
|
||||
Bukkit.getPluginManager().registerEvents(new InteractEntity(this), this);
|
||||
|
||||
ConfigReader.tryEnableJedis();
|
||||
|
||||
if (ConfigReader.Season.enable){
|
||||
this.seasonManager = new SeasonManager();
|
||||
this.seasonManager.loadData();
|
||||
}
|
||||
this.cropManager = new CropManager();
|
||||
this.cropManager.loadData();
|
||||
|
||||
this.sprinklerManager = new SprinklerManager();
|
||||
this.sprinklerManager.loadData();
|
||||
this.potManager = new PotManager();
|
||||
this.potManager.loadData();
|
||||
this.cropTimer = new CropTimer();
|
||||
if (ConfigReader.Config.cropMode.equalsIgnoreCase("item_frame")){
|
||||
this.cropManager = new CropManager(true);
|
||||
AdventureManager.consoleMessage("<gradient:#ff206c:#fdee55>[CustomCrops] </gradient><color:#F5DEB3>Crop Mode: ItemFrame");
|
||||
Bukkit.getPluginManager().registerEvents(new RightClickI(), this);
|
||||
Bukkit.getPluginManager().registerEvents(new BreakBlockI(), this);
|
||||
Bukkit.getPluginManager().registerEvents(new BreakFurnitureI(), this);
|
||||
Bukkit.getPluginManager().registerEvents(new InteractFurnitureI(), this);
|
||||
}else{
|
||||
this.cropManager = new CropManager(false);
|
||||
AdventureManager.consoleMessage("<gradient:#ff206c:#fdee55>[CustomCrops] </gradient><color:#F5DEB3>Crop Mode: TripWire");
|
||||
Bukkit.getPluginManager().registerEvents(new RightClickT(), this);
|
||||
Bukkit.getPluginManager().registerEvents(new BreakBlockT(), this);
|
||||
Bukkit.getPluginManager().registerEvents(new BreakFurnitureT(), this);
|
||||
Bukkit.getPluginManager().registerEvents(new InteractFurnitureT(), this);
|
||||
checkIAConfig();
|
||||
if (!Objects.equals(ConfigReader.Config.version, "3")){
|
||||
ConfigUtil.update();
|
||||
}
|
||||
this.cropManager.loadData();
|
||||
AdventureManager.consoleMessage("<gradient:#ff206c:#fdee55>[CustomCrops] </gradient><color:#F5DEB3>Plugin Enabled!");
|
||||
}
|
||||
|
||||
|
||||
@@ -21,9 +21,9 @@ import net.momirealms.customcrops.ConfigReader;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabCompleter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
@@ -31,8 +31,7 @@ import java.util.List;
|
||||
public class Completer implements TabCompleter {
|
||||
|
||||
@Override
|
||||
@ParametersAreNonnullByDefault
|
||||
public @Nullable List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
|
||||
public @Nullable List<String> onTabComplete(CommandSender sender, @NotNull Command command, @NotNull String alias, String[] args) {
|
||||
if (!(sender.isOp() || sender.hasPermission("customcrops.admin"))){
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -26,8 +26,8 @@ import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
public class Executor implements CommandExecutor {
|
||||
|
||||
@@ -38,8 +38,7 @@ public class Executor implements CommandExecutor {
|
||||
}
|
||||
|
||||
@Override
|
||||
@ParametersAreNonnullByDefault
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
public boolean onCommand(CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) {
|
||||
|
||||
if (!(sender.hasPermission("customcrops.admin") || sender.isOp())){
|
||||
AdventureManager.playerMessage((Player) sender, ConfigReader.Message.prefix + ConfigReader.Message.noPerm);
|
||||
@@ -61,6 +60,12 @@ public class Executor implements CommandExecutor {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case "test" -> {
|
||||
CustomCrops.plugin.getCropManager().testData();
|
||||
}
|
||||
case "test2" -> {
|
||||
CustomCrops.plugin.getCropManager().testData2();
|
||||
}
|
||||
case "forcegrow" -> {
|
||||
if (args.length < 2) {
|
||||
lackArgs(sender);
|
||||
@@ -106,6 +111,7 @@ public class Executor implements CommandExecutor {
|
||||
lackArgs(sender);
|
||||
return true;
|
||||
}
|
||||
Bukkit.getScheduler().runTaskAsynchronously(CustomCrops.plugin, ()->{
|
||||
switch (args[1]){
|
||||
case "all" -> {
|
||||
plugin.getSprinklerManager().updateData();
|
||||
@@ -137,6 +143,7 @@ public class Executor implements CommandExecutor {
|
||||
forceSave(sender);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
case "backup" -> {
|
||||
FileUtil.backUpData();
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
package net.momirealms.customcrops.datamanager;
|
||||
|
||||
import dev.lone.itemsadder.api.CustomBlock;
|
||||
import dev.lone.itemsadder.api.CustomFurniture;
|
||||
import net.momirealms.customcrops.fertilizer.QualityCrop;
|
||||
import net.momirealms.customcrops.listener.JoinAndQuit;
|
||||
import net.momirealms.customcrops.utils.AdventureManager;
|
||||
@@ -27,13 +28,17 @@ import net.momirealms.customcrops.fertilizer.Fertilizer;
|
||||
import net.momirealms.customcrops.fertilizer.RetainingSoil;
|
||||
import net.momirealms.customcrops.fertilizer.SpeedGrow;
|
||||
import net.momirealms.customcrops.objects.Crop;
|
||||
import net.momirealms.customcrops.utils.FurnitureUtil;
|
||||
import net.momirealms.customcrops.utils.JedisUtil;
|
||||
import net.momirealms.customcrops.objects.SimpleLocation;
|
||||
import net.momirealms.customcrops.utils.LocUtil;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.scheduler.BukkitScheduler;
|
||||
|
||||
import java.io.File;
|
||||
@@ -41,14 +46,17 @@ import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class CropManager {
|
||||
public class CropManager{
|
||||
|
||||
private YamlConfiguration data;
|
||||
public static ConcurrentHashMap<Location, String> Cache = new ConcurrentHashMap<>();
|
||||
public static ConcurrentHashMap<SimpleLocation, String> Cache = new ConcurrentHashMap<>();
|
||||
public static HashSet<SimpleLocation> RemoveCache = new HashSet<>();
|
||||
private final BukkitScheduler bukkitScheduler;
|
||||
private final boolean isEntity;
|
||||
|
||||
public CropManager(){
|
||||
public CropManager(boolean isEntity){
|
||||
this.bukkitScheduler = Bukkit.getScheduler();
|
||||
this.isEntity = isEntity;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -86,11 +94,37 @@ public class CropManager {
|
||||
*/
|
||||
public void updateData(){
|
||||
Cache.forEach((location, String) -> {
|
||||
int x = location.getBlockX();
|
||||
int z = location.getBlockZ();
|
||||
data.set(location.getWorld().getName() + "." + x / 16 + "," + z / 16 + "." + x + "," + location.getBlockY() + "," + z, String);
|
||||
int x = location.getX();
|
||||
int z = location.getZ();
|
||||
data.set(location.getWorldName() + "." + x / 16 + "," + z / 16 + "." + x + "," + location.getY() + "," + z, String);
|
||||
});
|
||||
Cache.clear();
|
||||
HashSet<SimpleLocation> set = new HashSet<>(RemoveCache);
|
||||
for (SimpleLocation location : set) {
|
||||
int x = location.getX();
|
||||
int z = location.getZ();
|
||||
data.set(location.getWorldName() + "." + x / 16 + "," + z / 16 + "." + x + "," + location.getY() + "," + z, null);
|
||||
}
|
||||
RemoveCache.clear();
|
||||
}
|
||||
|
||||
public void testData(){
|
||||
for (int i = -100; i <= 100; i++){
|
||||
for (int j = -100; j <= 100; j++){
|
||||
SimpleLocation simpleLocation = new SimpleLocation("world",i,128,j);
|
||||
Cache.put(simpleLocation, "XiaoMoMi");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void testData2(){
|
||||
World world = Bukkit.getWorld("world");
|
||||
for (int i = -100; i <= 100; i++){
|
||||
for (int j = -100; j <= 100; j++){
|
||||
Location location = new Location(world, i, 128,j);
|
||||
FurnitureUtil.placeCrop("customcrops:tomato_stage_1", location);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -112,34 +146,43 @@ public class CropManager {
|
||||
* @param worldName 进行生长判定的世界名
|
||||
*/
|
||||
public void growModeOne(String worldName){
|
||||
Long time1 = System.currentTimeMillis();
|
||||
if(!ConfigReader.Config.allWorld){
|
||||
updateData();
|
||||
}
|
||||
Long time2 = System.currentTimeMillis();
|
||||
if(ConfigReader.Config.logTime) AdventureManager.consoleMessage("性能监测: 农作物数据更新" + (time2-time1) + "ms");
|
||||
if(!ConfigReader.Config.allWorld) updateData();
|
||||
if(!ConfigReader.Config.allWorld) saveData();
|
||||
if (data.contains(worldName)){
|
||||
World world = Bukkit.getWorld(worldName);
|
||||
if (!isEntity){
|
||||
data.getConfigurationSection(worldName).getKeys(false).forEach(chunk ->{
|
||||
String[] split = StringUtils.split(chunk,",");
|
||||
if (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]));
|
||||
int random = new Random().nextInt(ConfigReader.Config.timeToGrow);
|
||||
bukkitScheduler.runTaskLaterAsynchronously(CustomCrops.plugin, ()-> {
|
||||
if (growJudge(worldName, seedLocation)){
|
||||
data.set(worldName + "." + chunk + "." + key, null);
|
||||
}
|
||||
}, random);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
data.getConfigurationSection(worldName).getKeys(false).forEach(chunk ->{
|
||||
String[] split = StringUtils.split(chunk,",");
|
||||
if (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]));
|
||||
int random = new Random().nextInt(ConfigReader.Config.timeToGrow);
|
||||
bukkitScheduler.runTaskLater(CustomCrops.plugin, ()-> {
|
||||
growJudgeEntity(worldName, seedLocation, worldName + "." + chunk + "." + key);
|
||||
}, random);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
Long time3 = System.currentTimeMillis();
|
||||
if(ConfigReader.Config.logTime) AdventureManager.consoleMessage("性能监测: 农作物生长过程" + (time3-time2) + "ms");
|
||||
if(!ConfigReader.Config.allWorld){
|
||||
saveData();
|
||||
}
|
||||
Long time4 = System.currentTimeMillis();
|
||||
if(ConfigReader.Config.logTime) AdventureManager.consoleMessage("性能监测: 农作物数据保存" + (time4-time3) + "ms");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -148,34 +191,40 @@ public class CropManager {
|
||||
* @param worldName 进行生长判定的世界名
|
||||
*/
|
||||
public void growModeTwo(String worldName){
|
||||
Long time1 = System.currentTimeMillis();
|
||||
if(!ConfigReader.Config.allWorld){
|
||||
updateData();
|
||||
}
|
||||
Long time2 = System.currentTimeMillis();
|
||||
if(ConfigReader.Config.logTime) AdventureManager.consoleMessage("性能监测: 农作物数据更新" + (time2-time1) + "ms");
|
||||
//HashSet<String> players = new HashSet<>(JoinAndQuit.onlinePlayers);
|
||||
if(!ConfigReader.Config.allWorld) updateData();
|
||||
if(!ConfigReader.Config.allWorld) saveData();
|
||||
HashSet<String> players = getPlayers();
|
||||
if (data.contains(worldName)){
|
||||
World world = Bukkit.getWorld(worldName);
|
||||
if (!isEntity){
|
||||
data.getConfigurationSection(worldName).getKeys(false).forEach(chunk ->{
|
||||
data.getConfigurationSection(worldName + "." + chunk).getValues(false).forEach((key, value) -> {
|
||||
if (!players.contains(value)) return;
|
||||
String[] coordinate = StringUtils.split(key, ",");
|
||||
Location seedLocation = new Location(world,Double.parseDouble(coordinate[0]),Double.parseDouble(coordinate[1]),Double.parseDouble(coordinate[2]));
|
||||
int random = new Random().nextInt(ConfigReader.Config.timeToGrow);
|
||||
bukkitScheduler.runTaskLaterAsynchronously(CustomCrops.plugin, ()-> {
|
||||
if (growJudge(worldName, seedLocation)){
|
||||
data.set(worldName + "." + chunk + "." + key, null);
|
||||
}
|
||||
}, random);
|
||||
});
|
||||
});
|
||||
}
|
||||
else {
|
||||
data.getConfigurationSection(worldName).getKeys(false).forEach(chunk ->{
|
||||
data.getConfigurationSection(worldName + "." + chunk).getValues(false).forEach((key, value) -> {
|
||||
if (!players.contains(value)) return;
|
||||
String[] coordinate = StringUtils.split(key, ",");
|
||||
Location seedLocation = new Location(world,Double.parseDouble(coordinate[0]),Double.parseDouble(coordinate[1]),Double.parseDouble(coordinate[2]));
|
||||
int random = new Random().nextInt(ConfigReader.Config.timeToGrow);
|
||||
bukkitScheduler.runTaskLater(CustomCrops.plugin, ()-> {
|
||||
growJudgeEntity(worldName, seedLocation, worldName + "." + chunk + "." + key);
|
||||
}, random);
|
||||
});
|
||||
});
|
||||
}
|
||||
Long time3 = System.currentTimeMillis();
|
||||
if(ConfigReader.Config.logTime) AdventureManager.consoleMessage("性能监测: 农作物生长过程" + (time3-time2) + "ms");
|
||||
if(!ConfigReader.Config.allWorld){
|
||||
saveData();
|
||||
}
|
||||
Long time4 = System.currentTimeMillis();
|
||||
if(ConfigReader.Config.logTime) AdventureManager.consoleMessage("性能监测: 农作物数据保存" + (time4-time3) + "ms");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -184,16 +233,12 @@ public class CropManager {
|
||||
* @param worldName 进行生长判定的世界名
|
||||
*/
|
||||
public void growModeThree(String worldName){
|
||||
Long time1 = System.currentTimeMillis();
|
||||
if(!ConfigReader.Config.allWorld){
|
||||
updateData();
|
||||
}
|
||||
Long time2 = System.currentTimeMillis();
|
||||
if(ConfigReader.Config.logTime) AdventureManager.consoleMessage("性能监测: 农作物数据更新" + (time2-time1) + "ms");
|
||||
//HashSet<String> players = new HashSet<>(JoinAndQuit.onlinePlayers);
|
||||
if(!ConfigReader.Config.allWorld) updateData();
|
||||
if(!ConfigReader.Config.allWorld) saveData();
|
||||
HashSet<String> players = getPlayers();
|
||||
if (data.contains(worldName)){
|
||||
World world = Bukkit.getWorld(worldName);
|
||||
if (!isEntity){
|
||||
data.getConfigurationSection(worldName).getKeys(false).forEach(chunk ->{
|
||||
String[] split = StringUtils.split(chunk,",");
|
||||
//区块被加载,则强行生长判定
|
||||
@@ -201,9 +246,12 @@ public class CropManager {
|
||||
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]));
|
||||
int random = new Random().nextInt(ConfigReader.Config.timeToGrow);
|
||||
bukkitScheduler.runTaskLaterAsynchronously(CustomCrops.plugin, ()-> {
|
||||
if (growJudge(worldName, seedLocation)){
|
||||
data.set(worldName + "." + chunk + "." + key, null);
|
||||
}
|
||||
}, random);
|
||||
});
|
||||
}
|
||||
//区块未加载,玩家在线
|
||||
@@ -212,20 +260,45 @@ public class CropManager {
|
||||
if (!players.contains(value)) return;
|
||||
String[] coordinate = StringUtils.split(key, ",");
|
||||
Location seedLocation = new Location(world,Double.parseDouble(coordinate[0]),Double.parseDouble(coordinate[1]),Double.parseDouble(coordinate[2]));
|
||||
int random = new Random().nextInt(ConfigReader.Config.timeToGrow);
|
||||
bukkitScheduler.runTaskLaterAsynchronously(CustomCrops.plugin, ()-> {
|
||||
if (growJudge(worldName, seedLocation)){
|
||||
data.set(worldName + "." + chunk + "." + key, null);
|
||||
}
|
||||
}, random);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
data.getConfigurationSection(worldName).getKeys(false).forEach(chunk ->{
|
||||
String[] split = StringUtils.split(chunk,",");
|
||||
//区块被加载,则强行生长判定
|
||||
if (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]));
|
||||
int random = new Random().nextInt(ConfigReader.Config.timeToGrow);
|
||||
bukkitScheduler.runTaskLater(CustomCrops.plugin, ()-> {
|
||||
growJudgeEntity(worldName, seedLocation, worldName + "." + chunk + "." + key);
|
||||
}, random);
|
||||
});
|
||||
}
|
||||
//区块未加载,玩家在线
|
||||
else{
|
||||
data.getConfigurationSection(worldName + "." + chunk).getValues(false).forEach((key, value) -> {
|
||||
if (!players.contains(value)) return;
|
||||
String[] coordinate = StringUtils.split(key, ",");
|
||||
Location seedLocation = new Location(world,Double.parseDouble(coordinate[0]),Double.parseDouble(coordinate[1]),Double.parseDouble(coordinate[2]));
|
||||
int random = new Random().nextInt(ConfigReader.Config.timeToGrow);
|
||||
bukkitScheduler.runTaskLater(CustomCrops.plugin, ()-> {
|
||||
growJudgeEntity(worldName, seedLocation, worldName + "." + chunk + "." + key);
|
||||
}, random);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
Long time3 = System.currentTimeMillis();
|
||||
if(ConfigReader.Config.logTime) AdventureManager.consoleMessage("性能监测: 农作物生长过程" + (time3-time2) + "ms");
|
||||
if(!ConfigReader.Config.allWorld){
|
||||
saveData();
|
||||
}
|
||||
Long time4 = System.currentTimeMillis();
|
||||
if(ConfigReader.Config.logTime) AdventureManager.consoleMessage("性能监测: 农作物数据保存" + (time4-time3) + "ms");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -234,32 +307,37 @@ public class CropManager {
|
||||
* @param worldName 进行生长判定的世界名
|
||||
*/
|
||||
public void growModeFour(String worldName){
|
||||
Long time1 = System.currentTimeMillis();
|
||||
if(!ConfigReader.Config.allWorld){
|
||||
updateData();
|
||||
}
|
||||
Long time2 = System.currentTimeMillis();
|
||||
if(ConfigReader.Config.logTime) AdventureManager.consoleMessage("性能监测: 农作物数据更新" + (time2-time1) + "ms");
|
||||
if(!ConfigReader.Config.allWorld){updateData();}
|
||||
if(!ConfigReader.Config.allWorld) saveData();
|
||||
if (data.contains(worldName)){
|
||||
World world = Bukkit.getWorld(worldName);
|
||||
if (!isEntity){
|
||||
data.getConfigurationSection(worldName).getKeys(false).forEach(chunk ->{
|
||||
String[] split = StringUtils.split(chunk,",");
|
||||
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]));
|
||||
int random = new Random().nextInt(ConfigReader.Config.timeToGrow);
|
||||
bukkitScheduler.runTaskLaterAsynchronously(CustomCrops.plugin, ()-> {
|
||||
if (growJudge(worldName, seedLocation)){
|
||||
data.set(worldName + "." + chunk + "." + key, null);
|
||||
}
|
||||
}, random);
|
||||
});
|
||||
});
|
||||
}
|
||||
else {
|
||||
data.getConfigurationSection(worldName).getKeys(false).forEach(chunk ->{
|
||||
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]));
|
||||
int random = new Random().nextInt(ConfigReader.Config.timeToGrow);
|
||||
bukkitScheduler.runTaskLater(CustomCrops.plugin, ()-> {
|
||||
growJudgeEntity(worldName, seedLocation, worldName + "." + chunk + "." + key);
|
||||
}, random);
|
||||
});
|
||||
});
|
||||
}
|
||||
Long time3 = System.currentTimeMillis();
|
||||
if(ConfigReader.Config.logTime) AdventureManager.consoleMessage("性能监测: 农作物生长过程" + (time3-time2) + "ms");
|
||||
if(!ConfigReader.Config.allWorld){
|
||||
saveData();
|
||||
}
|
||||
Long time4 = System.currentTimeMillis();
|
||||
if(ConfigReader.Config.logTime) AdventureManager.consoleMessage("性能监测: 农作物数据保存" + (time4-time3) + "ms");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -316,17 +394,15 @@ public class CropManager {
|
||||
//获取自定义方块ID
|
||||
String potNamespacedID = pot.getNamespacedID();
|
||||
if (potNamespacedID.equals(ConfigReader.Basic.watered_pot)){
|
||||
int random = new Random().nextInt(ConfigReader.Config.timeToGrow);
|
||||
|
||||
//如果启用季节限制且农作物有季节需求
|
||||
if (ConfigReader.Season.enable && cropInstance.getSeasons() != null){
|
||||
if (isWrongSeason(seedLocation, cropInstance.getSeasons(), worldName)){
|
||||
|
||||
bukkitScheduler.runTaskLater(CustomCrops.plugin, () -> {
|
||||
bukkitScheduler.runTask(CustomCrops.plugin, () -> {
|
||||
CustomBlock.remove(seedLocation);
|
||||
CustomBlock.place(ConfigReader.Basic.dead, seedLocation);
|
||||
}, random);
|
||||
});
|
||||
return true;
|
||||
|
||||
}
|
||||
}
|
||||
//获取下一阶段
|
||||
@@ -334,7 +410,7 @@ public class CropManager {
|
||||
//下一阶段存在
|
||||
if (CustomBlock.getInstance(StringUtils.chop(namespacedID) + nextStage) != null) {
|
||||
//尝试获取肥料类型
|
||||
Fertilizer fertilizer = PotManager.Cache.get(SimpleLocation.fromLocation(potLocation));
|
||||
Fertilizer fertilizer = PotManager.Cache.get(LocUtil.fromLocation(potLocation));
|
||||
//有肥料
|
||||
if (fertilizer != null){
|
||||
//查询剩余使用次数
|
||||
@@ -346,67 +422,67 @@ public class CropManager {
|
||||
if (cropInstance.getGrowChance() > Math.random()){
|
||||
//农作物存在下两个阶段
|
||||
if (Math.random() < speedGrow.getChance() && CustomBlock.getInstance(StringUtils.chop(namespacedID) + (nextStage + 1)) != null){
|
||||
addStage(potLocation, seedLocation, namespacedID, nextStage + 1, random);
|
||||
addStage(potLocation, seedLocation, namespacedID, nextStage + 1);
|
||||
}else {
|
||||
addStage(potLocation, seedLocation, namespacedID, nextStage, random);
|
||||
addStage(potLocation, seedLocation, namespacedID, nextStage);
|
||||
}
|
||||
}else {
|
||||
notAddStage(potLocation, random);
|
||||
notAddStage(potLocation);
|
||||
}
|
||||
}
|
||||
//保湿土壤
|
||||
else if(fertilizer instanceof RetainingSoil retainingSoil){
|
||||
if (Math.random() < retainingSoil.getChance()){
|
||||
if (cropInstance.getGrowChance() > Math.random()){
|
||||
addStage(seedLocation, namespacedID, nextStage, random);
|
||||
addStage(seedLocation, namespacedID, nextStage);
|
||||
}
|
||||
}else {
|
||||
if (cropInstance.getGrowChance() > Math.random()){
|
||||
addStage(potLocation, seedLocation, namespacedID, nextStage, random);
|
||||
addStage(potLocation, seedLocation, namespacedID, nextStage);
|
||||
}else {
|
||||
notAddStage(potLocation, random);
|
||||
notAddStage(potLocation);
|
||||
}
|
||||
}
|
||||
}
|
||||
//品质肥料
|
||||
else if(fertilizer instanceof QualityCrop){
|
||||
if (cropInstance.getGrowChance() > Math.random()){
|
||||
addStage(potLocation, seedLocation, namespacedID, nextStage, random);
|
||||
addStage(potLocation, seedLocation, namespacedID, nextStage);
|
||||
}else {
|
||||
notAddStage(potLocation, random);
|
||||
notAddStage(potLocation);
|
||||
}
|
||||
}else {
|
||||
//未知肥料类型处理
|
||||
AdventureManager.consoleMessage("<red>[CustomCrops] Unknown fertilizer, Auto removed!</red>");
|
||||
PotManager.Cache.remove(SimpleLocation.fromLocation(potLocation));
|
||||
PotManager.Cache.remove(LocUtil.fromLocation(potLocation));
|
||||
|
||||
if (cropInstance.getGrowChance() > Math.random()){
|
||||
addStage(potLocation, seedLocation, namespacedID, nextStage, random);
|
||||
addStage(potLocation, seedLocation, namespacedID, nextStage);
|
||||
}else {
|
||||
notAddStage(potLocation, random);
|
||||
notAddStage(potLocation);
|
||||
}
|
||||
}
|
||||
//肥料的最后一次使用
|
||||
if (times == 1){
|
||||
PotManager.Cache.remove(SimpleLocation.fromLocation(potLocation));
|
||||
PotManager.Cache.remove(LocUtil.fromLocation(potLocation));
|
||||
}
|
||||
}
|
||||
else {
|
||||
//移除肥料信息,一般不会出现此情况
|
||||
PotManager.Cache.remove(SimpleLocation.fromLocation(potLocation));
|
||||
PotManager.Cache.remove(LocUtil.fromLocation(potLocation));
|
||||
if (cropInstance.getGrowChance() > Math.random()){
|
||||
addStage(potLocation, seedLocation, namespacedID, nextStage, random);
|
||||
addStage(potLocation, seedLocation, namespacedID, nextStage);
|
||||
}else {
|
||||
notAddStage(potLocation, random);
|
||||
notAddStage(potLocation);
|
||||
}
|
||||
}
|
||||
}
|
||||
//没有肥料
|
||||
else {
|
||||
if (cropInstance.getGrowChance() > Math.random()){
|
||||
addStage(potLocation, seedLocation, namespacedID, nextStage, random);
|
||||
addStage(potLocation, seedLocation, namespacedID, nextStage);
|
||||
}else {
|
||||
notAddStage(potLocation, random);
|
||||
notAddStage(potLocation);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -414,29 +490,40 @@ public class CropManager {
|
||||
else if(cropInstance.getGiant() != null){
|
||||
//巨大化判定
|
||||
if (cropInstance.getGiantChance() > Math.random()){
|
||||
//成功巨大化,移除数据
|
||||
bukkitScheduler.runTaskLater(CustomCrops.plugin, () ->{
|
||||
|
||||
if (cropInstance.isBlock()){
|
||||
bukkitScheduler.runTask(CustomCrops.plugin, () ->{
|
||||
CustomBlock.remove(seedLocation);
|
||||
CustomBlock.place(cropInstance.getGiant(), seedLocation);
|
||||
CustomBlock.remove(potLocation);
|
||||
CustomBlock.place(ConfigReader.Basic.pot, potLocation);
|
||||
}, random);
|
||||
});
|
||||
}else {
|
||||
bukkitScheduler.runTask(CustomCrops.plugin, () ->{
|
||||
//加载区块哦亲
|
||||
CustomBlock.remove(seedLocation);
|
||||
CustomFurniture.spawn(cropInstance.getGiant(), seedLocation.getBlock());
|
||||
CustomBlock.remove(potLocation);
|
||||
CustomBlock.place(ConfigReader.Basic.pot, potLocation);
|
||||
});
|
||||
}
|
||||
//成功巨大化,移除数据
|
||||
return true;
|
||||
}else {
|
||||
//失败,转湿为干
|
||||
bukkitScheduler.runTaskLater(CustomCrops.plugin, () ->{
|
||||
bukkitScheduler.runTask(CustomCrops.plugin, () ->{
|
||||
CustomBlock.remove(potLocation);
|
||||
CustomBlock.place(ConfigReader.Basic.pot, potLocation);
|
||||
}, random);
|
||||
return ConfigReader.Config.growMode == 4;
|
||||
});
|
||||
return ConfigReader.Config.oneTry || ConfigReader.Config.growMode == 4;
|
||||
}
|
||||
}else {
|
||||
//若无下一阶段,无巨大化,未启用季节,则移除无用数据
|
||||
if (!ConfigReader.Season.enable) return true;
|
||||
bukkitScheduler.runTaskLater(CustomCrops.plugin, () -> {
|
||||
bukkitScheduler.runTask(CustomCrops.plugin, () -> {
|
||||
CustomBlock.remove(potLocation);
|
||||
CustomBlock.place(ConfigReader.Basic.pot, potLocation);
|
||||
}, random);
|
||||
});
|
||||
}
|
||||
}
|
||||
//干燥的种植盆
|
||||
@@ -448,10 +535,10 @@ public class CropManager {
|
||||
if(seasons == null) return false;
|
||||
//错误季节
|
||||
if(isWrongSeason(seedLocation, seasons, worldName)){
|
||||
bukkitScheduler.runTaskLater(CustomCrops.plugin, () -> {
|
||||
bukkitScheduler.runTask(CustomCrops.plugin, () -> {
|
||||
CustomBlock.remove(seedLocation);
|
||||
CustomBlock.place(ConfigReader.Basic.dead, seedLocation);
|
||||
}, new Random().nextInt(ConfigReader.Config.timeToGrow));
|
||||
});
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -495,22 +582,211 @@ public class CropManager {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 对某个位置进行生长判定
|
||||
* @param worldName 世界名
|
||||
* @param seedLocation 种子位置
|
||||
*/
|
||||
private void growJudgeEntity(String worldName, Location seedLocation, String path) {
|
||||
Chunk chunk = seedLocation.getChunk();
|
||||
chunk.load();
|
||||
bukkitScheduler.runTaskLater(CustomCrops.plugin, ()-> {
|
||||
if (chunk.isEntitiesLoaded()){
|
||||
CustomFurniture crop = FurnitureUtil.getFurniture(seedLocation.clone().add(0.5,0.1,0.5));
|
||||
//自定义农作物家具不存在
|
||||
if(crop == null) {
|
||||
data.set(path, null);
|
||||
return;
|
||||
}
|
||||
String namespacedID = crop.getNamespacedID();
|
||||
//已死亡或不是农作物
|
||||
if(namespacedID.equals(ConfigReader.Basic.dead) || !namespacedID.contains("_stage_")) {
|
||||
data.set(path, null);
|
||||
return;
|
||||
}
|
||||
//农作物下方自定义方块不存在
|
||||
Location potLocation = seedLocation.clone().subtract(0,1,0);
|
||||
CustomBlock pot = CustomBlock.byAlreadyPlaced(potLocation.getBlock());
|
||||
if (pot == null){
|
||||
data.set(path, null);
|
||||
return;
|
||||
}
|
||||
//农作物实例不存在
|
||||
String id = crop.getId();
|
||||
String[] cropNameList = StringUtils.split(id,"_");
|
||||
Crop cropInstance = ConfigReader.CROPS.get(cropNameList[0]);
|
||||
if (cropInstance == null){
|
||||
data.set(path, null);
|
||||
return;
|
||||
}
|
||||
//获取自定义方块ID
|
||||
String potNamespacedID = pot.getNamespacedID();
|
||||
if (potNamespacedID.equals(ConfigReader.Basic.watered_pot)){
|
||||
//如果启用季节限制且农作物有季节需求
|
||||
if (ConfigReader.Season.enable && cropInstance.getSeasons() != null){
|
||||
if (isWrongSeason(seedLocation, cropInstance.getSeasons(), worldName)){
|
||||
seedLocation.getChunk().load();
|
||||
CustomFurniture.remove(crop.getArmorstand(), false);
|
||||
FurnitureUtil.placeCrop(ConfigReader.Basic.dead, seedLocation);
|
||||
data.set(path, null);
|
||||
return;
|
||||
}
|
||||
}
|
||||
//获取下一阶段
|
||||
int nextStage = Integer.parseInt(cropNameList[2]) + 1;
|
||||
//下一阶段存在
|
||||
if (CustomFurniture.getInstance(StringUtils.chop(namespacedID) + nextStage) != null) {
|
||||
//尝试获取肥料类型
|
||||
Fertilizer fertilizer = PotManager.Cache.get(LocUtil.fromLocation(potLocation));
|
||||
//有肥料
|
||||
if (fertilizer != null){
|
||||
//查询剩余使用次数
|
||||
int times = fertilizer.getTimes();
|
||||
if (times > 0){
|
||||
fertilizer.setTimes(times - 1);
|
||||
//生长激素
|
||||
if (fertilizer instanceof SpeedGrow speedGrow){
|
||||
if (cropInstance.getGrowChance() > Math.random()){
|
||||
//农作物存在下两个阶段
|
||||
if (Math.random() < speedGrow.getChance() && CustomBlock.getInstance(StringUtils.chop(namespacedID) + (nextStage + 1)) != null){
|
||||
addStageEntity(potLocation, seedLocation, crop.getArmorstand(), StringUtils.chop(namespacedID) + (nextStage + 1));
|
||||
}else {
|
||||
addStageEntity(potLocation, seedLocation, crop.getArmorstand(), StringUtils.chop(namespacedID) + nextStage);
|
||||
}
|
||||
}else {
|
||||
CustomBlock.remove(potLocation);
|
||||
CustomBlock.place(ConfigReader.Basic.pot, potLocation);
|
||||
}
|
||||
}
|
||||
//保湿土壤
|
||||
else if(fertilizer instanceof RetainingSoil retainingSoil){
|
||||
if (Math.random() < retainingSoil.getChance()){
|
||||
if (cropInstance.getGrowChance() > Math.random()){
|
||||
addStageEntity(seedLocation, crop.getArmorstand(), StringUtils.chop(namespacedID) + nextStage);
|
||||
}
|
||||
}else {
|
||||
if (cropInstance.getGrowChance() > Math.random()){
|
||||
addStageEntity(potLocation, seedLocation, crop.getArmorstand(), StringUtils.chop(namespacedID) + nextStage);
|
||||
}else {
|
||||
CustomBlock.remove(potLocation);
|
||||
CustomBlock.place(ConfigReader.Basic.pot, potLocation);
|
||||
}
|
||||
}
|
||||
}
|
||||
//品质肥料
|
||||
else if(fertilizer instanceof QualityCrop){
|
||||
if (cropInstance.getGrowChance() > Math.random()){
|
||||
addStageEntity(potLocation, seedLocation, crop.getArmorstand(), StringUtils.chop(namespacedID) + nextStage);
|
||||
}else {
|
||||
CustomBlock.remove(potLocation);
|
||||
CustomBlock.place(ConfigReader.Basic.pot, potLocation);
|
||||
}
|
||||
}else {
|
||||
//未知肥料类型处理
|
||||
AdventureManager.consoleMessage("<red>[CustomCrops] Unknown fertilizer, Auto removed!</red>");
|
||||
PotManager.Cache.remove(LocUtil.fromLocation(potLocation));
|
||||
if (cropInstance.getGrowChance() > Math.random()){
|
||||
addStageEntity(potLocation, seedLocation, crop.getArmorstand(), StringUtils.chop(namespacedID) + nextStage);
|
||||
}else {
|
||||
CustomBlock.remove(potLocation);
|
||||
CustomBlock.place(ConfigReader.Basic.pot, potLocation);
|
||||
}
|
||||
}
|
||||
//肥料的最后一次使用
|
||||
if (times == 1){
|
||||
PotManager.Cache.remove(LocUtil.fromLocation(potLocation));
|
||||
}
|
||||
}
|
||||
else {
|
||||
//移除肥料信息,一般不会出现此情况
|
||||
PotManager.Cache.remove(LocUtil.fromLocation(potLocation));
|
||||
if (cropInstance.getGrowChance() > Math.random()){
|
||||
addStageEntity(potLocation, seedLocation, crop.getArmorstand(), StringUtils.chop(namespacedID) + nextStage);
|
||||
}else {
|
||||
CustomBlock.remove(potLocation);
|
||||
CustomBlock.place(ConfigReader.Basic.pot, potLocation);
|
||||
}
|
||||
}
|
||||
}
|
||||
//没有肥料
|
||||
else {
|
||||
if (cropInstance.getGrowChance() > Math.random()){
|
||||
addStageEntity(potLocation, seedLocation, crop.getArmorstand(), StringUtils.chop(namespacedID) + nextStage);
|
||||
}else {
|
||||
CustomBlock.remove(potLocation);
|
||||
CustomBlock.place(ConfigReader.Basic.pot, potLocation);
|
||||
}
|
||||
}
|
||||
}
|
||||
//农作物是否存在巨大化
|
||||
else if(cropInstance.getGiant() != null){
|
||||
//巨大化判定
|
||||
if (cropInstance.getGiantChance() > Math.random()){
|
||||
if (cropInstance.isBlock()){
|
||||
CustomBlock.remove(potLocation);
|
||||
CustomBlock.place(ConfigReader.Basic.pot, potLocation);
|
||||
CustomFurniture.remove(crop.getArmorstand(), false);
|
||||
CustomBlock.place(cropInstance.getGiant(), seedLocation);
|
||||
}else {
|
||||
CustomBlock.remove(potLocation);
|
||||
CustomBlock.place(ConfigReader.Basic.pot, potLocation);
|
||||
CustomFurniture.remove(crop.getArmorstand(), false);
|
||||
CustomFurniture.spawn(cropInstance.getGiant(), seedLocation.getBlock());
|
||||
}
|
||||
//成功巨大化,移除数据
|
||||
data.set(path, null);
|
||||
}else {
|
||||
//失败,转湿为干
|
||||
CustomBlock.remove(potLocation);
|
||||
CustomBlock.place(ConfigReader.Basic.pot, potLocation);
|
||||
if (ConfigReader.Config.oneTry || ConfigReader.Config.growMode == 4){
|
||||
data.set(path, null);
|
||||
}
|
||||
}
|
||||
}else {
|
||||
//若无下一阶段,无巨大化,未启用季节,则移除无用数据
|
||||
if (!ConfigReader.Season.enable){
|
||||
data.set(path, null);
|
||||
return;
|
||||
}
|
||||
CustomBlock.remove(potLocation);
|
||||
CustomBlock.place(ConfigReader.Basic.pot, potLocation);
|
||||
}
|
||||
}
|
||||
//干燥的种植盆
|
||||
else if(potNamespacedID.equals(ConfigReader.Basic.pot)){
|
||||
//未启用季节
|
||||
if(!ConfigReader.Season.enable) return;
|
||||
//农作物无视季节
|
||||
List<String> seasons = cropInstance.getSeasons();
|
||||
if(seasons == null) return;
|
||||
//错误季节
|
||||
if(isWrongSeason(seedLocation, seasons, worldName)){
|
||||
CustomBlock.remove(seedLocation);
|
||||
CustomBlock.place(ConfigReader.Basic.dead, seedLocation);
|
||||
data.set(path, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
},4);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 生长一个阶段(消耗水)
|
||||
* @param potLocation 种植盆位置
|
||||
* @param seedLocation 农作物位置
|
||||
* @param namespacedID 农作物下一阶段的ID
|
||||
* @param nextStage 农作物下一阶段的阶段数
|
||||
* @param random 随机生长时间
|
||||
*/
|
||||
private void addStage(Location potLocation, Location seedLocation, String namespacedID, int nextStage, int random){
|
||||
private void addStage(Location potLocation, Location seedLocation, String namespacedID, int nextStage){
|
||||
String stage = StringUtils.chop(namespacedID) + nextStage;
|
||||
bukkitScheduler.runTaskLater(CustomCrops.plugin, () ->{
|
||||
bukkitScheduler.runTask(CustomCrops.plugin, () ->{
|
||||
CustomBlock.remove(potLocation);
|
||||
CustomBlock.place(ConfigReader.Basic.pot, potLocation);
|
||||
CustomBlock.remove(seedLocation);
|
||||
CustomBlock.place(stage, seedLocation);
|
||||
}, random);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -518,26 +794,41 @@ public class CropManager {
|
||||
* @param seedLocation 农作物位置
|
||||
* @param namespacedID 农作物下一阶段的ID
|
||||
* @param nextStage 农作物下一阶段的阶段数
|
||||
* @param random 随机生长时间
|
||||
*/
|
||||
private void addStage(Location seedLocation, String namespacedID, int nextStage, int random){
|
||||
private void addStage(Location seedLocation, String namespacedID, int nextStage){
|
||||
String stage = StringUtils.chop(namespacedID) + nextStage;
|
||||
bukkitScheduler.runTaskLater(CustomCrops.plugin, () ->{
|
||||
bukkitScheduler.runTask(CustomCrops.plugin, () ->{
|
||||
CustomBlock.remove(seedLocation);
|
||||
CustomBlock.place(stage, seedLocation);
|
||||
}, random);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private void addStageEntity(Location potLocation, Location seedLocation, Entity entity, String nextStage){
|
||||
CustomBlock.remove(potLocation);
|
||||
CustomBlock.place(ConfigReader.Basic.pot, potLocation);
|
||||
CustomFurniture.remove(entity,false);
|
||||
if (FurnitureUtil.getFurniture(seedLocation.add(0.5,0.1,0.5)) == null){
|
||||
FurnitureUtil.placeCrop(nextStage, seedLocation);
|
||||
}
|
||||
}
|
||||
|
||||
private void addStageEntity(Location seedLocation, Entity entity, String nextStage){
|
||||
CustomFurniture.remove(entity,false);
|
||||
if (FurnitureUtil.getFurniture(seedLocation.add(0.5,0.1,0.5)) == null){
|
||||
FurnitureUtil.placeCrop(nextStage, seedLocation);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 停滞阶段(消耗水)
|
||||
* @param potLocation 种植盆位置
|
||||
* @param random 随机生长时间
|
||||
*/
|
||||
private void notAddStage(Location potLocation, int random){
|
||||
bukkitScheduler.runTaskLater(CustomCrops.plugin, () ->{
|
||||
private void notAddStage(Location potLocation){
|
||||
bukkitScheduler.runTask(CustomCrops.plugin, () ->{
|
||||
CustomBlock.remove(potLocation);
|
||||
CustomBlock.place(ConfigReader.Basic.pot, potLocation);
|
||||
}, random);
|
||||
});
|
||||
}
|
||||
|
||||
private HashSet<String> getPlayers(){
|
||||
|
||||
@@ -82,8 +82,11 @@ public class SeasonManager{
|
||||
*/
|
||||
public void getSeason(World world) {
|
||||
if (ConfigReader.Config.realisticSeason){
|
||||
Bukkit.getScheduler().runTaskLater(CustomCrops.plugin, ()->{
|
||||
SEASON.put(world.getName(), RealisticSeason.getSeason(world));
|
||||
}else {
|
||||
},60);
|
||||
}
|
||||
else {
|
||||
int season = (int) ((world.getFullTime() / 24000L) % (ConfigReader.Season.duration * 4)) / ConfigReader.Season.duration;
|
||||
switch (season) {
|
||||
case 0 -> SEASON.put(world.getName(), "spring");
|
||||
|
||||
@@ -39,7 +39,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class SprinklerManager {
|
||||
|
||||
public YamlConfiguration data;
|
||||
public static YamlConfiguration data;
|
||||
public static ConcurrentHashMap<SimpleLocation, Sprinkler> Cache = new ConcurrentHashMap<>();
|
||||
public static HashSet<SimpleLocation> RemoveCache = new HashSet<>();
|
||||
private final BukkitScheduler bukkitScheduler;
|
||||
@@ -62,7 +62,7 @@ public class SprinklerManager {
|
||||
AdventureManager.consoleMessage("<red>[CustomCrops] 洒水器数据文件生成失败!</red>");
|
||||
}
|
||||
}
|
||||
this.data = YamlConfiguration.loadConfiguration(file);
|
||||
data = YamlConfiguration.loadConfiguration(file);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -120,12 +120,8 @@ public class SprinklerManager {
|
||||
* @param worldName 世界名
|
||||
*/
|
||||
public void workModeOne(String worldName){
|
||||
Long time1 = System.currentTimeMillis();
|
||||
if(!ConfigReader.Config.allWorld){
|
||||
updateData();
|
||||
}
|
||||
Long time2 = System.currentTimeMillis();
|
||||
if (ConfigReader.Config.logTime) AdventureManager.consoleMessage("性能监测: 洒水器数据更新" + (time2-time1) + "ms");
|
||||
if(!ConfigReader.Config.allWorld) updateData();
|
||||
if(!ConfigReader.Config.allWorld) saveData();
|
||||
if (data.contains(worldName)){
|
||||
World world = Bukkit.getWorld(worldName);
|
||||
data.getConfigurationSection(worldName).getKeys(false).forEach(chunk ->{
|
||||
@@ -138,7 +134,7 @@ public class SprinklerManager {
|
||||
bukkitScheduler.runTask(CustomCrops.plugin, ()->{
|
||||
int water = (int) map.get("water");
|
||||
int range = (int) Optional.ofNullable(map.get("range")).orElse(0);
|
||||
if(!IAFurnitureUtil.isSprinkler(location)){
|
||||
if(!FurnitureUtil.isSprinkler(location)){
|
||||
data.set(worldName + "." + chunk + "." + key, null);
|
||||
return;
|
||||
}
|
||||
@@ -159,13 +155,6 @@ public class SprinklerManager {
|
||||
}
|
||||
});
|
||||
}
|
||||
Long time3 = System.currentTimeMillis();
|
||||
if(ConfigReader.Config.logTime) AdventureManager.consoleMessage("性能监测: 洒水器工作过程" + (time3-time2) + "ms");
|
||||
if(!ConfigReader.Config.allWorld){
|
||||
saveData();
|
||||
}
|
||||
Long time4 = System.currentTimeMillis();
|
||||
if(ConfigReader.Config.logTime) AdventureManager.consoleMessage("性能监测: 洒水器数据保存" + (time4-time3) + "ms");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -173,13 +162,8 @@ public class SprinklerManager {
|
||||
* @param worldName 世界名
|
||||
*/
|
||||
public void workModeTwo(String worldName){
|
||||
Long time1 = System.currentTimeMillis();
|
||||
if(!ConfigReader.Config.allWorld){
|
||||
updateData();
|
||||
}
|
||||
Long time2 = System.currentTimeMillis();
|
||||
if (ConfigReader.Config.logTime) AdventureManager.consoleMessage("性能监测: 洒水器数据更新" + (time2-time1) + "ms");
|
||||
//HashSet<String> players = new HashSet<>(JoinAndQuit.onlinePlayers);
|
||||
if(!ConfigReader.Config.allWorld) updateData();
|
||||
if(!ConfigReader.Config.allWorld) saveData();
|
||||
HashSet<String> players = getPlayers();
|
||||
if (data.contains(worldName)){
|
||||
World world = Bukkit.getWorld(worldName);
|
||||
@@ -194,7 +178,7 @@ public class SprinklerManager {
|
||||
if (!players.contains(player)) return;
|
||||
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);
|
||||
bukkitScheduler.callSyncMethod(CustomCrops.plugin, ()->{
|
||||
bukkitScheduler.runTask(CustomCrops.plugin, ()->{
|
||||
int water = (int) map.get("water");
|
||||
int range = (int) Optional.ofNullable(map.get("range")).orElse(0);
|
||||
if (water > 0){
|
||||
@@ -208,19 +192,11 @@ public class SprinklerManager {
|
||||
}, new Random().nextInt(ConfigReader.Config.timeToWork));
|
||||
}
|
||||
if (range == 0) data.set(worldName + "." + chunk + "." + key, null);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
Long time3 = System.currentTimeMillis();
|
||||
if(ConfigReader.Config.logTime) AdventureManager.consoleMessage("性能监测: 洒水器工作过程" + (time3-time2) + "ms");
|
||||
if(!ConfigReader.Config.allWorld){
|
||||
saveData();
|
||||
}
|
||||
Long time4 = System.currentTimeMillis();
|
||||
if(ConfigReader.Config.logTime) AdventureManager.consoleMessage("性能监测: 洒水器数据保存" + (time4-time3) + "ms");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -228,13 +204,8 @@ public class SprinklerManager {
|
||||
* @param worldName 世界名
|
||||
*/
|
||||
public void workModeThree(String worldName){
|
||||
Long time1 = System.currentTimeMillis();
|
||||
if(!ConfigReader.Config.allWorld){
|
||||
updateData();
|
||||
}
|
||||
Long time2 = System.currentTimeMillis();
|
||||
if (ConfigReader.Config.logTime) AdventureManager.consoleMessage("性能监测: 洒水器数据更新" + (time2-time1) + "ms");
|
||||
//HashSet<String> players = new HashSet<>(JoinAndQuit.onlinePlayers);
|
||||
if(!ConfigReader.Config.allWorld) updateData();
|
||||
if(!ConfigReader.Config.allWorld) saveData();
|
||||
HashSet<String> players = getPlayers();
|
||||
if (data.contains(worldName)){
|
||||
World world = Bukkit.getWorld(worldName);
|
||||
@@ -248,7 +219,7 @@ public class SprinklerManager {
|
||||
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);
|
||||
bukkitScheduler.runTask(CustomCrops.plugin, ()->{
|
||||
if(!IAFurnitureUtil.isSprinkler(location)){
|
||||
if(!FurnitureUtil.isSprinkler(location)){
|
||||
data.set(worldName + "." + chunk + "." + key, null);
|
||||
return;
|
||||
}
|
||||
@@ -296,13 +267,6 @@ public class SprinklerManager {
|
||||
}
|
||||
});
|
||||
}
|
||||
Long time3 = System.currentTimeMillis();
|
||||
if(ConfigReader.Config.logTime) AdventureManager.consoleMessage("性能监测: 洒水器工作过程" + (time3-time2) + "ms");
|
||||
if(!ConfigReader.Config.allWorld){
|
||||
saveData();
|
||||
}
|
||||
Long time4 = System.currentTimeMillis();
|
||||
if(ConfigReader.Config.logTime) AdventureManager.consoleMessage("性能监测: 洒水器数据保存" + (time4-time3) + "ms");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -310,12 +274,8 @@ public class SprinklerManager {
|
||||
* @param worldName 世界名
|
||||
*/
|
||||
public void workModeFour(String worldName){
|
||||
Long time1 = System.currentTimeMillis();
|
||||
if(!ConfigReader.Config.allWorld){
|
||||
updateData();
|
||||
}
|
||||
Long time2 = System.currentTimeMillis();
|
||||
if (ConfigReader.Config.logTime) AdventureManager.consoleMessage("性能监测: 洒水器数据更新" + (time2-time1) + "ms");
|
||||
if(!ConfigReader.Config.allWorld) updateData();
|
||||
if(!ConfigReader.Config.allWorld) saveData();
|
||||
if (data.contains(worldName)){
|
||||
World world = Bukkit.getWorld(worldName);
|
||||
data.getConfigurationSection(worldName).getKeys(false).forEach(chunk ->{
|
||||
@@ -340,13 +300,6 @@ public class SprinklerManager {
|
||||
});
|
||||
});
|
||||
}
|
||||
Long time3 = System.currentTimeMillis();
|
||||
if(ConfigReader.Config.logTime) AdventureManager.consoleMessage("性能监测: 洒水器工作过程" + (time3-time2) + "ms");
|
||||
if(!ConfigReader.Config.allWorld){
|
||||
saveData();
|
||||
}
|
||||
Long time4 = System.currentTimeMillis();
|
||||
if(ConfigReader.Config.logTime) AdventureManager.consoleMessage("性能监测: 洒水器数据保存" + (time4-time3) + "ms");
|
||||
}
|
||||
|
||||
|
||||
@@ -391,4 +344,24 @@ public class SprinklerManager {
|
||||
return new HashSet<>(JoinAndQuit.onlinePlayers);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取某个洒水器的水量
|
||||
* @param location 洒水器位置
|
||||
* @param world 世界
|
||||
* @param x 坐标
|
||||
* @param z 坐标
|
||||
* @param sprinkler 洒水器类型
|
||||
* @return 水量
|
||||
*/
|
||||
public static int getCurrentWater(Location location, String world, int x, int z, Sprinkler sprinkler) {
|
||||
int currentWater;
|
||||
if (sprinkler != null) currentWater = sprinkler.getWater();
|
||||
else {
|
||||
String path = world + "." + x / 16 + "," + z / 16 + "." + x + "," + location.getBlockY() + "," + z + ".water";
|
||||
currentWater = data.getInt(path);
|
||||
}
|
||||
return currentWater;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,6 @@ 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")
|
||||
@@ -126,7 +125,6 @@ public final class LibraryLoader {
|
||||
return jarDir;
|
||||
}
|
||||
|
||||
@NonnullByDefault
|
||||
public static final class Dependency {
|
||||
private final String groupId;
|
||||
private final String artifactId;
|
||||
|
||||
@@ -27,33 +27,32 @@ package net.momirealms.customcrops.helper;
|
||||
|
||||
import net.momirealms.customcrops.CustomCrops;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
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) {
|
||||
public static void info(@NotNull String s) {
|
||||
CustomCrops.plugin.getLogger().info(s);
|
||||
}
|
||||
|
||||
public static void warn(@Nonnull String s) {
|
||||
public static void warn(@NotNull String s) {
|
||||
CustomCrops.plugin.getLogger().warning(s);
|
||||
}
|
||||
|
||||
public static void severe(@Nonnull String s) {
|
||||
public static void severe(@NotNull String s) {
|
||||
CustomCrops.plugin.getLogger().severe(s);
|
||||
}
|
||||
|
||||
public static void warn(@Nonnull String s, Throwable t) {
|
||||
public static void warn(@NotNull String s, Throwable t) {
|
||||
CustomCrops.plugin.getLogger().log(Level.WARNING, s, t);
|
||||
}
|
||||
|
||||
public static void severe(@Nonnull String s, Throwable t) {
|
||||
public static void severe(@NotNull String s, Throwable t) {
|
||||
CustomCrops.plugin.getLogger().log(Level.SEVERE, s, t);
|
||||
}
|
||||
|
||||
|
||||
@@ -25,14 +25,14 @@
|
||||
|
||||
package net.momirealms.customcrops.helper;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
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.
|
||||
*/
|
||||
@@ -41,7 +41,7 @@ import javax.annotation.Nonnull;
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface MavenLibraries {
|
||||
|
||||
@Nonnull
|
||||
@NotNull
|
||||
MavenLibrary[] value() default {};
|
||||
|
||||
}
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
|
||||
package net.momirealms.customcrops.helper;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Repeatable;
|
||||
@@ -32,8 +34,6 @@ 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.
|
||||
*/
|
||||
@@ -48,7 +48,7 @@ public @interface MavenLibrary {
|
||||
*
|
||||
* @return the group id of the library
|
||||
*/
|
||||
@Nonnull
|
||||
@NotNull
|
||||
String groupId();
|
||||
|
||||
/**
|
||||
@@ -56,7 +56,7 @@ public @interface MavenLibrary {
|
||||
*
|
||||
* @return the artifact id of the library
|
||||
*/
|
||||
@Nonnull
|
||||
@NotNull
|
||||
String artifactId();
|
||||
|
||||
/**
|
||||
@@ -64,7 +64,7 @@ public @interface MavenLibrary {
|
||||
*
|
||||
* @return the version of the library
|
||||
*/
|
||||
@Nonnull
|
||||
@NotNull
|
||||
String version();
|
||||
|
||||
/**
|
||||
@@ -72,7 +72,7 @@ public @interface MavenLibrary {
|
||||
*
|
||||
* @return the repo where the library can be obtained from
|
||||
*/
|
||||
@Nonnull
|
||||
@NotNull
|
||||
Repository repo() default @Repository(url = "https://repo1.maven.org/maven2");
|
||||
|
||||
}
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
/*
|
||||
* 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 {
|
||||
|
||||
}
|
||||
@@ -31,8 +31,6 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* Represents a maven repository.
|
||||
*/
|
||||
@@ -46,7 +44,6 @@ public @interface Repository {
|
||||
*
|
||||
* @return the base url of the repository
|
||||
*/
|
||||
@Nonnull
|
||||
String url();
|
||||
|
||||
}
|
||||
|
||||
@@ -25,13 +25,13 @@
|
||||
|
||||
package net.momirealms.customcrops.helper;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
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.
|
||||
*/
|
||||
@@ -63,7 +63,7 @@ public abstract class URLClassLoaderAccess {
|
||||
*
|
||||
* @param url the URL to add
|
||||
*/
|
||||
public abstract void addURL(@Nonnull URL url);
|
||||
public abstract void addURL(@NotNull URL url);
|
||||
|
||||
/**
|
||||
* Accesses using sun.misc.Unsafe, supported on Java 9+.
|
||||
@@ -117,7 +117,7 @@ public abstract class URLClassLoaderAccess {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addURL(@Nonnull URL url) {
|
||||
public void addURL(@NotNull URL url) {
|
||||
this.unopenedURLs.add(url);
|
||||
this.pathURLs.add(url);
|
||||
}
|
||||
@@ -131,7 +131,7 @@ public abstract class URLClassLoaderAccess {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addURL(@Nonnull URL url) {
|
||||
public void addURL(@NotNull URL url) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,20 @@
|
||||
/*
|
||||
* Copyright (C) <2022> <XiaoMoMi>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.momirealms.customcrops.hook;
|
||||
|
||||
import me.casperge.realisticseasons.api.SeasonsAPI;
|
||||
|
||||
@@ -24,6 +24,6 @@ public class mcMMO implements SkillXP {
|
||||
|
||||
@Override
|
||||
public void addXp(Player player, double amount) {
|
||||
ExperienceAPI.addXP(player, "Herbalism", (int) amount, "UNKNOWN");
|
||||
ExperienceAPI.addRawXP(player, "Herbalism", (float) amount, "UNKNOWN");
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,7 @@
|
||||
package net.momirealms.customcrops.limits;
|
||||
|
||||
import net.momirealms.customcrops.ConfigReader;
|
||||
import net.momirealms.customcrops.utils.IAFurnitureUtil;
|
||||
import net.momirealms.customcrops.utils.FurnitureUtil;
|
||||
import org.bukkit.Location;
|
||||
|
||||
public class SprinklersPerChunk {
|
||||
@@ -33,7 +33,7 @@ public class SprinklersPerChunk {
|
||||
Location square = chunkLocation.clone().add(i + 0.5, 0.5, j + 0.5);
|
||||
for (int k = ConfigReader.Config.yMin; k <= ConfigReader.Config.yMax; ++k) {
|
||||
square.add(0.0, 1.0, 0.0);
|
||||
if(IAFurnitureUtil.isSprinkler(square))
|
||||
if(FurnitureUtil.isSprinkler(square))
|
||||
if (n++ > ConfigReader.Config.sprinklerLimit)
|
||||
break Label_out;
|
||||
}
|
||||
|
||||
@@ -1,16 +1,19 @@
|
||||
package net.momirealms.customcrops.listener;
|
||||
|
||||
import net.momirealms.customcrops.utils.JedisUtil;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
|
||||
public class JoinAndQuit implements Listener {
|
||||
|
||||
public static HashSet<String> onlinePlayers = new HashSet<>();
|
||||
public static HashMap<Player, Long> coolDown = new HashMap<>();
|
||||
|
||||
@EventHandler
|
||||
public void onJoin(PlayerJoinEvent event){
|
||||
@@ -22,5 +25,6 @@ public class JoinAndQuit implements Listener {
|
||||
public void onQuit(PlayerQuitEvent event){
|
||||
if (JedisUtil.useRedis) JedisUtil.remPlayer(event.getPlayer().getName());
|
||||
else onlinePlayers.remove(event.getPlayer().getName());
|
||||
coolDown.remove(event.getPlayer());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package net.momirealms.customcrops.listener.itemframe;
|
||||
|
||||
import dev.lone.itemsadder.api.CustomFurniture;
|
||||
import dev.lone.itemsadder.api.CustomStack;
|
||||
import dev.lone.itemsadder.api.Events.CustomBlockBreakEvent;
|
||||
import net.momirealms.customcrops.ConfigReader;
|
||||
import net.momirealms.customcrops.datamanager.CropManager;
|
||||
import net.momirealms.customcrops.datamanager.PotManager;
|
||||
import net.momirealms.customcrops.fertilizer.Fertilizer;
|
||||
import net.momirealms.customcrops.fertilizer.QualityCrop;
|
||||
import net.momirealms.customcrops.integrations.protection.Integration;
|
||||
import net.momirealms.customcrops.objects.Crop;
|
||||
import net.momirealms.customcrops.objects.SimpleLocation;
|
||||
import net.momirealms.customcrops.utils.DropUtil;
|
||||
import net.momirealms.customcrops.utils.FurnitureUtil;
|
||||
import net.momirealms.customcrops.utils.LocUtil;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
public class BreakBlockI implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void onBreak(CustomBlockBreakEvent event){
|
||||
String namespacedId = event.getNamespacedID();
|
||||
if(namespacedId.equalsIgnoreCase(ConfigReader.Basic.watered_pot) || namespacedId.equalsIgnoreCase(ConfigReader.Basic.pot)){
|
||||
Location location = event.getBlock().getLocation();
|
||||
PotManager.Cache.remove(LocUtil.fromLocation(location));
|
||||
World world = location.getWorld();
|
||||
for (Integration integration : ConfigReader.Config.integration)
|
||||
if(!integration.canBreak(location, event.getPlayer())) return;
|
||||
CustomFurniture furniture = FurnitureUtil.getFurniture(location.add(0.5,1.1,0.5));
|
||||
if(furniture != null){
|
||||
String nsID = furniture.getNamespacedID();
|
||||
if(nsID.contains("_stage_")){
|
||||
SimpleLocation simpleLocation = LocUtil.fromLocation(location);
|
||||
if (CropManager.Cache.remove(simpleLocation) == null){
|
||||
CropManager.RemoveCache.add(simpleLocation);
|
||||
}
|
||||
CustomFurniture.remove(furniture.getArmorstand(), false);
|
||||
if (nsID.equals(ConfigReader.Basic.dead)) return;
|
||||
if (ConfigReader.Config.quality){
|
||||
String[] cropNameList = StringUtils.split(StringUtils.split(nsID, ":")[1], "_");
|
||||
int nextStage = Integer.parseInt(cropNameList[2]) + 1;
|
||||
if (CustomFurniture.getInstance(StringUtils.chop(nsID) + nextStage) == null) {
|
||||
Crop cropInstance = ConfigReader.CROPS.get(cropNameList[0]);
|
||||
ThreadLocalRandom current = ThreadLocalRandom.current();
|
||||
int random = current.nextInt(cropInstance.getMin(), cropInstance.getMax() + 1);
|
||||
Location itemLoc = location.clone().add(0.5,0.2,0.5);
|
||||
Fertilizer fertilizer = PotManager.Cache.get(LocUtil.fromLocation(location.clone().subtract(0,1,0)));
|
||||
if (fertilizer != null){
|
||||
if (fertilizer instanceof QualityCrop qualityCrop){
|
||||
int[] weights = qualityCrop.getChance();
|
||||
double weightTotal = weights[0] + weights[1] + weights[2];
|
||||
for (int i = 0; i < random; i++){
|
||||
double ran = Math.random();
|
||||
if (ran < weights[0]/(weightTotal)) world.dropItem(itemLoc, CustomStack.getInstance(cropInstance.getQuality_1()).getItemStack());
|
||||
else if(ran > 1 - weights[1]/(weightTotal)) world.dropItem(itemLoc, CustomStack.getInstance(cropInstance.getQuality_2()).getItemStack());
|
||||
else world.dropItem(itemLoc, CustomStack.getInstance(cropInstance.getQuality_3()).getItemStack());
|
||||
}
|
||||
}
|
||||
}
|
||||
else DropUtil.normalDrop(cropInstance, random, itemLoc, world);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package net.momirealms.customcrops.listener.itemframe;
|
||||
|
||||
import dev.lone.itemsadder.api.CustomFurniture;
|
||||
import dev.lone.itemsadder.api.CustomStack;
|
||||
import dev.lone.itemsadder.api.Events.FurnitureBreakEvent;
|
||||
import net.momirealms.customcrops.ConfigReader;
|
||||
import net.momirealms.customcrops.datamanager.CropManager;
|
||||
import net.momirealms.customcrops.datamanager.PotManager;
|
||||
import net.momirealms.customcrops.datamanager.SprinklerManager;
|
||||
import net.momirealms.customcrops.fertilizer.Fertilizer;
|
||||
import net.momirealms.customcrops.fertilizer.QualityCrop;
|
||||
import net.momirealms.customcrops.integrations.protection.Integration;
|
||||
import net.momirealms.customcrops.objects.Crop;
|
||||
import net.momirealms.customcrops.objects.SimpleLocation;
|
||||
import net.momirealms.customcrops.objects.Sprinkler;
|
||||
import net.momirealms.customcrops.utils.DropUtil;
|
||||
import net.momirealms.customcrops.utils.LocUtil;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
public class BreakFurnitureI implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void onBreakFurniture(FurnitureBreakEvent event){
|
||||
String namespacedID = event.getNamespacedID();
|
||||
Sprinkler config = ConfigReader.SPRINKLERS.get(namespacedID);
|
||||
if (config != null){
|
||||
SimpleLocation simpleLocation = LocUtil.fromLocation(event.getBukkitEntity().getLocation());
|
||||
if (SprinklerManager.Cache.remove(simpleLocation) == null){
|
||||
SprinklerManager.RemoveCache.add(simpleLocation);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (namespacedID.contains("_stage_")){
|
||||
Player player = event.getPlayer();
|
||||
Location location = event.getBukkitEntity().getLocation();
|
||||
for (Integration integration : ConfigReader.Config.integration)
|
||||
if(!integration.canBreak(location, player)) return;
|
||||
SimpleLocation simpleLocation = LocUtil.fromLocation(location);
|
||||
if (CropManager.Cache.remove(simpleLocation) == null){
|
||||
CropManager.RemoveCache.add(simpleLocation);
|
||||
}
|
||||
if (!ConfigReader.Config.quality || namespacedID.equals(ConfigReader.Basic.dead)) return;
|
||||
String[] cropNameList = StringUtils.split(StringUtils.split(namespacedID, ":")[1], "_");
|
||||
int nextStage = Integer.parseInt(cropNameList[2]) + 1;
|
||||
if (CustomFurniture.getInstance(StringUtils.chop(namespacedID) + nextStage) == null) {
|
||||
Crop cropInstance = ConfigReader.CROPS.get(cropNameList[0]);
|
||||
ThreadLocalRandom current = ThreadLocalRandom.current();
|
||||
int random = current.nextInt(cropInstance.getMin(), cropInstance.getMax() + 1);
|
||||
Location itemLoc = location.clone().add(0,0.2,0);
|
||||
World world = location.getWorld();
|
||||
List<String> commands = cropInstance.getCommands();
|
||||
Fertilizer fertilizer = PotManager.Cache.get(LocUtil.fromLocation(location.clone().subtract(0,1,0)));
|
||||
if (commands != null)
|
||||
for (String command : commands)
|
||||
Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(), command.replace("{player}", player.getName()));
|
||||
if (ConfigReader.Config.skillXP != null && cropInstance.getSkillXP() != 0) ConfigReader.Config.skillXP.addXp(player, cropInstance.getSkillXP());
|
||||
if (fertilizer != null){
|
||||
if (fertilizer instanceof QualityCrop qualityCrop){
|
||||
int[] weights = qualityCrop.getChance();
|
||||
double weightTotal = weights[0] + weights[1] + weights[2];
|
||||
for (int i = 0; i < random; i++){
|
||||
double ran = Math.random();
|
||||
if (ran < weights[0]/(weightTotal)) world.dropItem(itemLoc, CustomStack.getInstance(cropInstance.getQuality_1()).getItemStack());
|
||||
else if(ran > 1 - weights[1]/(weightTotal)) world.dropItem(itemLoc, CustomStack.getInstance(cropInstance.getQuality_2()).getItemStack());
|
||||
else world.dropItem(itemLoc, CustomStack.getInstance(cropInstance.getQuality_3()).getItemStack());
|
||||
}
|
||||
}
|
||||
else DropUtil.normalDrop(cropInstance, random, itemLoc, world);
|
||||
}
|
||||
else DropUtil.normalDrop(cropInstance, random, itemLoc, world);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,293 @@
|
||||
package net.momirealms.customcrops.listener.itemframe;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NBTCompound;
|
||||
import de.tr7zw.changeme.nbtapi.NBTItem;
|
||||
import dev.lone.itemsadder.api.CustomFurniture;
|
||||
import dev.lone.itemsadder.api.CustomStack;
|
||||
import dev.lone.itemsadder.api.Events.FurnitureInteractEvent;
|
||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
||||
import net.momirealms.customcrops.ConfigReader;
|
||||
import net.momirealms.customcrops.datamanager.CropManager;
|
||||
import net.momirealms.customcrops.datamanager.PotManager;
|
||||
import net.momirealms.customcrops.datamanager.SprinklerManager;
|
||||
import net.momirealms.customcrops.fertilizer.Fertilizer;
|
||||
import net.momirealms.customcrops.fertilizer.QualityCrop;
|
||||
import net.momirealms.customcrops.integrations.protection.Integration;
|
||||
import net.momirealms.customcrops.listener.JoinAndQuit;
|
||||
import net.momirealms.customcrops.objects.Crop;
|
||||
import net.momirealms.customcrops.objects.SimpleLocation;
|
||||
import net.momirealms.customcrops.objects.Sprinkler;
|
||||
import net.momirealms.customcrops.objects.WateringCan;
|
||||
import net.momirealms.customcrops.utils.*;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
public class InteractFurnitureI implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void onEntityInteract(FurnitureInteractEvent event){
|
||||
long time = System.currentTimeMillis();
|
||||
Player player = event.getPlayer();
|
||||
if (time - (JoinAndQuit.coolDown.getOrDefault(player, time - 200)) < 200) return;
|
||||
JoinAndQuit.coolDown.put(player, time);
|
||||
String namespacedID = event.getNamespacedID();
|
||||
Sprinkler config = ConfigReader.SPRINKLERS.get(namespacedID);
|
||||
if(config != null){
|
||||
ItemStack itemStack = player.getInventory().getItemInMainHand();
|
||||
Location location = event.getBukkitEntity().getLocation();
|
||||
String world = location.getWorld().getName();
|
||||
int x = location.getBlockX();
|
||||
int z = location.getBlockZ();
|
||||
int maxWater = config.getWater();
|
||||
int currentWater = 0;
|
||||
Location loc = location.clone().subtract(0,1,0).getBlock().getLocation().add(0,1,0);
|
||||
Sprinkler sprinkler = SprinklerManager.Cache.get(LocUtil.fromLocation(loc));
|
||||
if (itemStack.getType() == Material.WATER_BUCKET){
|
||||
itemStack.setType(Material.BUCKET);
|
||||
if (sprinkler != null){
|
||||
currentWater = sprinkler.getWater();
|
||||
currentWater += ConfigReader.Config.sprinklerRefill;
|
||||
if (currentWater > maxWater) currentWater = maxWater;
|
||||
sprinkler.setWater(currentWater);
|
||||
}else {
|
||||
String path = world + "." + x / 16 + "," + z / 16 + "." + x + "," + location.getBlockY() + "," + z;
|
||||
currentWater = SprinklerManager.data.getInt(path+ ".water");
|
||||
currentWater += ConfigReader.Config.sprinklerRefill;
|
||||
if (currentWater > maxWater) currentWater = maxWater;
|
||||
SprinklerManager.data.set(path + ".water", currentWater);
|
||||
SprinklerManager.data.set(path + ".range", config.getRange());
|
||||
}
|
||||
AdventureManager.playerSound(player, ConfigReader.Sounds.addWaterToSprinklerSource, ConfigReader.Sounds.addWaterToSprinklerKey);
|
||||
}
|
||||
else {
|
||||
if (ConfigReader.Config.canAddWater && itemStack.getType() != Material.AIR){
|
||||
NBTItem nbtItem = new NBTItem(itemStack);
|
||||
NBTCompound nbtCompound = nbtItem.getCompound("itemsadder");
|
||||
if (nbtCompound != null) {
|
||||
String id = nbtCompound.getString("id");
|
||||
String namespace = nbtCompound.getString("namespace");
|
||||
WateringCan wateringCan = ConfigReader.CANS.get(namespace + ":" + id);
|
||||
if (wateringCan != null) {
|
||||
int water = nbtItem.getInteger("WaterAmount");
|
||||
if (water > 0){
|
||||
nbtItem.setInteger("WaterAmount", --water);
|
||||
AdventureManager.playerSound(player, ConfigReader.Sounds.addWaterToSprinklerSource, ConfigReader.Sounds.addWaterToSprinklerKey);
|
||||
if (sprinkler != null){
|
||||
currentWater = sprinkler.getWater();
|
||||
currentWater++;
|
||||
if (currentWater > maxWater) currentWater = maxWater;
|
||||
sprinkler.setWater(currentWater);
|
||||
}else {
|
||||
String path = world + "." + x / 16 + "," + z / 16 + "." + x + "," + location.getBlockY() + "," + z;
|
||||
currentWater = SprinklerManager.data.getInt(path + ".water");
|
||||
currentWater++;
|
||||
if (currentWater > maxWater) currentWater = maxWater;
|
||||
SprinklerManager.data.set(path + ".water", currentWater);
|
||||
SprinklerManager.data.set(path + ".range", config.getRange());
|
||||
}
|
||||
}
|
||||
else {
|
||||
currentWater = SprinklerManager.getCurrentWater(location, world, x, z, sprinkler);
|
||||
}
|
||||
if (ConfigReader.Message.hasWaterInfo){
|
||||
AdventureManager.playerActionbar(player,
|
||||
(ConfigReader.Message.waterLeft +
|
||||
ConfigReader.Message.waterFull.repeat(water) +
|
||||
ConfigReader.Message.waterEmpty.repeat(wateringCan.getMax() - water) +
|
||||
ConfigReader.Message.waterRight)
|
||||
.replace("{max_water}", String.valueOf(wateringCan.getMax()))
|
||||
.replace("{water}", String.valueOf(water)));
|
||||
}
|
||||
if (ConfigReader.Basic.hasWaterLore){
|
||||
String string =
|
||||
(ConfigReader.Basic.waterLeft +
|
||||
ConfigReader.Basic.waterFull.repeat(water) +
|
||||
ConfigReader.Basic.waterEmpty.repeat(wateringCan.getMax() - water) +
|
||||
ConfigReader.Basic.waterRight)
|
||||
.replace("{max_water}", String.valueOf(wateringCan.getMax()))
|
||||
.replace("{water}", String.valueOf(water));
|
||||
List<String> lores = nbtItem.getCompound("display").getStringList("Lore");
|
||||
lores.clear();
|
||||
ConfigReader.Basic.waterLore.forEach(lore -> lores.add(GsonComponentSerializer.gson().serialize(MiniMessage.miniMessage().deserialize(lore.replace("{water_info}", string)))));
|
||||
}
|
||||
itemStack.setItemMeta(nbtItem.getItem().getItemMeta());
|
||||
}
|
||||
}
|
||||
else currentWater = SprinklerManager.getCurrentWater(location, world, x, z, sprinkler);
|
||||
}
|
||||
else currentWater = SprinklerManager.getCurrentWater(location, world, x, z, sprinkler);
|
||||
}
|
||||
if (ConfigReader.Message.hasSprinklerInfo)
|
||||
HoloUtil.showHolo(
|
||||
(ConfigReader.Message.sprinklerLeft +
|
||||
ConfigReader.Message.sprinklerFull.repeat(currentWater) +
|
||||
ConfigReader.Message.sprinklerEmpty.repeat(maxWater - currentWater) +
|
||||
ConfigReader.Message.sprinklerRight)
|
||||
.replace("{max_water}", String.valueOf(maxWater))
|
||||
.replace("{water}", String.valueOf(currentWater)),
|
||||
player,
|
||||
location.add(0, ConfigReader.Message.sprinklerOffset,0),
|
||||
ConfigReader.Message.sprinklerTime);
|
||||
}
|
||||
if (namespacedID.contains("_stage_")){
|
||||
ItemStack itemStack = player.getInventory().getItemInMainHand();
|
||||
if (itemStack.getType() != Material.AIR){
|
||||
NBTItem nbtItem = new NBTItem(itemStack);
|
||||
NBTCompound nbtCompound = nbtItem.getCompound("itemsadder");
|
||||
if (nbtCompound != null){
|
||||
Location location = event.getBukkitEntity().getLocation();
|
||||
for (Integration integration : ConfigReader.Config.integration)
|
||||
if(!integration.canPlace(location, player)) return;
|
||||
String id = nbtCompound.getString("id");
|
||||
String namespace = nbtCompound.getString("namespace");
|
||||
String nsID = namespace + ":" +id;
|
||||
WateringCan wateringCan = ConfigReader.CANS.get(nsID);
|
||||
if (wateringCan != null){
|
||||
int water = nbtItem.getInteger("WaterAmount");
|
||||
if (water > 0){
|
||||
nbtItem.setInteger("WaterAmount", --water);
|
||||
AdventureManager.playerSound(player, ConfigReader.Sounds.waterPotSource, ConfigReader.Sounds.waterPotKey);
|
||||
PotUtil.waterPot(wateringCan.getWidth(), wateringCan.getLength(), location.subtract(0.5,1,0.5), player.getLocation().getYaw());
|
||||
}
|
||||
if (ConfigReader.Message.hasWaterInfo)
|
||||
AdventureManager.playerActionbar(player,
|
||||
(ConfigReader.Message.waterLeft +
|
||||
ConfigReader.Message.waterFull.repeat(water) +
|
||||
ConfigReader.Message.waterEmpty.repeat(wateringCan.getMax() - water) +
|
||||
ConfigReader.Message.waterRight)
|
||||
.replace("{max_water}", String.valueOf(wateringCan.getMax()))
|
||||
.replace("{water}", String.valueOf(water)));
|
||||
if (ConfigReader.Basic.hasWaterLore){
|
||||
List<String> lores = nbtItem.getCompound("display").getStringList("Lore");
|
||||
lores.clear();
|
||||
String string =
|
||||
(ConfigReader.Basic.waterLeft +
|
||||
ConfigReader.Basic.waterFull.repeat(water) +
|
||||
ConfigReader.Basic.waterEmpty.repeat(wateringCan.getMax() - water) +
|
||||
ConfigReader.Basic.waterRight)
|
||||
.replace("{max_water}", String.valueOf(wateringCan.getMax()))
|
||||
.replace("{water}", String.valueOf(water));
|
||||
ConfigReader.Basic.waterLore.forEach(lore -> lores.add(GsonComponentSerializer.gson().serialize(MiniMessage.miniMessage().deserialize(lore.replace("{water_info}", string)))));
|
||||
}
|
||||
itemStack.setItemMeta(nbtItem.getItem().getItemMeta());
|
||||
return;
|
||||
}
|
||||
Fertilizer fertilizerConfig = ConfigReader.FERTILIZERS.get(id);
|
||||
if (fertilizerConfig != null){
|
||||
if (!fertilizerConfig.isBefore()){
|
||||
if (player.getGameMode() != GameMode.CREATIVE) itemStack.setAmount(itemStack.getAmount() - 1);
|
||||
PotUtil.addFertilizer(fertilizerConfig, event.getBukkitEntity().getLocation().subtract(0,1,0));
|
||||
AdventureManager.playerSound(player, ConfigReader.Sounds.useFertilizerSource, ConfigReader.Sounds.useFertilizerKey);
|
||||
}else {
|
||||
AdventureManager.playerMessage(player, ConfigReader.Message.prefix + ConfigReader.Message.beforePlant);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (ConfigReader.Message.hasCropInfo && nsID.equals(ConfigReader.Basic.soilDetector)){
|
||||
Fertilizer fertilizer = PotManager.Cache.get(LocUtil.fromLocation(location.subtract(0,1,0)));
|
||||
if (fertilizer != null){
|
||||
Fertilizer fertilizer1 = ConfigReader.FERTILIZERS.get(fertilizer.getKey());
|
||||
if (fertilizer1 == null) return;
|
||||
HoloUtil.showHolo(
|
||||
ConfigReader.Message.cropText
|
||||
.replace("{fertilizer}", fertilizer1.getName())
|
||||
.replace("{times}", String.valueOf(fertilizer.getTimes()))
|
||||
.replace("{max_times}", String.valueOf(fertilizer1.getTimes())),
|
||||
player,
|
||||
location.add(0, ConfigReader.Message.cropOffset, 0),
|
||||
ConfigReader.Message.cropTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (ConfigReader.Config.boneMeal && itemStack.getType() == Material.BONE_MEAL){
|
||||
Entity entity = event.getBukkitEntity();
|
||||
Location location = entity.getLocation();
|
||||
for (Integration integration : ConfigReader.Config.integration)
|
||||
if(!integration.canPlace(location, player)) return;
|
||||
if (!namespacedID.equals(ConfigReader.Basic.dead)){
|
||||
int nextStage = Integer.parseInt(namespacedID.substring(namespacedID.length()-1)) + 1;
|
||||
String next = StringUtils.chop(namespacedID) + nextStage;
|
||||
if (CustomFurniture.getInstance(next) != null){
|
||||
if (player.getGameMode() != GameMode.CREATIVE) itemStack.setAmount(itemStack.getAmount() - 1);
|
||||
AdventureManager.playerSound(player, ConfigReader.Sounds.boneMealSource, ConfigReader.Sounds.boneMealKey);
|
||||
if (Math.random() < ConfigReader.Config.boneMealChance){
|
||||
CustomFurniture.remove(entity, false);
|
||||
FurnitureUtil.placeCrop(next, location);
|
||||
location.getWorld().spawnParticle(ConfigReader.Config.boneMealSuccess, location.add(0,0.3,0),5,0.2,0.2,0.2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(ConfigReader.Config.rightClickHarvest && !ConfigReader.Config.needEmptyHand){
|
||||
rightClickHarvest(event.getFurniture(), player);
|
||||
}
|
||||
}
|
||||
else if(ConfigReader.Config.rightClickHarvest && !Objects.equals(ConfigReader.Basic.dead, namespacedID)){
|
||||
rightClickHarvest(event.getFurniture(), player);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 右键收获判定
|
||||
* @param crop 农作物实体
|
||||
* @param player 玩家
|
||||
*/
|
||||
private void rightClickHarvest(CustomFurniture crop, Player player) {
|
||||
Entity entity = crop.getArmorstand();
|
||||
Location location = entity.getLocation();
|
||||
for (Integration integration : ConfigReader.Config.integration)
|
||||
if(!integration.canBreak(location, player)) return;
|
||||
String namespacedID = crop.getNamespacedID();
|
||||
String[] cropNameList = StringUtils.split(namespacedID, "_");
|
||||
int nextStage = Integer.parseInt(cropNameList[2]) + 1;
|
||||
if (CustomFurniture.getInstance(StringUtils.chop(namespacedID) + nextStage) == null) {
|
||||
CustomFurniture.remove(entity, false);
|
||||
Crop cropInstance = ConfigReader.CROPS.get(StringUtils.split(cropNameList[0], ":")[1]);
|
||||
if (ConfigReader.Config.quality){
|
||||
ThreadLocalRandom current = ThreadLocalRandom.current();
|
||||
int random = current.nextInt(cropInstance.getMin(), cropInstance.getMax() + 1);
|
||||
World world = location.getWorld();
|
||||
Location itemLoc = location.clone().add(0,0.2,0);
|
||||
Fertilizer fertilizer = PotManager.Cache.get(LocUtil.fromLocation(location.clone().subtract(0,1,0)));
|
||||
List<String> commands = cropInstance.getCommands();
|
||||
if (commands != null)
|
||||
for (String command : commands)
|
||||
Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(), command.replace("{player}", player.getName()));
|
||||
if (ConfigReader.Config.skillXP != null && cropInstance.getSkillXP() != 0) ConfigReader.Config.skillXP.addXp(player, cropInstance.getSkillXP());
|
||||
if (cropInstance.getOtherLoots() != null) cropInstance.getOtherLoots().forEach(s -> location.getWorld().dropItem(itemLoc, CustomStack.getInstance(s).getItemStack()));
|
||||
if (fertilizer != null){
|
||||
if (fertilizer instanceof QualityCrop qualityCrop){
|
||||
int[] weights = qualityCrop.getChance();
|
||||
double weightTotal = weights[0] + weights[1] + weights[2];
|
||||
for (int i = 0; i < random; i++){
|
||||
double ran = Math.random();
|
||||
if (ran < weights[0]/(weightTotal)) world.dropItem(itemLoc, CustomStack.getInstance(cropInstance.getQuality_1()).getItemStack());
|
||||
else if(ran > 1 - weights[1]/(weightTotal)) world.dropItem(itemLoc, CustomStack.getInstance(cropInstance.getQuality_2()).getItemStack());
|
||||
else world.dropItem(itemLoc, CustomStack.getInstance(cropInstance.getQuality_3()).getItemStack());
|
||||
}
|
||||
}
|
||||
else DropUtil.normalDrop(cropInstance, random, itemLoc, world);
|
||||
}
|
||||
else DropUtil.normalDrop(cropInstance, random, itemLoc, world);
|
||||
}
|
||||
AdventureManager.playerSound(player, ConfigReader.Sounds.harvestSource, ConfigReader.Sounds.harvestKey);
|
||||
if(cropInstance.getReturnStage() != null){
|
||||
FurnitureUtil.placeCrop(cropInstance.getReturnStage(), location);
|
||||
SimpleLocation simpleLocation = LocUtil.fromLocation(location);
|
||||
CropManager.RemoveCache.remove(simpleLocation);
|
||||
CropManager.Cache.put(simpleLocation, player.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,260 @@
|
||||
package net.momirealms.customcrops.listener.itemframe;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NBTCompound;
|
||||
import de.tr7zw.changeme.nbtapi.NBTItem;
|
||||
import dev.lone.itemsadder.api.CustomBlock;
|
||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
||||
import net.momirealms.customcrops.ConfigReader;
|
||||
import net.momirealms.customcrops.datamanager.CropManager;
|
||||
import net.momirealms.customcrops.datamanager.PotManager;
|
||||
import net.momirealms.customcrops.datamanager.SeasonManager;
|
||||
import net.momirealms.customcrops.datamanager.SprinklerManager;
|
||||
import net.momirealms.customcrops.fertilizer.Fertilizer;
|
||||
import net.momirealms.customcrops.integrations.protection.Integration;
|
||||
import net.momirealms.customcrops.limits.CropsPerChunk;
|
||||
import net.momirealms.customcrops.limits.SprinklersPerChunk;
|
||||
import net.momirealms.customcrops.listener.JoinAndQuit;
|
||||
import net.momirealms.customcrops.objects.Crop;
|
||||
import net.momirealms.customcrops.objects.SimpleLocation;
|
||||
import net.momirealms.customcrops.objects.Sprinkler;
|
||||
import net.momirealms.customcrops.objects.WateringCan;
|
||||
import net.momirealms.customcrops.requirements.PlantingCondition;
|
||||
import net.momirealms.customcrops.requirements.Requirement;
|
||||
import net.momirealms.customcrops.utils.*;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.Action;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class RightClickI implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void onInteract(PlayerInteractEvent event){
|
||||
long time = System.currentTimeMillis();
|
||||
Player player = event.getPlayer();
|
||||
if (time - (JoinAndQuit.coolDown.getOrDefault(player, time - 200)) < 200) return;
|
||||
JoinAndQuit.coolDown.put(player, time);
|
||||
Action action = event.getAction();
|
||||
if (action == Action.RIGHT_CLICK_AIR || action == Action.RIGHT_CLICK_BLOCK){
|
||||
ItemStack itemStack = event.getItem();
|
||||
if (itemStack != null && itemStack.getType() != Material.AIR){
|
||||
NBTItem nbtItem = new NBTItem(itemStack);
|
||||
NBTCompound nbtCompound = nbtItem.getCompound("itemsadder");
|
||||
if (nbtCompound != null){
|
||||
String id = nbtCompound.getString("id");
|
||||
String namespace = nbtCompound.getString("namespace");
|
||||
String itemNID = namespace + ":" + id;
|
||||
if (id.endsWith("_seeds") && action == Action.RIGHT_CLICK_BLOCK && event.getBlockFace() == BlockFace.UP){
|
||||
String cropName = StringUtils.remove(id, "_seeds");
|
||||
Crop cropInstance = ConfigReader.CROPS.get(cropName);
|
||||
if (cropInstance != null){
|
||||
Block block = event.getClickedBlock();
|
||||
CustomBlock customBlock = CustomBlock.byAlreadyPlaced(block);
|
||||
if (customBlock == null) return;
|
||||
String namespacedID = customBlock.getNamespacedID();
|
||||
if (namespacedID.equals(ConfigReader.Basic.pot) || namespacedID.equals(ConfigReader.Basic.watered_pot)){
|
||||
Location location = block.getLocation().add(0,1,0); //已+1
|
||||
for (Integration integration : ConfigReader.Config.integration)
|
||||
if(!integration.canPlace(location, player)) return;
|
||||
if (FurnitureUtil.getNamespacedID(location.clone().add(0.5,0.1,0.5)) != null) return;
|
||||
PlantingCondition plantingCondition = new PlantingCondition(player, location);
|
||||
if (cropInstance.getRequirements() != null)
|
||||
for (Requirement requirement : cropInstance.getRequirements())
|
||||
if (!requirement.canPlant(plantingCondition)) return;
|
||||
Label_out:
|
||||
if (ConfigReader.Season.enable && cropInstance.getSeasons() != null){
|
||||
if (!ConfigReader.Config.allWorld){
|
||||
for (String season : cropInstance.getSeasons())
|
||||
if (season.equals(SeasonManager.SEASON.get(location.getWorld().getName())))
|
||||
break Label_out;
|
||||
}else {
|
||||
for(String season : cropInstance.getSeasons())
|
||||
if (season.equals(SeasonManager.SEASON.get(ConfigReader.Config.referenceWorld)))
|
||||
break Label_out;
|
||||
}
|
||||
if(ConfigReader.Season.greenhouse){
|
||||
for(int i = 1; i <= ConfigReader.Season.range; i++){
|
||||
CustomBlock cb = CustomBlock.byAlreadyPlaced(location.clone().add(0,i,0).getBlock());
|
||||
if (cb != null)
|
||||
if(cb.getNamespacedID().equalsIgnoreCase(ConfigReader.Basic.glass))
|
||||
break Label_out;
|
||||
}
|
||||
}
|
||||
if (ConfigReader.Config.nwSeason) AdventureManager.playerMessage(player, ConfigReader.Message.prefix + ConfigReader.Message.badSeason);
|
||||
if (ConfigReader.Config.pwSeason) return;
|
||||
}
|
||||
if (location.getBlock().getType() != Material.AIR) return;
|
||||
if (player.getGameMode() != GameMode.CREATIVE) itemStack.setAmount(itemStack.getAmount() - 1);
|
||||
if (CropsPerChunk.isLimited(location)){
|
||||
AdventureManager.playerMessage(player,ConfigReader.Message.prefix + ConfigReader.Message.crop_limit.replace("{max}", String.valueOf(ConfigReader.Config.cropLimit)));
|
||||
return;
|
||||
}
|
||||
SimpleLocation simpleLocation = LocUtil.fromLocation(location);
|
||||
CropManager.RemoveCache.remove(simpleLocation);
|
||||
CropManager.Cache.put(simpleLocation, player.getName());
|
||||
FurnitureUtil.placeCrop(namespace + ":" + cropName + "_stage_1", location);
|
||||
AdventureManager.playerSound(player, ConfigReader.Sounds.plantSeedSource, ConfigReader.Sounds.plantSeedKey);
|
||||
}
|
||||
}else AdventureManager.playerMessage(player, ConfigReader.Message.prefix + ConfigReader.Message.not_configed);
|
||||
return;
|
||||
}
|
||||
WateringCan wateringCan = ConfigReader.CANS.get(itemNID);
|
||||
if (wateringCan != null){
|
||||
int water = nbtItem.getInteger("WaterAmount");
|
||||
List<Block> lineOfSight = player.getLineOfSight(null, 5);
|
||||
for (Block block : lineOfSight) {
|
||||
if (block.getType() == Material.WATER) {
|
||||
if (wateringCan.getMax() > water){
|
||||
water += ConfigReader.Config.waterCanRefill;
|
||||
if (water > wateringCan.getMax()) water = wateringCan.getMax();
|
||||
nbtItem.setInteger("WaterAmount", water);
|
||||
player.getWorld().playSound(player.getLocation(), Sound.ITEM_BUCKET_FILL,1,1);
|
||||
if (ConfigReader.Message.hasWaterInfo)
|
||||
AdventureManager.playerActionbar(player,
|
||||
(ConfigReader.Message.waterLeft +
|
||||
ConfigReader.Message.waterFull.repeat(water) +
|
||||
ConfigReader.Message.waterEmpty.repeat(wateringCan.getMax() - water) +
|
||||
ConfigReader.Message.waterRight)
|
||||
.replace("{max_water}", String.valueOf(wateringCan.getMax()))
|
||||
.replace("{water}", String.valueOf(water)));
|
||||
if (ConfigReader.Basic.hasWaterLore){
|
||||
List<String> lores = nbtItem.getCompound("display").getStringList("Lore");
|
||||
lores.clear();
|
||||
String string =
|
||||
(ConfigReader.Basic.waterLeft +
|
||||
ConfigReader.Basic.waterFull.repeat(water) +
|
||||
ConfigReader.Basic.waterEmpty.repeat(wateringCan.getMax() - water) +
|
||||
ConfigReader.Basic.waterRight)
|
||||
.replace("{max_water}", String.valueOf(wateringCan.getMax()))
|
||||
.replace("{water}", String.valueOf(water));
|
||||
ConfigReader.Basic.waterLore.forEach(lore -> lores.add(GsonComponentSerializer.gson().serialize(MiniMessage.miniMessage().deserialize(lore.replace("{water_info}", string)))));
|
||||
}
|
||||
if (ConfigReader.Config.hasParticle) player.getWorld().spawnParticle(Particle.WATER_SPLASH, block.getLocation().add(0.5,1, 0.5),15,0.1,0.1,0.1);
|
||||
itemStack.setItemMeta(nbtItem.getItem().getItemMeta());
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(action == Action.RIGHT_CLICK_BLOCK){
|
||||
Block block = event.getClickedBlock();
|
||||
CustomBlock customBlock = CustomBlock.byAlreadyPlaced(block);
|
||||
if (customBlock == null) return;
|
||||
for (Integration integration : ConfigReader.Config.integration)
|
||||
if(!integration.canPlace(block.getLocation(), player)) return;
|
||||
String namespacedID = customBlock.getNamespacedID();
|
||||
if ((namespacedID.equals(ConfigReader.Basic.pot) || namespacedID.equals(ConfigReader.Basic.watered_pot)) && event.getBlockFace() == BlockFace.UP){
|
||||
if (water > 0){
|
||||
nbtItem.setInteger("WaterAmount", --water);
|
||||
AdventureManager.playerSound(player, ConfigReader.Sounds.waterPotSource, ConfigReader.Sounds.waterPotKey);
|
||||
PotUtil.waterPot(wateringCan.getWidth(), wateringCan.getLength(), block.getLocation(), player.getLocation().getYaw());
|
||||
}
|
||||
if (ConfigReader.Message.hasWaterInfo)
|
||||
AdventureManager.playerActionbar(player,
|
||||
(ConfigReader.Message.waterLeft +
|
||||
ConfigReader.Message.waterFull.repeat(water) +
|
||||
ConfigReader.Message.waterEmpty.repeat(wateringCan.getMax() - water) +
|
||||
ConfigReader.Message.waterRight)
|
||||
.replace("{max_water}", String.valueOf(wateringCan.getMax()))
|
||||
.replace("{water}", String.valueOf(water)));
|
||||
if (ConfigReader.Basic.hasWaterLore){
|
||||
List<String> lores = nbtItem.getCompound("display").getStringList("Lore");
|
||||
lores.clear();
|
||||
String string =
|
||||
(ConfigReader.Basic.waterLeft +
|
||||
ConfigReader.Basic.waterFull.repeat(water) +
|
||||
ConfigReader.Basic.waterEmpty.repeat(wateringCan.getMax() - water) +
|
||||
ConfigReader.Basic.waterRight)
|
||||
.replace("{max_water}", String.valueOf(wateringCan.getMax()))
|
||||
.replace("{water}", String.valueOf(water));
|
||||
ConfigReader.Basic.waterLore.forEach(lore -> lores.add(GsonComponentSerializer.gson().serialize(MiniMessage.miniMessage().deserialize(lore.replace("{water_info}", string)))));
|
||||
}
|
||||
itemStack.setItemMeta(nbtItem.getItem().getItemMeta());
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
Fertilizer fertilizerConfig = ConfigReader.FERTILIZERS.get(id);
|
||||
if (fertilizerConfig != null && action == Action.RIGHT_CLICK_BLOCK){
|
||||
Block block = event.getClickedBlock();
|
||||
CustomBlock customBlock = CustomBlock.byAlreadyPlaced(block);
|
||||
if (customBlock == null) return;
|
||||
for (Integration integration : ConfigReader.Config.integration)
|
||||
if(!integration.canPlace(block.getLocation(), player)) return;
|
||||
String namespacedID = customBlock.getNamespacedID();
|
||||
if (namespacedID.equals(ConfigReader.Basic.pot) || namespacedID.equals(ConfigReader.Basic.watered_pot)){
|
||||
String furniture = FurnitureUtil.getNamespacedID(block.getLocation().clone().add(0.5,1.1,0.5));
|
||||
if (furniture != null){
|
||||
if (fertilizerConfig.isBefore() && furniture.contains("_stage_")){
|
||||
AdventureManager.playerMessage(player, ConfigReader.Message.prefix + ConfigReader.Message.beforePlant);
|
||||
return;
|
||||
}else {
|
||||
if (player.getGameMode() != GameMode.CREATIVE) itemStack.setAmount(itemStack.getAmount() - 1);
|
||||
AdventureManager.playerSound(player, ConfigReader.Sounds.useFertilizerSource, ConfigReader.Sounds.useFertilizerKey);
|
||||
PotUtil.addFertilizer(fertilizerConfig, block.getLocation());
|
||||
}
|
||||
}else {
|
||||
if (player.getGameMode() != GameMode.CREATIVE) itemStack.setAmount(itemStack.getAmount() - 1);
|
||||
AdventureManager.playerSound(player, ConfigReader.Sounds.useFertilizerSource, ConfigReader.Sounds.useFertilizerKey);
|
||||
PotUtil.addFertilizer(fertilizerConfig, block.getLocation());
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
Sprinkler sprinkler = ConfigReader.SPRINKLERS.get(itemNID);
|
||||
if (sprinkler != null && action == Action.RIGHT_CLICK_BLOCK && event.getBlockFace() == BlockFace.UP){
|
||||
Location location = event.getClickedBlock().getLocation();
|
||||
for (Integration integration : ConfigReader.Config.integration)
|
||||
if (!integration.canPlace(location, player)) return;
|
||||
if (FurnitureUtil.isSprinkler(location.clone().add(0.5, 1.5, 0.5))) return;
|
||||
if (SprinklersPerChunk.isLimited(location)){
|
||||
AdventureManager.playerMessage(player, ConfigReader.Message.prefix + ConfigReader.Message.sprinkler_limit.replace("{max}", String.valueOf(ConfigReader.Config.sprinklerLimit)));
|
||||
return;
|
||||
}
|
||||
Sprinkler sprinklerData = new Sprinkler(sprinkler.getRange(), 0);
|
||||
sprinklerData.setPlayer(player.getName());
|
||||
if (player.getGameMode() != GameMode.CREATIVE) itemStack.setAmount(itemStack.getAmount() - 1);
|
||||
SimpleLocation simpleLocation = LocUtil.fromLocation(location.add(0,1,0));
|
||||
SprinklerManager.Cache.put(simpleLocation, sprinklerData);
|
||||
SprinklerManager.RemoveCache.remove(simpleLocation);
|
||||
FurnitureUtil.placeFurniture(sprinkler.getNamespacedID_2(),location);
|
||||
AdventureManager.playerSound(player, ConfigReader.Sounds.placeSprinklerSource, ConfigReader.Sounds.placeSprinklerKey);
|
||||
return;
|
||||
}
|
||||
if (ConfigReader.Message.hasCropInfo && itemNID.equals(ConfigReader.Basic.soilDetector) && action == Action.RIGHT_CLICK_BLOCK){
|
||||
Block block = event.getClickedBlock();
|
||||
CustomBlock customBlock = CustomBlock.byAlreadyPlaced(block);
|
||||
if (customBlock == null) return;
|
||||
for (Integration integration : ConfigReader.Config.integration) if(!integration.canPlace(block.getLocation(), player)) return;
|
||||
String namespacedID = customBlock.getNamespacedID();
|
||||
if(namespacedID.equals(ConfigReader.Basic.pot) || namespacedID.equals(ConfigReader.Basic.watered_pot)){
|
||||
Location location = block.getLocation();
|
||||
Fertilizer fertilizer = PotManager.Cache.get(LocUtil.fromLocation(block.getLocation()));
|
||||
if (fertilizer != null){
|
||||
Fertilizer config = ConfigReader.FERTILIZERS.get(fertilizer.getKey());
|
||||
String name = config.getName();
|
||||
int max_times = config.getTimes();
|
||||
HoloUtil.showHolo(
|
||||
ConfigReader.Message.cropText
|
||||
.replace("{fertilizer}", name)
|
||||
.replace("{times}", String.valueOf(fertilizer.getTimes()))
|
||||
.replace("{max_times}", String.valueOf(max_times)),
|
||||
player,
|
||||
location.add(0.5,ConfigReader.Message.cropOffset,0.5),
|
||||
ConfigReader.Message.cropTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,19 +15,22 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.momirealms.customcrops.listener;
|
||||
package net.momirealms.customcrops.listener.tripwire;
|
||||
|
||||
import dev.lone.itemsadder.api.CustomBlock;
|
||||
import dev.lone.itemsadder.api.CustomStack;
|
||||
import dev.lone.itemsadder.api.Events.CustomBlockBreakEvent;
|
||||
import net.momirealms.customcrops.ConfigReader;
|
||||
import net.momirealms.customcrops.CustomCrops;
|
||||
import net.momirealms.customcrops.datamanager.CropManager;
|
||||
import net.momirealms.customcrops.datamanager.PotManager;
|
||||
import net.momirealms.customcrops.fertilizer.Fertilizer;
|
||||
import net.momirealms.customcrops.fertilizer.QualityCrop;
|
||||
import net.momirealms.customcrops.integrations.protection.Integration;
|
||||
import net.momirealms.customcrops.objects.Crop;
|
||||
import net.momirealms.customcrops.objects.SimpleLocation;
|
||||
import net.momirealms.customcrops.utils.DropUtil;
|
||||
import net.momirealms.customcrops.utils.LocUtil;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
@@ -43,7 +46,7 @@ import org.bukkit.inventory.ItemStack;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
public class BreakBlock implements Listener {
|
||||
public class BreakBlockT implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void onBreak(CustomBlockBreakEvent event){
|
||||
@@ -53,6 +56,10 @@ public class BreakBlock implements Listener {
|
||||
Location location = event.getBlock().getLocation();
|
||||
for (Integration integration : ConfigReader.Config.integration)
|
||||
if(!integration.canBreak(location, player)) return;
|
||||
SimpleLocation simpleLocation = LocUtil.fromLocation(location);
|
||||
if (CropManager.Cache.remove(simpleLocation) == null){
|
||||
CropManager.RemoveCache.add(simpleLocation);
|
||||
}
|
||||
if (player.getInventory().getItemInMainHand().containsEnchantment(Enchantment.SILK_TOUCH) || player.getInventory().getItemInMainHand().getType() == Material.SHEARS){
|
||||
event.setCancelled(true);
|
||||
CustomBlock.place(namespacedId, location);
|
||||
@@ -72,7 +79,7 @@ public class BreakBlock implements Listener {
|
||||
Location itemLoc = location.clone().add(0.5,0.2,0.5);
|
||||
World world = location.getWorld();
|
||||
List<String> commands = cropInstance.getCommands();
|
||||
Fertilizer fertilizer = PotManager.Cache.get(SimpleLocation.fromLocation(location.clone().subtract(0,1,0)));
|
||||
Fertilizer fertilizer = PotManager.Cache.get(LocUtil.fromLocation(location.clone().subtract(0,1,0)));
|
||||
if (commands != null)
|
||||
Bukkit.getScheduler().runTask(CustomCrops.plugin, ()-> {
|
||||
for (String command : commands)
|
||||
@@ -93,15 +100,15 @@ public class BreakBlock implements Listener {
|
||||
}
|
||||
});
|
||||
}
|
||||
else Bukkit.getScheduler().runTask(CustomCrops.plugin, ()-> normalDrop(cropInstance, random, itemLoc, world));
|
||||
else Bukkit.getScheduler().runTask(CustomCrops.plugin, ()-> DropUtil.normalDrop(cropInstance, random, itemLoc, world));
|
||||
}
|
||||
else Bukkit.getScheduler().runTask(CustomCrops.plugin, ()-> normalDrop(cropInstance, random, itemLoc, world));
|
||||
else Bukkit.getScheduler().runTask(CustomCrops.plugin, ()-> DropUtil.normalDrop(cropInstance, random, itemLoc, world));
|
||||
});
|
||||
}
|
||||
}
|
||||
else if(namespacedId.equalsIgnoreCase(ConfigReader.Basic.watered_pot) || namespacedId.equalsIgnoreCase(ConfigReader.Basic.pot)){
|
||||
Location location = event.getBlock().getLocation();
|
||||
PotManager.Cache.remove(SimpleLocation.fromLocation(location));
|
||||
PotManager.Cache.remove(LocUtil.fromLocation(location));
|
||||
World world = location.getWorld();
|
||||
Block blockUp = location.add(0,1,0).getBlock();
|
||||
for (Integration integration : ConfigReader.Config.integration)
|
||||
@@ -111,6 +118,10 @@ public class BreakBlock implements Listener {
|
||||
String cropNamespacedId = customBlock.getNamespacedID();
|
||||
if(cropNamespacedId.contains("_stage_")){
|
||||
CustomBlock.remove(location);
|
||||
SimpleLocation simpleLocation = LocUtil.fromLocation(location);
|
||||
if (CropManager.Cache.remove(simpleLocation) == null){
|
||||
CropManager.RemoveCache.add(simpleLocation);
|
||||
}
|
||||
if (cropNamespacedId.equals(ConfigReader.Basic.dead)) return;
|
||||
if (ConfigReader.Config.quality){
|
||||
String[] cropNameList = StringUtils.split(StringUtils.split(cropNamespacedId, ":")[1], "_");
|
||||
@@ -120,7 +131,7 @@ public class BreakBlock implements Listener {
|
||||
ThreadLocalRandom current = ThreadLocalRandom.current();
|
||||
int random = current.nextInt(cropInstance.getMin(), cropInstance.getMax() + 1);
|
||||
Location itemLoc = location.clone().add(0.5,0.2,0.5);
|
||||
Fertilizer fertilizer = PotManager.Cache.get(SimpleLocation.fromLocation(location.clone().subtract(0,1,0)));
|
||||
Fertilizer fertilizer = PotManager.Cache.get(LocUtil.fromLocation(location.clone().subtract(0,1,0)));
|
||||
if (fertilizer != null){
|
||||
if (fertilizer instanceof QualityCrop qualityCrop){
|
||||
int[] weights = qualityCrop.getChance();
|
||||
@@ -133,35 +144,14 @@ public class BreakBlock implements Listener {
|
||||
}
|
||||
}
|
||||
}
|
||||
else normalDrop(cropInstance, random, itemLoc, world);
|
||||
else DropUtil.normalDrop(cropInstance, random, itemLoc, world);
|
||||
return;
|
||||
}
|
||||
}
|
||||
for (ItemStack itemStack : customBlock.getLoot())
|
||||
world.dropItem(location.clone().add(0.5, 0.2, 0.5), itemStack);
|
||||
CustomBlock.remove(location);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 没有品质肥料下的普通掉落
|
||||
* @param cropInstance 农作物
|
||||
* @param random 随机农作物数量
|
||||
* @param itemLoc 掉落物位置
|
||||
* @param world 世界
|
||||
*/
|
||||
static void normalDrop(Crop cropInstance, int random, Location itemLoc, World world) {
|
||||
for (int i = 0; i < random; i++){
|
||||
double ran = Math.random();
|
||||
if (ran < ConfigReader.Config.quality_1){
|
||||
world.dropItem(itemLoc, CustomStack.getInstance(cropInstance.getQuality_1()).getItemStack());
|
||||
}else if(ran > ConfigReader.Config.quality_2){
|
||||
world.dropItem(itemLoc, CustomStack.getInstance(cropInstance.getQuality_2()).getItemStack());
|
||||
}else {
|
||||
world.dropItem(itemLoc, CustomStack.getInstance(cropInstance.getQuality_3()).getItemStack());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,22 +1,24 @@
|
||||
package net.momirealms.customcrops.listener;
|
||||
package net.momirealms.customcrops.listener.tripwire;
|
||||
|
||||
import dev.lone.itemsadder.api.Events.FurnitureBreakEvent;
|
||||
import net.momirealms.customcrops.ConfigReader;
|
||||
import net.momirealms.customcrops.datamanager.SprinklerManager;
|
||||
import net.momirealms.customcrops.objects.SimpleLocation;
|
||||
import net.momirealms.customcrops.objects.Sprinkler;
|
||||
import net.momirealms.customcrops.utils.LocUtil;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
public class BreakFurniture implements Listener {
|
||||
public class BreakFurnitureT implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void onBreakFurniture(FurnitureBreakEvent event){
|
||||
Sprinkler config = ConfigReader.SPRINKLERS.get(event.getNamespacedID());
|
||||
if (config != null){
|
||||
SimpleLocation simpleLocation = SimpleLocation.fromLocation(event.getBukkitEntity().getLocation());
|
||||
SprinklerManager.Cache.remove(simpleLocation);
|
||||
SimpleLocation simpleLocation = LocUtil.fromLocation(event.getBukkitEntity().getLocation());
|
||||
if(SprinklerManager.Cache.remove(simpleLocation) == null){
|
||||
SprinklerManager.RemoveCache.add(simpleLocation);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.momirealms.customcrops.listener;
|
||||
package net.momirealms.customcrops.listener.tripwire;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NBTCompound;
|
||||
import de.tr7zw.changeme.nbtapi.NBTItem;
|
||||
@@ -25,6 +25,7 @@ import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
||||
import net.momirealms.customcrops.ConfigReader;
|
||||
import net.momirealms.customcrops.CustomCrops;
|
||||
import net.momirealms.customcrops.datamanager.SprinklerManager;
|
||||
import net.momirealms.customcrops.listener.JoinAndQuit;
|
||||
import net.momirealms.customcrops.objects.SimpleLocation;
|
||||
import net.momirealms.customcrops.objects.Sprinkler;
|
||||
import net.momirealms.customcrops.objects.WateringCan;
|
||||
@@ -40,14 +41,7 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public class InteractEntity implements Listener {
|
||||
|
||||
private final CustomCrops plugin;
|
||||
private final HashMap<Player, Long> coolDown = new HashMap<>();
|
||||
|
||||
public InteractEntity(CustomCrops plugin){
|
||||
this.plugin = plugin;
|
||||
}
|
||||
public class InteractFurnitureT implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void onEntityInteract(FurnitureInteractEvent event){
|
||||
@@ -55,8 +49,8 @@ public class InteractEntity implements Listener {
|
||||
if(config != null){
|
||||
long time = System.currentTimeMillis();
|
||||
Player player = event.getPlayer();
|
||||
if (time - (coolDown.getOrDefault(player, time - 200)) < 200) return;
|
||||
coolDown.put(player, time);
|
||||
if (time - (JoinAndQuit.coolDown.getOrDefault(player, time - 200)) < 200) return;
|
||||
JoinAndQuit.coolDown.put(player, time);
|
||||
ItemStack itemStack = player.getInventory().getItemInMainHand();
|
||||
Location location = event.getBukkitEntity().getLocation();
|
||||
String world = location.getWorld().getName();
|
||||
@@ -65,7 +59,7 @@ public class InteractEntity implements Listener {
|
||||
int maxWater = config.getWater();
|
||||
int currentWater = 0;
|
||||
Location loc = location.clone().subtract(0,1,0).getBlock().getLocation().add(0,1,0);
|
||||
Sprinkler sprinkler = SprinklerManager.Cache.get(SimpleLocation.fromLocation(loc));
|
||||
Sprinkler sprinkler = SprinklerManager.Cache.get(LocUtil.fromLocation(loc));
|
||||
if (itemStack.getType() == Material.WATER_BUCKET){
|
||||
itemStack.setType(Material.BUCKET);
|
||||
if (sprinkler != null){
|
||||
@@ -75,25 +69,25 @@ public class InteractEntity implements Listener {
|
||||
sprinkler.setWater(currentWater);
|
||||
}else {
|
||||
String path = world + "." + x / 16 + "," + z / 16 + "." + x + "," + location.getBlockY() + "," + z ;
|
||||
currentWater = plugin.getSprinklerManager().data.getInt(path+ ".water");
|
||||
currentWater = SprinklerManager.data.getInt(path+ ".water");
|
||||
currentWater += ConfigReader.Config.sprinklerRefill;
|
||||
if (currentWater > maxWater) currentWater = maxWater;
|
||||
plugin.getSprinklerManager().data.set(path + ".water", currentWater);
|
||||
plugin.getSprinklerManager().data.set(path + ".range", config.getRange());
|
||||
SprinklerManager.data.set(path + ".water", currentWater);
|
||||
SprinklerManager.data.set(path + ".range", config.getRange());
|
||||
}
|
||||
AdventureManager.playerSound(player, ConfigReader.Sounds.addWaterToSprinklerSource, ConfigReader.Sounds.addWaterToSprinklerKey);
|
||||
}
|
||||
else {
|
||||
if (ConfigReader.Config.canAddWater && itemStack.getType() != Material.AIR){
|
||||
NBTItem nbtItem = new NBTItem(itemStack);
|
||||
int water = nbtItem.getInteger("WaterAmount");
|
||||
if (water > 0){
|
||||
NBTCompound nbtCompound = nbtItem.getCompound("itemsadder");
|
||||
if (nbtCompound != null) {
|
||||
String id = nbtCompound.getString("id");
|
||||
String namespace = nbtCompound.getString("namespace");
|
||||
WateringCan wateringCan = ConfigReader.CANS.get(namespace + ":" + id);
|
||||
if (wateringCan != null) {
|
||||
int water = nbtItem.getInteger("WaterAmount");
|
||||
if (water > 0){
|
||||
nbtItem.setInteger("WaterAmount", --water);
|
||||
AdventureManager.playerSound(player, ConfigReader.Sounds.addWaterToSprinklerSource, ConfigReader.Sounds.addWaterToSprinklerKey);
|
||||
if (sprinkler != null){
|
||||
@@ -102,11 +96,16 @@ public class InteractEntity implements Listener {
|
||||
if (currentWater > maxWater) currentWater = maxWater;
|
||||
sprinkler.setWater(currentWater);
|
||||
}else {
|
||||
String path = world + "." + x / 16 + "," + z / 16 + "." + x + "," + location.getBlockY() + "," + z + ".water";
|
||||
currentWater = plugin.getSprinklerManager().data.getInt(path);
|
||||
String path = world + "." + x / 16 + "," + z / 16 + "." + x + "," + location.getBlockY() + "," + z ;
|
||||
currentWater = SprinklerManager.data.getInt(path + ".water");
|
||||
currentWater++;
|
||||
if (currentWater > maxWater) currentWater = maxWater;
|
||||
plugin.getSprinklerManager().data.set(path, currentWater);
|
||||
SprinklerManager.data.set(path + ".water", currentWater);
|
||||
SprinklerManager.data.set(path + ".range", config.getRange());
|
||||
}
|
||||
}
|
||||
else {
|
||||
currentWater = SprinklerManager.getCurrentWater(location, world, x, z, sprinkler);
|
||||
}
|
||||
if (ConfigReader.Message.hasWaterInfo){
|
||||
AdventureManager.playerActionbar(player,
|
||||
@@ -132,10 +131,9 @@ public class InteractEntity implements Listener {
|
||||
itemStack.setItemMeta(nbtItem.getItem().getItemMeta());
|
||||
}
|
||||
}
|
||||
else currentWater = SprinklerManager.getCurrentWater(location, world, x, z, sprinkler);
|
||||
}
|
||||
else currentWater = getCurrentWater(location, world, x, z, sprinkler);
|
||||
}
|
||||
else currentWater = getCurrentWater(location, world, x, z, sprinkler);
|
||||
else currentWater = SprinklerManager.getCurrentWater(location, world, x, z, sprinkler);
|
||||
}
|
||||
if (ConfigReader.Message.hasSprinklerInfo)
|
||||
HoloUtil.showHolo(
|
||||
@@ -150,23 +148,4 @@ public class InteractEntity implements Listener {
|
||||
ConfigReader.Message.sprinklerTime);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取某个洒水器的水量
|
||||
* @param location 洒水器位置
|
||||
* @param world 世界
|
||||
* @param x 坐标
|
||||
* @param z 坐标
|
||||
* @param sprinkler 洒水器类型
|
||||
* @return 水量
|
||||
*/
|
||||
private int getCurrentWater(Location location, String world, int x, int z, Sprinkler sprinkler) {
|
||||
int currentWater;
|
||||
if (sprinkler != null) currentWater = sprinkler.getWater();
|
||||
else {
|
||||
String path = world + "." + x / 16 + "," + z / 16 + "." + x + "," + location.getBlockY() + "," + z + ".water";
|
||||
currentWater = plugin.getSprinklerManager().data.getInt(path);
|
||||
}
|
||||
return currentWater;
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.momirealms.customcrops.listener;
|
||||
package net.momirealms.customcrops.listener.tripwire;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NBTCompound;
|
||||
import de.tr7zw.changeme.nbtapi.NBTItem;
|
||||
@@ -30,11 +30,10 @@ import net.momirealms.customcrops.datamanager.SeasonManager;
|
||||
import net.momirealms.customcrops.datamanager.SprinklerManager;
|
||||
import net.momirealms.customcrops.fertilizer.Fertilizer;
|
||||
import net.momirealms.customcrops.fertilizer.QualityCrop;
|
||||
import net.momirealms.customcrops.fertilizer.RetainingSoil;
|
||||
import net.momirealms.customcrops.fertilizer.SpeedGrow;
|
||||
import net.momirealms.customcrops.integrations.protection.Integration;
|
||||
import net.momirealms.customcrops.limits.CropsPerChunk;
|
||||
import net.momirealms.customcrops.limits.SprinklersPerChunk;
|
||||
import net.momirealms.customcrops.listener.JoinAndQuit;
|
||||
import net.momirealms.customcrops.objects.Crop;
|
||||
import net.momirealms.customcrops.objects.SimpleLocation;
|
||||
import net.momirealms.customcrops.objects.Sprinkler;
|
||||
@@ -51,23 +50,19 @@ import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.Action;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
public class RightClick implements Listener {
|
||||
|
||||
private final HashMap<Player, Long> coolDown = new HashMap<>();
|
||||
public class RightClickT implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void onInteract(PlayerInteractEvent event){
|
||||
long time = System.currentTimeMillis();
|
||||
Player player = event.getPlayer();
|
||||
if (time - (coolDown.getOrDefault(player, time - 250)) < 250) return;
|
||||
coolDown.put(player, time);
|
||||
if (time - (JoinAndQuit.coolDown.getOrDefault(player, time - 200)) < 200) return;
|
||||
JoinAndQuit.coolDown.put(player, time);
|
||||
Action action = event.getAction();
|
||||
if (action == Action.RIGHT_CLICK_AIR || action == Action.RIGHT_CLICK_BLOCK){
|
||||
ItemStack itemStack = event.getItem();
|
||||
@@ -90,7 +85,7 @@ public class RightClick implements Listener {
|
||||
Location location = block.getLocation().add(0,1,0); //已+1
|
||||
for (Integration integration : ConfigReader.Config.integration)
|
||||
if(!integration.canPlace(location, player)) return;
|
||||
if(IAFurnitureUtil.isSprinkler(location.clone().add(0.5, 0.5, 0.5))) return;
|
||||
if(FurnitureUtil.isSprinkler(location.clone().add(0.5, 0.5, 0.5))) return;
|
||||
PlantingCondition plantingCondition = new PlantingCondition(player, location);
|
||||
if (cropInstance.getRequirements() != null)
|
||||
for (Requirement requirement : cropInstance.getRequirements())
|
||||
@@ -123,7 +118,9 @@ public class RightClick implements Listener {
|
||||
AdventureManager.playerMessage(player,ConfigReader.Message.prefix + ConfigReader.Message.crop_limit.replace("{max}", String.valueOf(ConfigReader.Config.cropLimit)));
|
||||
return;
|
||||
}
|
||||
CropManager.Cache.put(location, player.getName());
|
||||
SimpleLocation simpleLocation = LocUtil.fromLocation(location);
|
||||
CropManager.RemoveCache.remove(simpleLocation);
|
||||
CropManager.Cache.put(simpleLocation, player.getName());
|
||||
CustomBlock.place((namespace + ":" + cropName + "_stage_1"), location);
|
||||
AdventureManager.playerSound(player, ConfigReader.Sounds.plantSeedSource, ConfigReader.Sounds.plantSeedKey);
|
||||
}
|
||||
@@ -167,7 +164,7 @@ public class RightClick implements Listener {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(water != 0 && action == Action.RIGHT_CLICK_BLOCK){
|
||||
if(action == Action.RIGHT_CLICK_BLOCK){
|
||||
Block block = event.getClickedBlock();
|
||||
CustomBlock customBlock = CustomBlock.byAlreadyPlaced(block);
|
||||
if (customBlock == null) return;
|
||||
@@ -175,53 +172,57 @@ public class RightClick implements Listener {
|
||||
if(!integration.canPlace(block.getLocation(), player)) return;
|
||||
String namespacedID = customBlock.getNamespacedID();
|
||||
if ((namespacedID.equals(ConfigReader.Basic.pot) || namespacedID.equals(ConfigReader.Basic.watered_pot)) && event.getBlockFace() == BlockFace.UP){
|
||||
nbtItem.setInteger("WaterAmount", water - 1);
|
||||
if (water > 0){
|
||||
nbtItem.setInteger("WaterAmount", --water);
|
||||
AdventureManager.playerSound(player, ConfigReader.Sounds.waterPotSource, ConfigReader.Sounds.waterPotKey);
|
||||
waterPot(wateringCan.getWidth(), wateringCan.getLength(), block.getLocation(), player.getLocation().getYaw());
|
||||
PotUtil.waterPot(wateringCan.getWidth(), wateringCan.getLength(), block.getLocation(), player.getLocation().getYaw());
|
||||
}
|
||||
if (ConfigReader.Message.hasWaterInfo)
|
||||
AdventureManager.playerActionbar(player,
|
||||
(ConfigReader.Message.waterLeft +
|
||||
ConfigReader.Message.waterFull.repeat(water - 1) +
|
||||
ConfigReader.Message.waterEmpty.repeat(wateringCan.getMax() - water + 1) +
|
||||
ConfigReader.Message.waterFull.repeat(water) +
|
||||
ConfigReader.Message.waterEmpty.repeat(wateringCan.getMax() - water) +
|
||||
ConfigReader.Message.waterRight)
|
||||
.replace("{max_water}", String.valueOf(wateringCan.getMax()))
|
||||
.replace("{water}", String.valueOf(water -1)));
|
||||
.replace("{water}", String.valueOf(water)));
|
||||
if (ConfigReader.Basic.hasWaterLore){
|
||||
List<String> lores = nbtItem.getCompound("display").getStringList("Lore");
|
||||
lores.clear();
|
||||
String string =
|
||||
(ConfigReader.Basic.waterLeft +
|
||||
ConfigReader.Basic.waterFull.repeat(water - 1) +
|
||||
ConfigReader.Basic.waterEmpty.repeat(wateringCan.getMax() - water + 1) +
|
||||
ConfigReader.Basic.waterFull.repeat(water) +
|
||||
ConfigReader.Basic.waterEmpty.repeat(wateringCan.getMax() - water) +
|
||||
ConfigReader.Basic.waterRight)
|
||||
.replace("{max_water}", String.valueOf(wateringCan.getMax()))
|
||||
.replace("{water}", String.valueOf(water -1));
|
||||
.replace("{water}", String.valueOf(water));
|
||||
ConfigReader.Basic.waterLore.forEach(lore -> lores.add(GsonComponentSerializer.gson().serialize(MiniMessage.miniMessage().deserialize(lore.replace("{water_info}", string)))));
|
||||
}
|
||||
itemStack.setItemMeta(nbtItem.getItem().getItemMeta());
|
||||
}
|
||||
else if (namespacedID.contains("_stage_")){
|
||||
nbtItem.setInteger("WaterAmount", water - 1);
|
||||
if (water > 0) {
|
||||
nbtItem.setInteger("WaterAmount", --water);
|
||||
AdventureManager.playerSound(player, ConfigReader.Sounds.waterPotSource, ConfigReader.Sounds.waterPotKey);
|
||||
waterPot(wateringCan.getWidth(), wateringCan.getLength(), block.getLocation().subtract(0,1,0), player.getLocation().getYaw());
|
||||
PotUtil.waterPot(wateringCan.getWidth(), wateringCan.getLength(), block.getLocation().subtract(0, 1, 0), player.getLocation().getYaw());
|
||||
}
|
||||
if (ConfigReader.Message.hasWaterInfo)
|
||||
AdventureManager.playerActionbar(player,
|
||||
(ConfigReader.Message.waterLeft +
|
||||
ConfigReader.Message.waterFull.repeat(water - 1) +
|
||||
ConfigReader.Message.waterEmpty.repeat(wateringCan.getMax() - water + 1) +
|
||||
ConfigReader.Message.waterFull.repeat(water) +
|
||||
ConfigReader.Message.waterEmpty.repeat(wateringCan.getMax() - water) +
|
||||
ConfigReader.Message.waterRight)
|
||||
.replace("{max_water}", String.valueOf(wateringCan.getMax()))
|
||||
.replace("{water}", String.valueOf(water -1)));
|
||||
.replace("{water}", String.valueOf(water)));
|
||||
if (ConfigReader.Basic.hasWaterLore){
|
||||
List<String> lores = nbtItem.getCompound("display").getStringList("Lore");
|
||||
lores.clear();
|
||||
String string =
|
||||
(ConfigReader.Basic.waterLeft +
|
||||
ConfigReader.Basic.waterFull.repeat(water - 1) +
|
||||
ConfigReader.Basic.waterEmpty.repeat(wateringCan.getMax() - water + 1) +
|
||||
ConfigReader.Basic.waterFull.repeat(water) +
|
||||
ConfigReader.Basic.waterEmpty.repeat(wateringCan.getMax() - water) +
|
||||
ConfigReader.Basic.waterRight)
|
||||
.replace("{max_water}", String.valueOf(wateringCan.getMax()))
|
||||
.replace("{water}", String.valueOf(water -1));
|
||||
.replace("{water}", String.valueOf(water));
|
||||
ConfigReader.Basic.waterLore.forEach(lore -> lores.add(GsonComponentSerializer.gson().serialize(MiniMessage.miniMessage().deserialize(lore.replace("{water_info}", string)))));
|
||||
}
|
||||
itemStack.setItemMeta(nbtItem.getItem().getItemMeta());
|
||||
@@ -246,17 +247,17 @@ public class RightClick implements Listener {
|
||||
}else {
|
||||
if (player.getGameMode() != GameMode.CREATIVE) itemStack.setAmount(itemStack.getAmount() - 1);
|
||||
AdventureManager.playerSound(player, ConfigReader.Sounds.useFertilizerSource, ConfigReader.Sounds.useFertilizerKey);
|
||||
addFertilizer(fertilizerConfig, block.getLocation());
|
||||
PotUtil.addFertilizer(fertilizerConfig, block.getLocation());
|
||||
}
|
||||
}else {
|
||||
if (player.getGameMode() != GameMode.CREATIVE) itemStack.setAmount(itemStack.getAmount() - 1);
|
||||
AdventureManager.playerSound(player, ConfigReader.Sounds.useFertilizerSource, ConfigReader.Sounds.useFertilizerKey);
|
||||
addFertilizer(fertilizerConfig, block.getLocation());
|
||||
PotUtil.addFertilizer(fertilizerConfig, block.getLocation());
|
||||
}
|
||||
}else if (namespacedID.contains("_stage_")){
|
||||
if (!fertilizerConfig.isBefore()){
|
||||
if (player.getGameMode() != GameMode.CREATIVE) itemStack.setAmount(itemStack.getAmount() - 1);
|
||||
addFertilizer(fertilizerConfig, block.getLocation().subtract(0,1,0));
|
||||
PotUtil.addFertilizer(fertilizerConfig, block.getLocation().subtract(0,1,0));
|
||||
AdventureManager.playerSound(player, ConfigReader.Sounds.useFertilizerSource, ConfigReader.Sounds.useFertilizerKey);
|
||||
}else {
|
||||
AdventureManager.playerMessage(player, ConfigReader.Message.prefix + ConfigReader.Message.beforePlant);
|
||||
@@ -270,7 +271,7 @@ public class RightClick implements Listener {
|
||||
Location location = event.getClickedBlock().getLocation();
|
||||
for (Integration integration : ConfigReader.Config.integration)
|
||||
if (!integration.canPlace(location, player)) return;
|
||||
if (IAFurnitureUtil.isSprinkler(location.clone().add(0.5, 1.5, 0.5))) return;
|
||||
if (FurnitureUtil.isSprinkler(location.clone().add(0.5, 1.5, 0.5))) return;
|
||||
if (SprinklersPerChunk.isLimited(location)){
|
||||
AdventureManager.playerMessage(player, ConfigReader.Message.prefix + ConfigReader.Message.sprinkler_limit.replace("{max}", String.valueOf(ConfigReader.Config.sprinklerLimit)));
|
||||
return;
|
||||
@@ -278,10 +279,10 @@ public class RightClick implements Listener {
|
||||
Sprinkler sprinklerData = new Sprinkler(sprinkler.getRange(), 0);
|
||||
sprinklerData.setPlayer(player.getName());
|
||||
if (player.getGameMode() != GameMode.CREATIVE) itemStack.setAmount(itemStack.getAmount() - 1);
|
||||
SimpleLocation simpleLocation = SimpleLocation.fromLocation(location.add(0,1,0));
|
||||
SimpleLocation simpleLocation = LocUtil.fromLocation(location.add(0,1,0));
|
||||
SprinklerManager.Cache.put(simpleLocation, sprinklerData);
|
||||
SprinklerManager.RemoveCache.remove(simpleLocation);
|
||||
IAFurnitureUtil.placeFurniture(sprinkler.getNamespacedID_2(),location);
|
||||
FurnitureUtil.placeFurniture(sprinkler.getNamespacedID_2(),location);
|
||||
AdventureManager.playerSound(player, ConfigReader.Sounds.placeSprinklerSource, ConfigReader.Sounds.placeSprinklerKey);
|
||||
return;
|
||||
}
|
||||
@@ -293,7 +294,7 @@ public class RightClick implements Listener {
|
||||
String namespacedID = customBlock.getNamespacedID();
|
||||
if (namespacedID.contains("_stage_")){
|
||||
Location location = block.getLocation().subtract(0,1,0);
|
||||
Fertilizer fertilizer = PotManager.Cache.get(SimpleLocation.fromLocation(location));
|
||||
Fertilizer fertilizer = PotManager.Cache.get(LocUtil.fromLocation(location));
|
||||
if (fertilizer != null){
|
||||
Fertilizer config = ConfigReader.FERTILIZERS.get(fertilizer.getKey());
|
||||
if (config == null) return;
|
||||
@@ -308,7 +309,7 @@ public class RightClick implements Listener {
|
||||
}
|
||||
}else if(namespacedID.equals(ConfigReader.Basic.pot) || namespacedID.equals(ConfigReader.Basic.watered_pot)){
|
||||
Location location = block.getLocation();
|
||||
Fertilizer fertilizer = PotManager.Cache.get(SimpleLocation.fromLocation(block.getLocation()));
|
||||
Fertilizer fertilizer = PotManager.Cache.get(LocUtil.fromLocation(block.getLocation()));
|
||||
if (fertilizer != null){
|
||||
Fertilizer config = ConfigReader.FERTILIZERS.get(fertilizer.getKey());
|
||||
String name = config.getName();
|
||||
@@ -378,13 +379,14 @@ public class RightClick implements Listener {
|
||||
int random = current.nextInt(cropInstance.getMin(), cropInstance.getMax() + 1);
|
||||
World world = location.getWorld();
|
||||
Location itemLoc = location.clone().add(0.5,0.2,0.5);
|
||||
Fertilizer fertilizer = PotManager.Cache.get(SimpleLocation.fromLocation(location.clone().subtract(0,1,0)));
|
||||
Fertilizer fertilizer = PotManager.Cache.get(LocUtil.fromLocation(location.clone().subtract(0,1,0)));
|
||||
List<String> commands = cropInstance.getCommands();
|
||||
if (commands != null)
|
||||
for (String command : commands)
|
||||
Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(), command.replace("{player}", player.getName()));
|
||||
if (ConfigReader.Config.skillXP != null && cropInstance.getSkillXP() != 0) ConfigReader.Config.skillXP.addXp(player, cropInstance.getSkillXP());
|
||||
if (cropInstance.doesDropIALoot()) customBlock.getLoot().forEach(itemStack -> location.getWorld().dropItem(location.clone().add(0.5,0.2,0.5), itemStack));
|
||||
if (cropInstance.getOtherLoots() != null) cropInstance.getOtherLoots().forEach(s -> location.getWorld().dropItem(location.clone().add(0.5,0.2,0.5), CustomStack.getInstance(s).getItemStack()));
|
||||
if (fertilizer != null){
|
||||
if (fertilizer instanceof QualityCrop qualityCrop){
|
||||
int[] weights = qualityCrop.getChance();
|
||||
@@ -396,118 +398,18 @@ public class RightClick implements Listener {
|
||||
else world.dropItem(itemLoc, CustomStack.getInstance(cropInstance.getQuality_3()).getItemStack());
|
||||
}
|
||||
}
|
||||
else BreakBlock.normalDrop(cropInstance, random, itemLoc, world);
|
||||
else DropUtil.normalDrop(cropInstance, random, itemLoc, world);
|
||||
}
|
||||
else BreakBlock.normalDrop(cropInstance, random, itemLoc, world);
|
||||
else DropUtil.normalDrop(cropInstance, random, itemLoc, world);
|
||||
}
|
||||
else customBlock.getLoot().forEach(loot-> location.getWorld().dropItem(location.clone().add(0.5,0.2,0.5), loot));
|
||||
CustomBlock.remove(location);
|
||||
AdventureManager.playerSound(player, ConfigReader.Sounds.harvestSource, ConfigReader.Sounds.harvestKey);
|
||||
if(cropInstance.getReturnStage() != null){
|
||||
CustomBlock.place(cropInstance.getReturnStage(), location);
|
||||
CropManager.Cache.put(location, player.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onQuit(PlayerQuitEvent event){
|
||||
coolDown.remove(event.getPlayer());
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加肥料
|
||||
* @param fertilizerConfig 肥料配置
|
||||
* @param location 种植盆位置
|
||||
*/
|
||||
private void addFertilizer(Fertilizer fertilizerConfig, Location location) {
|
||||
if (fertilizerConfig instanceof QualityCrop config){
|
||||
QualityCrop qualityCrop = new QualityCrop(config.getKey(), config.getTimes(), config.getChance(), config.isBefore());
|
||||
PotManager.Cache.put(SimpleLocation.fromLocation(location), qualityCrop);
|
||||
}else if (fertilizerConfig instanceof SpeedGrow config){
|
||||
SpeedGrow speedGrow = new SpeedGrow(config.getKey(), config.getTimes(),config.getChance(), config.isBefore());
|
||||
PotManager.Cache.put(SimpleLocation.fromLocation(location), speedGrow);
|
||||
}else if (fertilizerConfig instanceof RetainingSoil config){
|
||||
RetainingSoil retainingSoil = new RetainingSoil(config.getKey(), config.getTimes(),config.getChance(), config.isBefore());
|
||||
PotManager.Cache.put(SimpleLocation.fromLocation(location), retainingSoil);
|
||||
}
|
||||
if (fertilizerConfig.getParticle() != null)
|
||||
location.getWorld().spawnParticle(fertilizerConfig.getParticle(), location.add(0.5,1.3,0.5), 5,0.2,0.2,0.2);
|
||||
}
|
||||
|
||||
/**
|
||||
* 水壶浇水判定
|
||||
* @param width 宽度
|
||||
* @param length 长度
|
||||
* @param location 位置
|
||||
* @param yaw 视角
|
||||
*/
|
||||
private void waterPot(int width, int length, Location location, float yaw){
|
||||
if (ConfigReader.Config.hasParticle)
|
||||
location.getWorld().spawnParticle(Particle.WATER_SPLASH, location.clone().add(0.5,1.2,0.5),15,0.1,0.1, 0.1);
|
||||
int extend = width / 2;
|
||||
if (yaw < 45 && yaw > -135) {
|
||||
if (yaw > -45) {
|
||||
for (int i = -extend; i <= extend; i++) {
|
||||
Location tempLoc = location.clone().add(i, 0, -1);
|
||||
for (int j = 0; j < length; j++){
|
||||
tempLoc.add(0,0,1);
|
||||
CustomBlock customBlock = CustomBlock.byAlreadyPlaced(tempLoc.getBlock());
|
||||
if(customBlock != null){
|
||||
if(customBlock.getNamespacedID().equals(ConfigReader.Basic.pot)){
|
||||
CustomBlock.remove(tempLoc);
|
||||
CustomBlock.place(ConfigReader.Basic.watered_pot, tempLoc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int i = -extend; i <= extend; i++) {
|
||||
Location tempLoc = location.clone().add(-1, 0, i);
|
||||
for (int j = 0; j < length; j++){
|
||||
tempLoc.add(1,0,0);
|
||||
CustomBlock customBlock = CustomBlock.byAlreadyPlaced(tempLoc.getBlock());
|
||||
if(customBlock != null){
|
||||
if(customBlock.getNamespacedID().equals(ConfigReader.Basic.pot)){
|
||||
CustomBlock.remove(tempLoc);
|
||||
CustomBlock.place(ConfigReader.Basic.watered_pot, tempLoc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (yaw > 45 && yaw < 135) {
|
||||
for (int i = -extend; i <= extend; i++) {
|
||||
Location tempLoc = location.clone().add(1, 0, i);
|
||||
for (int j = 0; j < length; j++){
|
||||
tempLoc.subtract(1,0,0);
|
||||
CustomBlock customBlock = CustomBlock.byAlreadyPlaced(tempLoc.getBlock());
|
||||
if(customBlock != null){
|
||||
if(customBlock.getNamespacedID().equals(ConfigReader.Basic.pot)){
|
||||
CustomBlock.remove(tempLoc);
|
||||
CustomBlock.place(ConfigReader.Basic.watered_pot, tempLoc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int i = -extend; i <= extend; i++) {
|
||||
Location tempLoc = location.clone().add(i, 0, 1);
|
||||
for (int j = 0; j < length; j++){
|
||||
tempLoc.subtract(0,0,1);
|
||||
CustomBlock customBlock = CustomBlock.byAlreadyPlaced(tempLoc.getBlock());
|
||||
if(customBlock != null){
|
||||
if(customBlock.getNamespacedID().equals(ConfigReader.Basic.pot)){
|
||||
CustomBlock.remove(tempLoc);
|
||||
CustomBlock.place(ConfigReader.Basic.watered_pot, tempLoc);
|
||||
}
|
||||
}
|
||||
}
|
||||
SimpleLocation simpleLocation = LocUtil.fromLocation(location);
|
||||
CropManager.RemoveCache.remove(simpleLocation);
|
||||
CropManager.Cache.put(simpleLocation, player.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,7 @@ public class Crop {
|
||||
private String giant;
|
||||
private List<Requirement> requirements;
|
||||
private List<String> seasons;
|
||||
private List<String> otherLoots;
|
||||
private String returnStage;
|
||||
private final int min;
|
||||
private final int max;
|
||||
@@ -37,6 +38,7 @@ public class Crop {
|
||||
private boolean dropIALoot;
|
||||
private List<String> commands;
|
||||
private double growChance;
|
||||
private boolean isBlock;
|
||||
|
||||
public Crop(int min, int max){
|
||||
this.min = min;
|
||||
@@ -61,6 +63,8 @@ public class Crop {
|
||||
public double getSkillXP() {return skillXP;}
|
||||
public boolean doesDropIALoot() {return dropIALoot;}
|
||||
public double getGrowChance() {return growChance;}
|
||||
public boolean isBlock() {return isBlock;}
|
||||
public List<String> getOtherLoots() {return otherLoots;}
|
||||
|
||||
public void setReturnStage(String stage){ this.returnStage = stage; }
|
||||
public void setGiant(String giant) { this.giant = giant; }
|
||||
@@ -74,4 +78,6 @@ public class Crop {
|
||||
public void setSkillXP(double skillXP) {this.skillXP = skillXP;}
|
||||
public void setDropIALoot(boolean dropIALoot) {this.dropIALoot = dropIALoot;}
|
||||
public void setGrowChance(double growChance) {this.growChance = growChance;}
|
||||
public void setIsBlock(boolean isBlock) {this.isBlock = isBlock;}
|
||||
public void setOtherLoots(List<String> otherLoots) {this.otherLoots = otherLoots;}
|
||||
}
|
||||
|
||||
@@ -17,8 +17,6 @@
|
||||
|
||||
package net.momirealms.customcrops.objects;
|
||||
|
||||
import org.bukkit.Location;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class SimpleLocation {
|
||||
@@ -35,15 +33,6 @@ public class SimpleLocation {
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将Location转换为SimpleLocation
|
||||
* @param location Location
|
||||
* @return SimpleLocation
|
||||
*/
|
||||
public static SimpleLocation fromLocation(Location location){
|
||||
return new SimpleLocation(location.getWorld().getName(), location.getBlockX(), location.getBlockY(), location.getBlockZ());
|
||||
}
|
||||
|
||||
public int getX() {return x;}
|
||||
public int getZ() {return z;}
|
||||
public int getY() {return y;}
|
||||
|
||||
31
src/main/java/net/momirealms/customcrops/utils/DropUtil.java
Normal file
31
src/main/java/net/momirealms/customcrops/utils/DropUtil.java
Normal file
@@ -0,0 +1,31 @@
|
||||
package net.momirealms.customcrops.utils;
|
||||
|
||||
import dev.lone.itemsadder.api.CustomStack;
|
||||
import net.momirealms.customcrops.ConfigReader;
|
||||
import net.momirealms.customcrops.objects.Crop;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
|
||||
public class DropUtil {
|
||||
|
||||
/**
|
||||
* 没有品质肥料下的普通掉落
|
||||
* @param cropInstance 农作物
|
||||
* @param random 随机农作物数量
|
||||
* @param itemLoc 掉落物位置
|
||||
* @param world 世界
|
||||
*/
|
||||
public static void normalDrop(Crop cropInstance, int random, Location itemLoc, World world) {
|
||||
for (int i = 0; i < random; i++){
|
||||
double ran = Math.random();
|
||||
if (ran < ConfigReader.Config.quality_1){
|
||||
world.dropItem(itemLoc, CustomStack.getInstance(cropInstance.getQuality_1()).getItemStack());
|
||||
}else if(ran > ConfigReader.Config.quality_2){
|
||||
world.dropItem(itemLoc, CustomStack.getInstance(cropInstance.getQuality_2()).getItemStack());
|
||||
}else {
|
||||
world.dropItem(itemLoc, CustomStack.getInstance(cropInstance.getQuality_3()).getItemStack());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright (C) <2022> <XiaoMoMi>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.momirealms.customcrops.utils;
|
||||
|
||||
import dev.lone.itemsadder.api.CustomFurniture;
|
||||
import net.momirealms.customcrops.ConfigReader;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Rotation;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.ItemFrame;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class FurnitureUtil {
|
||||
|
||||
static Rotation[] rotations4 = {Rotation.NONE, Rotation.FLIPPED, Rotation.CLOCKWISE, Rotation.COUNTER_CLOCKWISE};
|
||||
static Rotation[] rotations8 = {Rotation.NONE, Rotation.FLIPPED, Rotation.CLOCKWISE, Rotation.COUNTER_CLOCKWISE,
|
||||
Rotation.CLOCKWISE_45, Rotation.CLOCKWISE_135, Rotation.FLIPPED_45, Rotation.COUNTER_CLOCKWISE_45};
|
||||
|
||||
/**
|
||||
* 在指定位置放置家具
|
||||
* @param name 物品名
|
||||
* @param location 位置
|
||||
*/
|
||||
public static void placeFurniture(String name, Location location){
|
||||
CustomFurniture.spawn(name, location.getBlock());
|
||||
}
|
||||
|
||||
/**
|
||||
* 在指定位置放置农作物
|
||||
* @param name 农作物命名空间id
|
||||
* @param location 位置
|
||||
*/
|
||||
public static void placeCrop(String name, Location location){
|
||||
CustomFurniture customFurniture = CustomFurniture.spawn(name, location.getBlock());
|
||||
Entity entity = customFurniture.getArmorstand();
|
||||
if (ConfigReader.Config.rotation && entity instanceof ItemFrame itemFrame){
|
||||
if (ConfigReader.Config.variant4) itemFrame.setRotation(rotations4[new Random().nextInt(rotations4.length-1)]);
|
||||
else itemFrame.setRotation(rotations8[new Random().nextInt(rotations8.length-1)]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定位置的家具名
|
||||
* 仅限加载中的区块
|
||||
* @param location 位置
|
||||
* @return 是/否
|
||||
*/
|
||||
public static String getNamespacedID(Location location){
|
||||
CustomFurniture furniture = getFurniture(location);
|
||||
if (furniture != null){
|
||||
return furniture.getNamespacedID();
|
||||
}else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定位置的家具名
|
||||
* 仅限加载中的区块
|
||||
* @param location 位置
|
||||
* @return 是/否
|
||||
*/
|
||||
public static CustomFurniture getFurniture(Location location){
|
||||
for(Entity entity : location.getWorld().getNearbyEntities(location,0,0,0)){
|
||||
CustomFurniture furniture = CustomFurniture.byAlreadySpawned(entity);
|
||||
if(furniture != null) return furniture;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断指定位置的家具是不是洒水器
|
||||
* @param location 位置
|
||||
* @return 是/否
|
||||
*/
|
||||
public static boolean isSprinkler(Location location){
|
||||
String furniture = getNamespacedID(location);
|
||||
if (furniture != null) return ConfigReader.SPRINKLERS.get(furniture) != null;
|
||||
else return false;
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) <2022> <XiaoMoMi>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.momirealms.customcrops.utils;
|
||||
|
||||
import dev.lone.itemsadder.api.CustomFurniture;
|
||||
import net.momirealms.customcrops.ConfigReader;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Entity;
|
||||
|
||||
public class IAFurnitureUtil {
|
||||
|
||||
/**
|
||||
* 在指定位置放置家具
|
||||
* @param name 物品名
|
||||
* @param location 位置
|
||||
*/
|
||||
public static void placeFurniture(String name, Location location){
|
||||
CustomFurniture.spawn(name, location.getBlock());
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断指定位置的盔甲架是不是洒水器
|
||||
* 仅限加载中的区块
|
||||
* @param location 位置
|
||||
* @return 是/否
|
||||
*/
|
||||
public static String getFromLocation(Location location){
|
||||
for(Entity entity : location.getWorld().getNearbyEntities(location,0,0,0)){
|
||||
CustomFurniture furniture = CustomFurniture.byAlreadySpawned(entity);
|
||||
if(furniture != null) return furniture.getNamespacedID();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static boolean isSprinkler(Location location){
|
||||
String furniture = getFromLocation(location);
|
||||
if (furniture != null) return ConfigReader.SPRINKLERS.get(furniture) != null;
|
||||
else return false;
|
||||
}
|
||||
}
|
||||
15
src/main/java/net/momirealms/customcrops/utils/LocUtil.java
Normal file
15
src/main/java/net/momirealms/customcrops/utils/LocUtil.java
Normal file
@@ -0,0 +1,15 @@
|
||||
package net.momirealms.customcrops.utils;
|
||||
|
||||
import net.momirealms.customcrops.objects.SimpleLocation;
|
||||
import org.bukkit.Location;
|
||||
|
||||
public class LocUtil {
|
||||
/**
|
||||
* 将Location转换为SimpleLocation
|
||||
* @param location Location
|
||||
* @return SimpleLocation
|
||||
*/
|
||||
public static SimpleLocation fromLocation(Location location){
|
||||
return new SimpleLocation(location.getWorld().getName(), location.getBlockX(), location.getBlockY(), location.getBlockZ());
|
||||
}
|
||||
}
|
||||
111
src/main/java/net/momirealms/customcrops/utils/PotUtil.java
Normal file
111
src/main/java/net/momirealms/customcrops/utils/PotUtil.java
Normal file
@@ -0,0 +1,111 @@
|
||||
package net.momirealms.customcrops.utils;
|
||||
|
||||
import dev.lone.itemsadder.api.CustomBlock;
|
||||
import net.momirealms.customcrops.ConfigReader;
|
||||
import net.momirealms.customcrops.datamanager.PotManager;
|
||||
import net.momirealms.customcrops.fertilizer.Fertilizer;
|
||||
import net.momirealms.customcrops.fertilizer.QualityCrop;
|
||||
import net.momirealms.customcrops.fertilizer.RetainingSoil;
|
||||
import net.momirealms.customcrops.fertilizer.SpeedGrow;
|
||||
import net.momirealms.customcrops.objects.SimpleLocation;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Particle;
|
||||
|
||||
public class PotUtil {
|
||||
|
||||
/**
|
||||
* 水壶浇水判定
|
||||
* @param width 宽度
|
||||
* @param length 长度
|
||||
* @param location 位置
|
||||
* @param yaw 视角
|
||||
*/
|
||||
public static void waterPot(int width, int length, Location location, float yaw){
|
||||
if (ConfigReader.Config.hasParticle)
|
||||
location.getWorld().spawnParticle(Particle.WATER_SPLASH, location.clone().add(0.5,1.2,0.5),15,0.1,0.1, 0.1);
|
||||
int extend = width / 2;
|
||||
if (yaw < 45 && yaw > -135) {
|
||||
if (yaw > -45) {
|
||||
for (int i = -extend; i <= extend; i++) {
|
||||
Location tempLoc = location.clone().add(i, 0, -1);
|
||||
for (int j = 0; j < length; j++){
|
||||
tempLoc.add(0,0,1);
|
||||
CustomBlock customBlock = CustomBlock.byAlreadyPlaced(tempLoc.getBlock());
|
||||
if(customBlock != null){
|
||||
if(customBlock.getNamespacedID().equals(ConfigReader.Basic.pot)){
|
||||
CustomBlock.remove(tempLoc);
|
||||
CustomBlock.place(ConfigReader.Basic.watered_pot, tempLoc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int i = -extend; i <= extend; i++) {
|
||||
Location tempLoc = location.clone().add(-1, 0, i);
|
||||
for (int j = 0; j < length; j++){
|
||||
tempLoc.add(1,0,0);
|
||||
CustomBlock customBlock = CustomBlock.byAlreadyPlaced(tempLoc.getBlock());
|
||||
if(customBlock != null){
|
||||
if(customBlock.getNamespacedID().equals(ConfigReader.Basic.pot)){
|
||||
CustomBlock.remove(tempLoc);
|
||||
CustomBlock.place(ConfigReader.Basic.watered_pot, tempLoc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (yaw > 45 && yaw < 135) {
|
||||
for (int i = -extend; i <= extend; i++) {
|
||||
Location tempLoc = location.clone().add(1, 0, i);
|
||||
for (int j = 0; j < length; j++){
|
||||
tempLoc.subtract(1,0,0);
|
||||
CustomBlock customBlock = CustomBlock.byAlreadyPlaced(tempLoc.getBlock());
|
||||
if(customBlock != null){
|
||||
if(customBlock.getNamespacedID().equals(ConfigReader.Basic.pot)){
|
||||
CustomBlock.remove(tempLoc);
|
||||
CustomBlock.place(ConfigReader.Basic.watered_pot, tempLoc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int i = -extend; i <= extend; i++) {
|
||||
Location tempLoc = location.clone().add(i, 0, 1);
|
||||
for (int j = 0; j < length; j++){
|
||||
tempLoc.subtract(0,0,1);
|
||||
CustomBlock customBlock = CustomBlock.byAlreadyPlaced(tempLoc.getBlock());
|
||||
if(customBlock != null){
|
||||
if(customBlock.getNamespacedID().equals(ConfigReader.Basic.pot)){
|
||||
CustomBlock.remove(tempLoc);
|
||||
CustomBlock.place(ConfigReader.Basic.watered_pot, tempLoc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加肥料
|
||||
* @param fertilizerConfig 肥料配置
|
||||
* @param location 种植盆位置
|
||||
*/
|
||||
public static void addFertilizer(Fertilizer fertilizerConfig, Location location) {
|
||||
if (fertilizerConfig instanceof QualityCrop config){
|
||||
QualityCrop qualityCrop = new QualityCrop(config.getKey(), config.getTimes(), config.getChance(), config.isBefore());
|
||||
PotManager.Cache.put(LocUtil.fromLocation(location), qualityCrop);
|
||||
}else if (fertilizerConfig instanceof SpeedGrow config){
|
||||
SpeedGrow speedGrow = new SpeedGrow(config.getKey(), config.getTimes(),config.getChance(), config.isBefore());
|
||||
PotManager.Cache.put(LocUtil.fromLocation(location), speedGrow);
|
||||
}else if (fertilizerConfig instanceof RetainingSoil config){
|
||||
RetainingSoil retainingSoil = new RetainingSoil(config.getKey(), config.getTimes(),config.getChance(), config.isBefore());
|
||||
PotManager.Cache.put(LocUtil.fromLocation(location), retainingSoil);
|
||||
}
|
||||
if (fertilizerConfig.getParticle() != null) location.getWorld().spawnParticle(fertilizerConfig.getParticle(), location.add(0.5,1.3,0.5), 5,0.2,0.2,0.2);
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,54 @@
|
||||
#Don't change
|
||||
config-version: 3
|
||||
config-version: '4'
|
||||
|
||||
#Want to sell the crops?
|
||||
#Try this plugin: https://www.spigotmc.org/resources/shipping-bin.104591/
|
||||
#You can use it with a command binding to an ItemsAdder furniture
|
||||
#Shipping Bin is similar to the way how players sell items in Stardrew Valley
|
||||
|
||||
config:
|
||||
#english spanish chinese
|
||||
# lang: english / spanish / chinese
|
||||
lang: english
|
||||
|
||||
|
||||
# mode: tripwire / item_frame
|
||||
# This option requires a server restart
|
||||
# ------------ tripwire ------------
|
||||
# Advantage:
|
||||
# ● async check, less lag
|
||||
# ● Real block hitbox like vanilla
|
||||
#
|
||||
# Disadvantage:
|
||||
# ● limited amount
|
||||
# ● visual problem when breaking crops
|
||||
# ● Can't remove tripwire break sound
|
||||
#
|
||||
# ------------ item_frame ------------
|
||||
# Advantage:
|
||||
# ● unlimited amount
|
||||
# ● No tripwire break sound
|
||||
# ● Rotation
|
||||
#
|
||||
# Disadvantage:
|
||||
# ● entities are very laggy(loading every 5 item frames need 0.01 mspt)
|
||||
# ● spigot optimized the view distance of entities
|
||||
# ● crops would go missing if server is lagging
|
||||
# ● No real block hitbox
|
||||
# ● itemsAdder loot system doesn't apply to furnitures.
|
||||
#
|
||||
crop-mode: tripwire
|
||||
|
||||
|
||||
|
||||
# Should crops be planted in random rotation?
|
||||
# only works in item_frame mode
|
||||
rotation:
|
||||
enable: false
|
||||
# 4 / 8
|
||||
variant: 4
|
||||
|
||||
|
||||
|
||||
integration:
|
||||
#integration to prevent other players' grief
|
||||
Residence: false
|
||||
@@ -28,62 +70,64 @@ config:
|
||||
|
||||
|
||||
|
||||
#Mode 1:
|
||||
# Crops in loaded chunks will grow
|
||||
#Mode 2:
|
||||
# Online players' crops will grow
|
||||
#Mode 3:
|
||||
# Recommended
|
||||
# Mode 1 + Mode 2
|
||||
#Mode 4:
|
||||
# Please disable season in this mode!
|
||||
# All the crops will grow
|
||||
# Mode 1:
|
||||
# ● Crops in loaded chunks will grow
|
||||
# Mode 2:
|
||||
# ● Online players' crops will grow
|
||||
# Mode 3:
|
||||
# ● Recommended Mode 1 + Mode 2
|
||||
# Mode 4:
|
||||
# ● Please disable season in this mode!
|
||||
# ● All the crops will grow
|
||||
grow-mode: 3
|
||||
#The time to start growing(ticks)
|
||||
#1000ticks is 7am in game. (0-23999)
|
||||
#Sprinklers will work after all crops finish growing
|
||||
# The time to start growing(ticks)
|
||||
# 1000ticks is 7am in game. (0-23999)
|
||||
# Sprinklers will work after all crops finish growing
|
||||
grow-time:
|
||||
- 1000
|
||||
#Time in random a single crop need to grow(seconds)
|
||||
#This prevents a large amount of crops grow at the same time
|
||||
#Large amount of block replacement would cause lag.
|
||||
# Time in random a single crop need to grow(seconds)
|
||||
# This prevents a large amount of crops grow at the same time
|
||||
# Large amount of block replacement would cause lag.
|
||||
time-to-grow: 60
|
||||
#Similar to "time-to-grow", this prevent all sprinklers work at the same time
|
||||
# Similar to "time-to-grow", this prevent all sprinklers work at the same time
|
||||
time-to-work: 30
|
||||
#Async Time Check (requires restart)
|
||||
#Crops might not grow when using async.
|
||||
#It is not really necessary to be Async
|
||||
# Async Time Check (requires restart)
|
||||
# Crops might not grow when using async.
|
||||
# It is not really necessary to be Async
|
||||
async-time-check: false
|
||||
#Worlds where crops would grow
|
||||
# Worlds where crops would grow
|
||||
whitelist-worlds:
|
||||
- world
|
||||
#Should all the worlds' crops grow?
|
||||
#This is useful for per player per world server.
|
||||
#In this mode, whitelist world can only have one as the standard of time & season judgment.
|
||||
# Should all the worlds' crops grow?
|
||||
# This is useful for per player per world server.
|
||||
# In this mode, whitelist world can only have one for time & season judgment.
|
||||
all-world-grow: false
|
||||
|
||||
# How does gigantic work?
|
||||
# In stardrew valley, crops will still absorb water every day after it is ripe to be gigantic
|
||||
# But you can give it only one chance to be gigantic(This is also good for performance)
|
||||
gigantic-only-one-try: false
|
||||
|
||||
|
||||
quality:
|
||||
#If disabled, you need to configurate the loot in ItemsAdder config
|
||||
# If disabled, you need to configurate the loots in ItemsAdder config
|
||||
enable: true
|
||||
#Default ratio
|
||||
# Default ratio
|
||||
default-ratio: 17/2/1
|
||||
|
||||
|
||||
|
||||
#Water Amount to refill when using water bucket
|
||||
# Water Amount to refill when using water bucket
|
||||
sprinkler-refill: 2
|
||||
#Water Amount to refill with a sigle click to water block
|
||||
# Water Amount to refill with a single click to water block
|
||||
water-can-refill: 1
|
||||
#Can watering-can add water to sprinklers?
|
||||
# Can watering-can add water to sprinklers?
|
||||
water-can-add-water-to-sprinkler: true
|
||||
#Should particles be displayed when using watering can?
|
||||
# Should particles be displayed when using watering can?
|
||||
water-particles: true
|
||||
|
||||
|
||||
|
||||
#Will bone meal accelerate the growth of crop
|
||||
# Will bone meal accelerate the growth of crop
|
||||
bone-meal:
|
||||
enable: true
|
||||
chance: 0.5
|
||||
@@ -91,9 +135,9 @@ config:
|
||||
|
||||
|
||||
|
||||
#Should we limit the max amount of crops and sprinkler in one chunk
|
||||
#Recommended to enable because ItemsAdder might throw StackOverFlow
|
||||
#when there are too many custom blocks in one chunk
|
||||
# Should we limit the max amount of crops and sprinkler in one chunk
|
||||
# Recommended to enable because ItemsAdder might throw StackOverFlow
|
||||
# when there are too many custom blocks in one chunk
|
||||
limit:
|
||||
enable: true
|
||||
crop: 64
|
||||
@@ -101,13 +145,13 @@ config:
|
||||
|
||||
|
||||
|
||||
#can player harvest crops with right click?
|
||||
#if set "false" crops can't be harvested repeatedly
|
||||
# can player harvest crops with right click?
|
||||
# if set "false" crops can't be harvested repeatedly
|
||||
right-click-harvest: true
|
||||
#If "right-click-harvest" is true
|
||||
#Should player be allowed to harvest with items in hand
|
||||
# If "right-click-harvest" is true
|
||||
# Should player must harvest with empty hands?
|
||||
harvest-with-empty-hand: true
|
||||
#Should player be prevented from planting if wrong season
|
||||
# Should player be prevented from planting if wrong season
|
||||
prevent-plant-if-wrong-season: true
|
||||
#Should notify player of the wrong season?
|
||||
# Should player be notified of the wrong season?
|
||||
should-notify-if-wrong-season: true
|
||||
@@ -13,10 +13,18 @@ crops:
|
||||
2: customcrops:tomato_silver_star
|
||||
3: customcrops:tomato_golden_star
|
||||
|
||||
#When harvesting, should the crop drop the loots from ItemsAdder too
|
||||
#This is useful for dropping seeds and other items
|
||||
#When you break the crop, the event will be handled by ItemsAdder & Customcrops so IA loots would be certainly dropped
|
||||
#When you right click the crop, the event will only be handled by Customcrops so IA loots would be optional
|
||||
|
||||
#**right click** harvest, should the crop drop the loots from ItemsAdder too
|
||||
#This is useful for dropping seeds and other items(only works in tripwire mode, furnitures don't support loot at the moment)
|
||||
drop-ia-loots: false
|
||||
|
||||
#**right click** harvest, should the crop drop other loots
|
||||
#This is useful for dropping seeds and other items(Works in both tripwire/item_frame mode)
|
||||
drop-other-loots:
|
||||
- customcrops:tomato_seeds
|
||||
|
||||
#optional
|
||||
#The chance that a crop grow a stage at grow time
|
||||
grow-chance: 0.9
|
||||
@@ -27,6 +35,12 @@ crops:
|
||||
block: customcrops:gigantic_tomato
|
||||
chance: 0.01
|
||||
|
||||
#If you want to use item_frame/armor_stand for gigantic crops
|
||||
#You should config like this
|
||||
#gigantic:
|
||||
# furniture: customcrops:gigantic_tomato
|
||||
# chance: 0.01
|
||||
|
||||
#optional
|
||||
commands:
|
||||
- 'say {player} harvested a tomato! lol'
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
name: CustomCrops
|
||||
version: '${version}'
|
||||
main: net.momirealms.customcrops.CustomCrops
|
||||
api-version: 1.16
|
||||
api-version: 1.17
|
||||
authors: [ XiaoMoMi ]
|
||||
depend:
|
||||
- ItemsAdder
|
||||
|
||||
@@ -1,9 +1,50 @@
|
||||
#Don't change
|
||||
config-version: 1
|
||||
#请不要修改此值
|
||||
config-version: '4'
|
||||
|
||||
|
||||
config:
|
||||
#插件兼容
|
||||
# 语言: english / spanish / chinese
|
||||
lang: chinese
|
||||
|
||||
|
||||
# 模式: tripwire / item_frame
|
||||
# 此设置需要重启服务器
|
||||
# ------------ tripwire ------------
|
||||
# 优势:
|
||||
# ● 几乎完全异步
|
||||
# ● 有原版一样的真实碰撞体积
|
||||
#
|
||||
# 劣势:
|
||||
# ● 拌线数量限制(127)
|
||||
# ● 破坏拌线产生的视觉问题
|
||||
# ● 无法移除破坏拌线的音效
|
||||
#
|
||||
# ------------ item_frame ------------
|
||||
# 优势:
|
||||
# ● 无限制农作物数量
|
||||
# ● 支持旋转
|
||||
#
|
||||
# 劣势:
|
||||
# ● 展示框是实体,相对较卡
|
||||
# ● Spigot优化了实体可见距离
|
||||
# ● 没有真实的碰撞体积
|
||||
# ● ItemsAdder的战利品系统无法应用于家具
|
||||
#
|
||||
crop-mode: tripwire
|
||||
|
||||
|
||||
|
||||
# 农作物会有随机的朝向吗?
|
||||
# 这只在展示框模式中生效
|
||||
rotation:
|
||||
enable: false
|
||||
# 4 / 8
|
||||
variant: 4
|
||||
|
||||
|
||||
|
||||
integration:
|
||||
#领地保护
|
||||
Residence: false
|
||||
WorldGuard: false
|
||||
Kingdoms: false
|
||||
@@ -11,91 +52,99 @@ config:
|
||||
PlotSquared: false
|
||||
Towny: false
|
||||
Lands: false
|
||||
GriefPrevention: false
|
||||
CrashClaim: false
|
||||
#增加技能经验
|
||||
AureliumSkills: false
|
||||
mcMMO: false
|
||||
MMOCore: false
|
||||
EcoSkills: false
|
||||
#季节同步
|
||||
RealisticSeasons: false
|
||||
|
||||
#生长时间点(tick)
|
||||
#1000代表上午7点,农作物陆续开始生长
|
||||
#洒水器将会在农作物全部完成生长后开始工作
|
||||
|
||||
|
||||
# Mode 1:
|
||||
# ● 农作物仅在加载中的区块生长
|
||||
# Mode 2:
|
||||
# ● 在线玩家种植的农作物会生长
|
||||
# Mode 3:
|
||||
# ● (推荐) Mode 1 + Mode 2
|
||||
# Mode 4:
|
||||
# ● 在这个模式下请关闭季节
|
||||
# ● 所有数据内的农作物都会生长
|
||||
grow-mode: 3
|
||||
# 开始生长的时间(ticks)
|
||||
# 1000ticks 代表游戏时间 7点 (0-23999)
|
||||
# 洒水器将在所有农作物完成生长后开始工作
|
||||
grow-time:
|
||||
- 1000
|
||||
|
||||
#生长点后农作物成长所需的时间(秒)
|
||||
#农作物将在60秒内随机完成生长以避免在短时间内大量方块替换造成卡顿
|
||||
#但也不建议设置过长时间,否则内存无法及时释放,区块会被持续加载
|
||||
#配合上方的默认时间点,意思为每天上午7点后,农作物将在60秒内完成生长过程
|
||||
# 农作物将在开始生长的时间点后多少秒内完成生长(seconds)
|
||||
# 这是为了避免大量农作物在同一时间点进行判断和方块替换,否则会造成卡顿
|
||||
# 假如你有100个农作物,默认配置代表在游戏时间7点后的现实时间60秒内,100个农作物会在这60秒内随机时间点完成生长
|
||||
time-to-grow: 60
|
||||
#农作物全部完成生长后洒水器工作所需的时间
|
||||
# 和上面的配置类似,只不过这一次是洒水器工作的时间
|
||||
time-to-work: 30
|
||||
|
||||
#产物品质
|
||||
quality:
|
||||
#若不启用则植物成熟阶段会掉落IA配置里的loot
|
||||
#如果关闭产物品质需要在IA物品配置内自行添加最后一阶段掉落物
|
||||
enable: true
|
||||
#默认品质权重比
|
||||
default-ratio: 17/2/1
|
||||
|
||||
#异步时间检测,此设置需要重启生效
|
||||
#启用异步时间检测会带来更好的性能但是可能会因为服务器的跳tick原因错过一些生长时间点
|
||||
# 异步时间检测 (需要重启)
|
||||
# 服务端可能因为某些原因跳tick,所以异步模式下可能会错过生长判断
|
||||
# 异步检测不是很有必要,同步的检测也不会造成性能问题,除非你设置了几百个白名单世界
|
||||
async-time-check: false
|
||||
|
||||
#使用一次水桶可以补充几个洒水器水槽
|
||||
sprinkler-refill: 2
|
||||
#水壶右键一次水方块能补充多少水量
|
||||
water-can-refill: 1
|
||||
#是否可以用水壶为洒水器加水
|
||||
water-can-add-water-to-sprinkler: true
|
||||
#使用水的时候是否产生粒子效果
|
||||
water-particles: true
|
||||
|
||||
#生长生效的世界
|
||||
# 哪些世界的农作物能够生长(即白名单世界)
|
||||
whitelist-worlds:
|
||||
- world
|
||||
# 所有世界的农作物都生长吗?
|
||||
# 此选项适用于单玩家单世界服务器.
|
||||
# 这种模式下你只能填写一个白名单世界作为时间,季节的判断依据.
|
||||
all-world-grow: false
|
||||
# 农作物巨大化是否仅进行一次尝试
|
||||
# 如果你喜欢星露谷模式,农作物将在成熟后继续吸收水分,每天都有概率巨大化
|
||||
# 如果你喜欢起源模式,你可以设置巨大化农作物为金农作物,并且仅有一次成为金农作物的机会
|
||||
gigantic-only-one-try: false
|
||||
|
||||
#每个区块最大农作物数量和洒水器数量
|
||||
#是否启用限制
|
||||
|
||||
|
||||
quality:
|
||||
# 如果禁用品质系统,你需要在ItemsAdder的配置文件中单独设置每个农作物的掉落物
|
||||
enable: true
|
||||
# 默认品质比例
|
||||
default-ratio: 17/2/1
|
||||
|
||||
|
||||
|
||||
# 使用水桶右键洒水器能够补充几格水量
|
||||
sprinkler-refill: 2
|
||||
# 使用水壶右键水方块的时候能够为水壶补充多少水量
|
||||
water-can-refill: 1
|
||||
# 能否使用水壶为洒水器加水
|
||||
water-can-add-water-to-sprinkler: true
|
||||
# 使用水壶的时候发送水花粒子效果吗
|
||||
water-particles: true
|
||||
|
||||
|
||||
|
||||
# 是否启用骨粉特性
|
||||
bone-meal:
|
||||
enable: true
|
||||
chance: 0.5
|
||||
success-particle: VILLAGER_HAPPY
|
||||
|
||||
|
||||
|
||||
# 区块限制最大农作物和洒水器数量
|
||||
# 建议开启限制,因为一个区块内过多的农作物方块会导致IA插件报错Stack Overflow
|
||||
limit:
|
||||
enable: true
|
||||
crop: 64
|
||||
sprinkler: 8
|
||||
|
||||
#记录生长判断和洒水所需的时间(测试性能用)
|
||||
log-time-consume: false
|
||||
|
||||
#Mode 1:
|
||||
# 加载中区块的农作物生长
|
||||
#Mode 2:
|
||||
# 在线玩家的农作物生长
|
||||
#Mode 3:
|
||||
# Mode 1 + Mode 2
|
||||
#Mode 4:
|
||||
# 所有农作物生长
|
||||
# 可能会造成卡顿!不建议使用此模式
|
||||
grow-mode: 3
|
||||
|
||||
#是否所有加载中的世界都要进行生长判断
|
||||
#本选项适用于使用玩家独立世界的服务器
|
||||
#因为有大量世界所以无法通过添加白名单世界的方式生长
|
||||
#在此选项开启的状态下,白名单世界只能填写一个
|
||||
#作为所有世界农作物生长的时间、季节判断依据
|
||||
all-world-grow: false
|
||||
|
||||
#玩家是否能右键收获
|
||||
# 玩家是否可以使用右键收获农作物
|
||||
# 如果禁用右键收获,那么重复收获的特性也会被关闭
|
||||
right-click-harvest: true
|
||||
|
||||
#玩家是否需要空手右键收获
|
||||
# 玩家是否必须要空手才能右键收获
|
||||
harvest-with-empty-hand: true
|
||||
|
||||
#是否阻止玩家在错误的季节种植
|
||||
# 是否阻止玩家在错误季节的种植
|
||||
prevent-plant-if-wrong-season: true
|
||||
#是否告知玩家这是错误的季节
|
||||
# 是否告知玩家这是错误的季节
|
||||
should-notify-if-wrong-season: true
|
||||
|
||||
#骨粉设置
|
||||
bone-meal:
|
||||
enable: true
|
||||
chance: 0.5
|
||||
success-particle: VILLAGER_HAPPY
|
||||
@@ -3,45 +3,73 @@
|
||||
#农作物生长阶段请以 _stage_X 结尾
|
||||
#生长阶段从1开始依次累加
|
||||
#若无法理解可以参考范例配置文件
|
||||
|
||||
crops:
|
||||
tomato:
|
||||
#收获时获取的基础数量
|
||||
#收获时候掉落多少个农产品
|
||||
amount: 1~4
|
||||
#农作物收获得到的三种品质
|
||||
|
||||
#品质农作物掉落
|
||||
quality:
|
||||
1: customcrops:tomato
|
||||
2: customcrops:tomato_silver_star
|
||||
3: customcrops:tomato_golden_star
|
||||
#农作物每个时间点生长一个阶段的概率
|
||||
#不设置默认为1
|
||||
grow-chance: 0.9
|
||||
#收获的时候是否额外掉落IA配置里的战利品
|
||||
#可用于最后一阶段掉落种子等操作
|
||||
|
||||
#当你破坏农作物的时候,这个事件会同时被ItemsAdder和CustomCrops处理,所以IA配置内的掉落物会被必定掉落
|
||||
#当你右键收获农作物的时候,这个事件仅被CustomCrops处理,因此是否掉落IA配置内的掉落物为可选项目
|
||||
|
||||
#右键收获的时候,是否掉落IA配置内的掉落物
|
||||
#这对于那些需要农作物掉落额外物品的用户帮助很大,比如掉落种子(但是此设置仅适用于拌线模式,因为IA的家具没有掉落物系统)
|
||||
drop-ia-loots: false
|
||||
#巨大化植物,以极低的概率生长为另一种形态
|
||||
|
||||
#右键收获的时候,是否额外掉落IA物品
|
||||
#这对于那些需要农作物掉落额外物品的用户帮助很大,比如掉落种子(这是本插件提供的额外掉落物系统,独立于IA存在,所以拌线和展示框模式都适用)
|
||||
drop-other-loots:
|
||||
- customcrops:tomato_seeds
|
||||
|
||||
#可选
|
||||
#农作物在某个生长点的生长概率
|
||||
#比如你可以设置一天在0点,6点,12点,18点进行生长判断(不建议设置太多),每次生长概率为0.25,这样即可增大玩家加载到农作物区块的概率
|
||||
#但是同一时间点种植的农作物,可能会出现一个已经成熟,而另一个还在第一阶段(如果你喜欢这种模式,可以这样设置)
|
||||
grow-chance: 0.9
|
||||
|
||||
#可选
|
||||
#巨大化农作物
|
||||
gigantic:
|
||||
block: customcrops:gigantic_tomato
|
||||
chance: 0.01
|
||||
#收获时候执行指令
|
||||
|
||||
#如果你想要使用展示框/盔甲架作为巨大化农作物的载体
|
||||
#你需要像这样填写,注意!IA的API不提供solid(屏障)方块的放置
|
||||
#所以家具模式下的巨大化作物无法被屏障包裹
|
||||
#gigantic:
|
||||
# furniture: customcrops:gigantic_tomato
|
||||
# chance: 0.01
|
||||
|
||||
#可选
|
||||
commands:
|
||||
- 'say {player} harvested a tomato! lol'
|
||||
#生长季节
|
||||
|
||||
#可选
|
||||
#如果你启用了技能插件的兼容,那么可以设置收获该农作物的经验值
|
||||
#skill-xp: 100
|
||||
|
||||
#可选
|
||||
#若不填写则农作物四季生长
|
||||
season:
|
||||
- summer
|
||||
- autumn
|
||||
#种植所需的条件
|
||||
|
||||
#可选
|
||||
#一些农作物种植的其他条件
|
||||
requirements:
|
||||
#适宜的生长高度
|
||||
yPos:
|
||||
- 50~100
|
||||
- 150~200
|
||||
#适宜的生长群系
|
||||
biome:
|
||||
- minecraft:plains
|
||||
#适宜的世界
|
||||
world:
|
||||
- world
|
||||
#种植此农作物需要玩家有什么权限
|
||||
permission: 'customcrops.plant.tomato'
|
||||
|
||||
cabbage:
|
||||
@@ -62,13 +90,14 @@ crops:
|
||||
1: customcrops:grape
|
||||
2: customcrops:grape_silver_star
|
||||
3: customcrops:grape_golden_star
|
||||
#空手收获后返回第几个生长状态
|
||||
#可选
|
||||
#右键收获的时候农作物返回哪一个阶段
|
||||
return: customcrops:grape_stage_4
|
||||
season:
|
||||
- autumn
|
||||
|
||||
corn:
|
||||
amount: 1~2
|
||||
amount: 2~3
|
||||
quality:
|
||||
1: customcrops:corn
|
||||
2: customcrops:corn_silver_star
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
#MiniMessage Format
|
||||
#https://docs.adventure.kyori.net/minimessage/format.html
|
||||
messages:
|
||||
prefix: '<gradient:#ff206c:#fdee55>[CustomCrops] </gradient>'
|
||||
reload: '<white>重载成功! 耗时 <green>{time}ms'
|
||||
no-perm: '<red>权限不足!'
|
||||
lack-args: '<white>参数不足!'
|
||||
wrong-args: '<white>参数错误!'
|
||||
spring: '春'
|
||||
summer: '夏'
|
||||
autumn: '秋'
|
||||
winter: '冬'
|
||||
sprinkler-limit: '<white>此区块的洒水器已到达上限{max}'
|
||||
crop-limit: '<white>此区块的农作物数量已到达上限{max}'
|
||||
not-configed: '<white>此种子未在配置文件中配置!'
|
||||
bad-Y: '<white>此高度不适合这种农作物生长!'
|
||||
bad-biome: '<white>此生物群系不适合这种农作物生长!'
|
||||
bad-perm: '<white>你还没有权限种植这种农作物呢!'
|
||||
bad-world: '<white>这个农作物无法在这个世界生长!'
|
||||
bad-season: '<white>当前季节不适合这种农作物生长!'
|
||||
force-grow: '<white>成功强制 {world} 的农作物生长!'
|
||||
force-water: '<white>成功强制 {world} 的洒水器洒水!'
|
||||
force-save: '<white>成功强制保存缓存信息!'
|
||||
back-up: '<white>已完成数据备份!'
|
||||
set-season: '<white>成功切换世界 {world} 的季节为 {season}!'
|
||||
before-plant: '<white>这种肥料必须在种植前使用!'
|
||||
no-season: '当前世界没有季节'
|
||||
|
||||
#全息信息显示
|
||||
hologram:
|
||||
#农作物肥料信息
|
||||
grow-info:
|
||||
enable: true
|
||||
#悬浮信息高度偏移
|
||||
y-offset: 0.8
|
||||
#悬浮信息持续时间(秒)
|
||||
duration: 1
|
||||
#悬浮信息内容
|
||||
#可用变量 {fertilizer}肥料名 {times}剩余生效次数 {max_times}最大生效次数
|
||||
text: '<font:customcrops:default>{fertilizer} </font><white>{times}<gray>/<white>{max_times}'
|
||||
#洒水器信息
|
||||
sprinkler-info:
|
||||
enable: true
|
||||
y-offset: -0.2
|
||||
duration: 1
|
||||
#可用变量 {water}当前水量 {max_water}最大蓄水量
|
||||
left: '<font:customcrops:default>뀂'
|
||||
full: '뀁뀃'
|
||||
empty: '뀁뀄'
|
||||
right: '뀁뀅</font>'
|
||||
|
||||
actionbar:
|
||||
#使用水壶的时候是否发送actionbar
|
||||
watering-can:
|
||||
enable: true
|
||||
#可用变量 {water}当前水量 {max_water}最大蓄水量
|
||||
left: '<font:customcrops:default>뀂'
|
||||
full: '뀁뀃'
|
||||
empty: '뀁뀄'
|
||||
right: '뀁뀅</font>'
|
||||
Reference in New Issue
Block a user