From f3a09d94e0eacca556f69d7a94d424eeeae146a8 Mon Sep 17 00:00:00 2001 From: Xiao-MoMi <70987828+Xiao-MoMi@users.noreply.github.com> Date: Tue, 2 Aug 2022 16:02:53 +0800 Subject: [PATCH] 1.5.22 --- .../momirealms/customcrops/ConfigReader.java | 14 +- .../momirealms/customcrops/CustomCrops.java | 9 +- .../customcrops/commands/Executor.java | 14 +- .../customcrops/datamanager/CropManager.java | 577 ++++++++++-------- .../datamanager/MushroomManager.java | 7 - .../datamanager/SprinklerManager.java | 304 ++++++--- .../customcrops/listener/BreakFurniture.java | 23 + .../customcrops/listener/InteractEntity.java | 184 +++--- .../customcrops/listener/JoinAndQuit.java | 23 + .../customcrops/listener/RightClick.java | 9 +- .../customcrops/timer/TimeCheck.java | 14 +- .../customcrops/utils/IAFurniture.java | 1 + .../customcrops/utils/Sprinkler.java | 3 + src/main/resources/basic.yml | 8 +- src/main/resources/config.yml | 75 ++- src/main/resources/fertilizer.yml | 7 +- src/main/resources/season.yml | 1 + src/main/resources/zh-cn/config.yml | 19 +- 18 files changed, 800 insertions(+), 492 deletions(-) delete mode 100644 src/main/java/net/momirealms/customcrops/datamanager/MushroomManager.java create mode 100644 src/main/java/net/momirealms/customcrops/listener/BreakFurniture.java create mode 100644 src/main/java/net/momirealms/customcrops/listener/JoinAndQuit.java diff --git a/src/main/java/net/momirealms/customcrops/ConfigReader.java b/src/main/java/net/momirealms/customcrops/ConfigReader.java index 4c9bb53..f92d29b 100644 --- a/src/main/java/net/momirealms/customcrops/ConfigReader.java +++ b/src/main/java/net/momirealms/customcrops/ConfigReader.java @@ -58,13 +58,13 @@ public class ConfigReader { } public static void ReloadConfig(){ + Sounds.loadSound(); Config.loadConfig(); + Season.loadSeason(); Message.loadMessage(); Basic.loadBasic(); - cropLoad(); fertilizerLoad(); - Season.loadSeason(); - Sounds.loadSound(); + cropLoad(); } public static class Config{ @@ -88,7 +88,7 @@ public class ConfigReader { public static int timeToGrow; public static int timeToWork; public static boolean logTime; - public static boolean onlyLoadedGrow; + public static int growMode; public static boolean quality; public static boolean canAddWater; public static boolean allWorld; @@ -115,16 +115,16 @@ public class ConfigReader { cropGrowTimeList = config.getLongList("config.grow-time"); cropGrowTimeList.forEach(time -> { if(time < 0 || time > 23999){ - AdventureManager.consoleMessage("[CustomCrops] time should be between 0 and 23999"); + AdventureManager.consoleMessage("[CustomCrops] Grow time should be between 0 and 23999"); } }); 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); - onlyLoadedGrow = !config.getBoolean("config.only-grow-in-loaded-chunks",true); + 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); rightClickHarvest = config.getBoolean("config.right-click-harvest", true); diff --git a/src/main/java/net/momirealms/customcrops/CustomCrops.java b/src/main/java/net/momirealms/customcrops/CustomCrops.java index cb3ff4c..cc48597 100644 --- a/src/main/java/net/momirealms/customcrops/CustomCrops.java +++ b/src/main/java/net/momirealms/customcrops/CustomCrops.java @@ -21,10 +21,7 @@ import net.kyori.adventure.platform.bukkit.BukkitAudiences; import net.momirealms.customcrops.commands.Executor; import net.momirealms.customcrops.commands.Completer; import net.momirealms.customcrops.datamanager.*; -import net.momirealms.customcrops.listener.BreakBlock; -import net.momirealms.customcrops.listener.InteractEntity; -import net.momirealms.customcrops.listener.ItemSpawn; -import net.momirealms.customcrops.listener.RightClick; +import net.momirealms.customcrops.listener.*; import net.momirealms.customcrops.timer.CropTimer; import net.momirealms.customcrops.utils.AdventureManager; import net.momirealms.customcrops.utils.BackUp; @@ -77,6 +74,8 @@ public final class CustomCrops extends JavaPlugin { Bukkit.getPluginManager().registerEvents(new ItemSpawn(), this); Bukkit.getPluginManager().registerEvents(new RightClick(), this); Bukkit.getPluginManager().registerEvents(new BreakBlock(), this); + Bukkit.getPluginManager().registerEvents(new JoinAndQuit(), this); + Bukkit.getPluginManager().registerEvents(new BreakFurniture(), this); Bukkit.getPluginManager().registerEvents(new InteractEntity(this), this); if (ConfigReader.Season.enable){ @@ -103,6 +102,7 @@ public final class CustomCrops extends JavaPlugin { if (this.cropManager != null){ this.cropManager.cleanData(); + this.cropManager.updateData(); this.cropManager.saveData(); this.cropManager = null; } @@ -112,6 +112,7 @@ public final class CustomCrops extends JavaPlugin { } if (this.sprinklerManager != null){ this.sprinklerManager.cleanData(); + this.sprinklerManager.updateData(); this.sprinklerManager.saveData(); this.sprinklerManager = null; } diff --git a/src/main/java/net/momirealms/customcrops/commands/Executor.java b/src/main/java/net/momirealms/customcrops/commands/Executor.java index 84707ad..ac2b629 100644 --- a/src/main/java/net/momirealms/customcrops/commands/Executor.java +++ b/src/main/java/net/momirealms/customcrops/commands/Executor.java @@ -67,7 +67,12 @@ public class Executor implements CommandExecutor { return true; } Bukkit.getScheduler().runTaskAsynchronously(CustomCrops.instance, ()-> { - plugin.getCropManager().cropGrow(args[1]); + switch (ConfigReader.Config.growMode){ + case 1 -> plugin.getCropManager().growModeOne(args[1]); + case 2 -> plugin.getCropManager().growModeTwo(args[1]); + case 3 -> plugin.getCropManager().growModeThree(args[1]); + case 4 -> plugin.getCropManager().growModeFour(args[1]); + } }); if (sender instanceof Player player){ AdventureManager.playerMessage(player,ConfigReader.Message.prefix + ConfigReader.Message.forceGrow.replace("{world}",args[1])); @@ -82,7 +87,12 @@ public class Executor implements CommandExecutor { return true; } Bukkit.getScheduler().runTaskAsynchronously(CustomCrops.instance, ()-> { - plugin.getSprinklerManager().sprinklerWork(args[1]); + switch (ConfigReader.Config.growMode){ + case 1 -> plugin.getSprinklerManager().workModeOne(args[1]); + case 2 -> plugin.getSprinklerManager().workModeTwo(args[1]); + case 3 -> plugin.getSprinklerManager().workModeThree(args[1]); + case 4 -> plugin.getSprinklerManager().workModeFour(args[1]); + } }); if (sender instanceof Player player){ AdventureManager.playerMessage(player,ConfigReader.Message.prefix + ConfigReader.Message.forceWater.replace("{world}",args[1])); diff --git a/src/main/java/net/momirealms/customcrops/datamanager/CropManager.java b/src/main/java/net/momirealms/customcrops/datamanager/CropManager.java index 54f718c..aea7dc6 100644 --- a/src/main/java/net/momirealms/customcrops/datamanager/CropManager.java +++ b/src/main/java/net/momirealms/customcrops/datamanager/CropManager.java @@ -18,8 +18,8 @@ package net.momirealms.customcrops.datamanager; import dev.lone.itemsadder.api.CustomBlock; -import dev.lone.itemsadder.api.CustomStack; import net.momirealms.customcrops.fertilizer.QualityCrop; +import net.momirealms.customcrops.listener.JoinAndQuit; import net.momirealms.customcrops.utils.AdventureManager; import net.momirealms.customcrops.ConfigReader; import net.momirealms.customcrops.CustomCrops; @@ -37,8 +37,8 @@ import org.bukkit.scheduler.BukkitScheduler; import java.io.File; import java.io.IOException; +import java.util.HashSet; import java.util.List; -import java.util.Map; import java.util.Random; import java.util.concurrent.ConcurrentHashMap; @@ -83,7 +83,7 @@ public class CropManager { } /** - * 将hashmap中的数据保存到data中 + * 将数据保存到data中 */ public void updateData(){ Cache.forEach((location, String) -> { @@ -108,139 +108,157 @@ public class CropManager { } /** - * 农作物生长 + * 农作物生长,Mode 1 + * 仅加载区块生长 * @param worldName 进行生长判定的世界名 */ - public void cropGrow(String worldName){ - + public void growModeOne(String worldName){ Long time1 = System.currentTimeMillis(); - updateData(); - Long time2 = System.currentTimeMillis(); - if(ConfigReader.Config.logTime){ - AdventureManager.consoleMessage("性能监测: 农作物数据更新" + (time2-time1) + "ms"); + if(!ConfigReader.Config.allWorld){ + updateData(); } + Long time2 = System.currentTimeMillis(); + if(ConfigReader.Config.logTime) AdventureManager.consoleMessage("性能监测: 农作物数据更新" + (time2-time1) + "ms"); if (data.contains(worldName)){ + World world = Bukkit.getWorld(worldName); data.getConfigurationSection(worldName).getKeys(false).forEach(chunk ->{ String[] split = StringUtils.split(chunk,","); - World world = Bukkit.getWorld(worldName); - if (ConfigReader.Config.onlyLoadedGrow || world.isChunkLoaded(Integer.parseInt(split[0]), Integer.parseInt(split[1]))){ + 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])); - CustomBlock seedBlock = CustomBlock.byAlreadyPlaced(seedLocation.getBlock()); - StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.append(worldName).append(".").append(chunk).append(".").append(key); - if(seedBlock == null) { - data.set(stringBuilder.toString(), null); - return; - } - String namespacedID = seedBlock.getNamespacedID(); - String id = seedBlock.getId(); - if(namespacedID.equals(ConfigReader.Basic.dead)) { - data.set(stringBuilder.toString(), null); - return; - } - if(!namespacedID.contains("_stage_")) { - data.set(stringBuilder.toString(), null); - return; - } - Location potLocation = seedLocation.clone().subtract(0,1,0); - CustomBlock pot = CustomBlock.byAlreadyPlaced(potLocation.getBlock()); - String potNamespacedID = pot.getNamespacedID(); - String[] cropNameList = StringUtils.split(id,"_"); - CropInstance cropInstance = ConfigReader.CROPS.get(cropNameList[0]); - if (pot == null || cropInstance == null){ - data.set(stringBuilder.toString(), null); - return; - } - int random = new Random().nextInt(ConfigReader.Config.timeToGrow); - if (potNamespacedID.equals(ConfigReader.Basic.watered_pot)){ - //如果启用季节限制且农作物有季节需求 - if (ConfigReader.Season.enable && cropInstance.getSeasons() != null){ - if (isWrongSeason(seedLocation, cropInstance.getSeasons(), worldName)){ - data.set(stringBuilder.toString(), null); - bukkitScheduler.runTaskLater(CustomCrops.instance, () -> { - CustomBlock.remove(seedLocation); - CustomBlock.place(ConfigReader.Basic.dead, seedLocation); - }, random); - return; - } - } - int nextStage = Integer.parseInt(cropNameList[2]) + 1; - if (CustomBlock.getInstance(StringUtils.chop(namespacedID) + nextStage) != null && cropInstance.getGrowChance() > Math.random()) { - Fertilizer fertilizer = PotManager.Cache.get(SimpleLocation.fromLocation(potLocation)); - if (fertilizer != null){ - int times = fertilizer.getTimes(); - if (times > 0){ - fertilizer.setTimes(times - 1); - if (fertilizer instanceof SpeedGrow speedGrow){ - if (Math.random() < speedGrow.getChance() && CustomBlock.getInstance(StringUtils.chop(namespacedID) + (nextStage + 1)) != null){ - addStage(potLocation, seedLocation, namespacedID, nextStage + 1, random); - }else { - addStage(potLocation, seedLocation, namespacedID, nextStage, random); - } - }else if(fertilizer instanceof RetainingSoil retainingSoil){ - if (Math.random() < retainingSoil.getChance()){ - addStage(seedLocation, namespacedID, nextStage, random); - }else { - addStage(potLocation, seedLocation, namespacedID, nextStage, random); - } - }else if(fertilizer instanceof QualityCrop){ - addStage(potLocation, seedLocation, namespacedID, nextStage, random); - }else { - AdventureManager.consoleMessage("[CustomCrops] 发现未知类型肥料,已自动清除错误数据!"); - PotManager.Cache.remove(SimpleLocation.fromLocation(potLocation)); - } - }else { - PotManager.Cache.remove(SimpleLocation.fromLocation(potLocation)); - } - } - else { - addStage(potLocation, seedLocation, namespacedID, nextStage, random); - } - } - else if(cropInstance.getGiant() != null){ - bukkitScheduler.runTaskLater(CustomCrops.instance, () ->{ - CustomBlock.remove(potLocation); - CustomBlock.place(ConfigReader.Basic.pot, potLocation); - if(cropInstance.getGiantChance() > Math.random()){ - data.set(stringBuilder.toString(), null); - CustomBlock.remove(seedLocation); - CustomBlock.place(cropInstance.getGiant(), seedLocation); - } - }, random); - }else { - if (!ConfigReader.Season.enable) data.set(stringBuilder.toString(), null); - bukkitScheduler.runTaskLater(CustomCrops.instance, () -> { - CustomBlock.remove(potLocation); - CustomBlock.place(ConfigReader.Basic.pot, potLocation); - }, random); - } - }else if(potNamespacedID.equals(ConfigReader.Basic.pot)){ - if(!ConfigReader.Season.enable || cropInstance.getSeasons() == null) return; - if(isWrongSeason(seedLocation, cropInstance.getSeasons(), worldName)){ - data.set(stringBuilder.toString(), null); - bukkitScheduler.runTaskLater(CustomCrops.instance, () -> { - CustomBlock.remove(seedLocation); - CustomBlock.place(ConfigReader.Basic.dead, seedLocation); - }, random); - } - }else { - data.set(stringBuilder.toString(), null); + if (growJudge(worldName, seedLocation)){ + data.set(worldName + "." + chunk + "." + key, null); } }); } }); } Long time3 = System.currentTimeMillis(); - if(ConfigReader.Config.logTime){ - AdventureManager.consoleMessage("性能监测: 农作物生长过程" + (time3-time2) + "ms"); + if(ConfigReader.Config.logTime) AdventureManager.consoleMessage("性能监测: 农作物生长过程" + (time3-time2) + "ms"); + if(!ConfigReader.Config.allWorld){ + saveData(); } - saveData(); Long time4 = System.currentTimeMillis(); - if(ConfigReader.Config.logTime){ - AdventureManager.consoleMessage("性能监测: 农作物数据保存" + (time4-time3) + "ms"); + if(ConfigReader.Config.logTime) AdventureManager.consoleMessage("性能监测: 农作物数据保存" + (time4-time3) + "ms"); + } + + /** + * 农作物生长,Mode 2 + * 仅在线玩家的农作物生长 + * @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 players = new HashSet<>(JoinAndQuit.onlinePlayers); + if (data.contains(worldName)){ + World world = Bukkit.getWorld(worldName); + 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])); + if (growJudge(worldName, seedLocation)){ + data.set(worldName + "." + chunk + "." + key, 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"); + } + + /** + * 农作物生长,Mode 3 + * 仅在线玩家和加载区块的农作物生长 + * @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 players = new HashSet<>(JoinAndQuit.onlinePlayers); + if (data.contains(worldName)){ + World world = Bukkit.getWorld(worldName); + 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])); + if (growJudge(worldName, seedLocation)){ + data.set(worldName + "." + chunk + "." + key, null); + } + }); + } + //区块未加载,玩家在线 + 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])); + if (growJudge(worldName, seedLocation)){ + data.set(worldName + "." + chunk + "." + key, 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"); + } + + /** + * 农作物生长,Mode 4 + * 全部农作物生长 + * @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 (data.contains(worldName)){ + World world = Bukkit.getWorld(worldName); + 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])); + if (growJudge(worldName, seedLocation)){ + data.set(worldName + "." + chunk + "." + key, 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"); } /** @@ -248,135 +266,198 @@ public class CropManager { * 对于使用动态加载世界的服务器有效 */ public void cropGrowAll(){ - Long time1 = System.currentTimeMillis(); updateData(); - Long time2 = System.currentTimeMillis(); - if(ConfigReader.Config.logTime){ - AdventureManager.consoleMessage("性能监测: 农作物数据更新" + (time2-time1) + "ms"); - } - Bukkit.getWorlds().forEach(world -> { - String worldName = world.getName(); - if (data.contains(worldName)){ - data.getConfigurationSection(worldName).getKeys(false).forEach(chunk ->{ - String[] split = StringUtils.split(chunk,","); - if (ConfigReader.Config.onlyLoadedGrow || world.isChunkLoaded(Integer.parseInt(split[0]), Integer.parseInt(split[1]))){ - data.getConfigurationSection(worldName + "." + chunk).getValues(false).forEach((key, value) -> { - String[] coordinate = StringUtils.split(key, ","); - Location seedLocation = new Location(world,Double.parseDouble(coordinate[0]),Double.parseDouble(coordinate[1]),Double.parseDouble(coordinate[2])); - CustomBlock seedBlock = CustomBlock.byAlreadyPlaced(seedLocation.getBlock()); - StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.append(worldName).append(".").append(chunk).append(".").append(key); - if(seedBlock == null) { - data.set(stringBuilder.toString(), null); - return; - } - String namespacedID = seedBlock.getNamespacedID(); - String id = seedBlock.getId(); - if(namespacedID.equals(ConfigReader.Basic.dead)) { - data.set(stringBuilder.toString(), null); - return; - } - if(!namespacedID.contains("_stage_")) { - data.set(stringBuilder.toString(), null); - return; - } - Location potLocation = seedLocation.clone().subtract(0,1,0); - CustomBlock pot = CustomBlock.byAlreadyPlaced(potLocation.getBlock()); - String potNamespacedID = pot.getNamespacedID(); - String[] cropNameList = StringUtils.split(id,"_"); - CropInstance cropInstance = ConfigReader.CROPS.get(cropNameList[0]); - if (pot == null || cropInstance == null){ - data.set(stringBuilder.toString(), null); - return; - } - int random = new Random().nextInt(ConfigReader.Config.timeToGrow); - if (potNamespacedID.equals(ConfigReader.Basic.watered_pot)){ - if (ConfigReader.Season.enable && cropInstance.getSeasons() != null){ - if (isWrongSeason(seedLocation, cropInstance.getSeasons(), worldName)){ - data.set(stringBuilder.toString(), null); - bukkitScheduler.runTaskLater(CustomCrops.instance, () -> { - CustomBlock.remove(seedLocation); - CustomBlock.place(ConfigReader.Basic.dead, seedLocation); - }, random); - return; - } - } - int nextStage = Integer.parseInt(cropNameList[2]) + 1; - if (CustomBlock.getInstance(StringUtils.chop(namespacedID) + nextStage) != null && cropInstance.getGrowChance() > Math.random()) { - Fertilizer fertilizer = PotManager.Cache.get(SimpleLocation.fromLocation(potLocation)); - if (fertilizer != null){ - int times = fertilizer.getTimes(); - if (times > 0){ - fertilizer.setTimes(times - 1); - if (fertilizer instanceof SpeedGrow speedGrow){ - if (Math.random() < speedGrow.getChance() && CustomBlock.getInstance(StringUtils.chop(namespacedID) + (nextStage + 1)) != null){ - addStage(potLocation, seedLocation, namespacedID, nextStage + 1, random); - }else { - addStage(potLocation, seedLocation, namespacedID, nextStage, random); - } - }else if(fertilizer instanceof RetainingSoil retainingSoil){ - if (Math.random() < retainingSoil.getChance()){ - addStage(seedLocation, namespacedID, nextStage, random); - }else { - addStage(potLocation, seedLocation, namespacedID, nextStage, random); - } - }else if(fertilizer instanceof QualityCrop){ - addStage(potLocation, seedLocation, namespacedID, nextStage, random); - }else { - AdventureManager.consoleMessage("[CustomCrops] 发现未知类型肥料,已自动清除错误数据!"); - PotManager.Cache.remove(SimpleLocation.fromLocation(potLocation)); - } - }else { - PotManager.Cache.remove(SimpleLocation.fromLocation(potLocation)); - } - } - else { - addStage(potLocation, seedLocation, namespacedID, nextStage, random); - } - } - else if(cropInstance.getGiant() != null){ - bukkitScheduler.runTaskLater(CustomCrops.instance, () ->{ - CustomBlock.remove(potLocation); - CustomBlock.place(ConfigReader.Basic.pot, potLocation); - if(cropInstance.getGiantChance() > Math.random()){ - data.set(stringBuilder.toString(), null); - CustomBlock.remove(seedLocation); - CustomBlock.place(cropInstance.getGiant(), seedLocation); - } - }, random); - }else { - if (!ConfigReader.Season.enable) data.set(stringBuilder.toString(), null); - bukkitScheduler.runTaskLater(CustomCrops.instance, () -> { - CustomBlock.remove(potLocation); - CustomBlock.place(ConfigReader.Basic.pot, potLocation); - }, random); - } - }else if(potNamespacedID.equals(ConfigReader.Basic.pot)){ - if(!ConfigReader.Season.enable || cropInstance.getSeasons() == null) return; - if(isWrongSeason(seedLocation, cropInstance.getSeasons(), worldName)){ - data.set(stringBuilder.toString(), null); - bukkitScheduler.runTaskLater(CustomCrops.instance, () -> { - CustomBlock.remove(seedLocation); - CustomBlock.place(ConfigReader.Basic.dead, seedLocation); - }, random); - } - }else { - data.set(stringBuilder.toString(), null); - } - }); - } - }); - } - }); - Long time3 = System.currentTimeMillis(); - if(ConfigReader.Config.logTime){ - AdventureManager.consoleMessage("性能监测: 农作物生长过程" + (time3-time2) + "ms"); + List worlds = Bukkit.getWorlds(); + for (int i = 0; i < worlds.size(); i++){ + String worldName = worlds.get(i).getName(); + bukkitScheduler.runTaskLaterAsynchronously(CustomCrops.instance, () -> { + switch (ConfigReader.Config.growMode){ + case 1 -> growModeOne(worldName); + case 2 -> growModeTwo(worldName); + case 3 -> growModeThree(worldName); + case 4 -> growModeFour(worldName); + } + }, i * 40L); } saveData(); - Long time4 = System.currentTimeMillis(); - if(ConfigReader.Config.logTime){ - AdventureManager.consoleMessage("性能监测: 农作物数据保存" + (time4-time3) + "ms"); + } + + /** + * 对某个位置进行生长判定 + * @param worldName 世界名 + * @param seedLocation 种子位置 + * @return 是否消除数据 + */ + private boolean growJudge(String worldName, Location seedLocation) { + CustomBlock seedBlock = CustomBlock.byAlreadyPlaced(seedLocation.getBlock()); + //自定义农作物方块不存在 + if(seedBlock == null) { + return true; } + String namespacedID = seedBlock.getNamespacedID(); + String id = seedBlock.getId(); + //已死亡或不是农作物 + if(namespacedID.equals(ConfigReader.Basic.dead) || !namespacedID.contains("_stage_")) { + return true; + } + //农作物下方自定义方块不存在 + Location potLocation = seedLocation.clone().subtract(0,1,0); + CustomBlock pot = CustomBlock.byAlreadyPlaced(potLocation.getBlock()); + if (pot == null){ + return true; + } + //农作物实例不存在 + String[] cropNameList = StringUtils.split(id,"_"); + CropInstance cropInstance = ConfigReader.CROPS.get(cropNameList[0]); + if (cropInstance == null){ + return true; + } + //获取自定义方块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.instance, () -> { + CustomBlock.remove(seedLocation); + CustomBlock.place(ConfigReader.Basic.dead, seedLocation); + }, random); + return true; + + } + } + //获取下一阶段 + int nextStage = Integer.parseInt(cropNameList[2]) + 1; + //下一阶段存在 + if (CustomBlock.getInstance(StringUtils.chop(namespacedID) + nextStage) != null) { + //尝试获取肥料类型 + Fertilizer fertilizer = PotManager.Cache.get(SimpleLocation.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){ + addStage(potLocation, seedLocation, namespacedID, nextStage + 1, random); + }else { + addStage(potLocation, seedLocation, namespacedID, nextStage, random); + } + }else { + notAddStage(potLocation, random); + } + } + //保湿土壤 + else if(fertilizer instanceof RetainingSoil retainingSoil){ + if (Math.random() < retainingSoil.getChance()){ + if (cropInstance.getGrowChance() > Math.random()){ + addStage(seedLocation, namespacedID, nextStage, random); + } + }else { + if (cropInstance.getGrowChance() > Math.random()){ + addStage(potLocation, seedLocation, namespacedID, nextStage, random); + }else { + notAddStage(potLocation, random); + } + } + } + //品质肥料 + else if(fertilizer instanceof QualityCrop){ + if (cropInstance.getGrowChance() > Math.random()){ + addStage(potLocation, seedLocation, namespacedID, nextStage, random); + }else { + notAddStage(potLocation, random); + } + }else { + //未知肥料类型处理 + AdventureManager.consoleMessage("[CustomCrops] Unknown fertilizer, Auto removed!"); + PotManager.Cache.remove(SimpleLocation.fromLocation(potLocation)); + + if (cropInstance.getGrowChance() > Math.random()){ + addStage(potLocation, seedLocation, namespacedID, nextStage, random); + }else { + notAddStage(potLocation, random); + } + } + //肥料的最后一次使用 + if (times == 1){ + PotManager.Cache.remove(SimpleLocation.fromLocation(potLocation)); + } + } + else { + //移除肥料信息,一般不会出现此情况 + PotManager.Cache.remove(SimpleLocation.fromLocation(potLocation)); + if (cropInstance.getGrowChance() > Math.random()){ + addStage(potLocation, seedLocation, namespacedID, nextStage, random); + }else { + notAddStage(potLocation, random); + } + } + } + //没有肥料 + else { + if (cropInstance.getGrowChance() > Math.random()){ + addStage(potLocation, seedLocation, namespacedID, nextStage, random); + }else { + notAddStage(potLocation, random); + } + } + } + //农作物是否存在巨大化 + else if(cropInstance.getGiant() != null){ + //巨大化判定 + if (cropInstance.getGiantChance() > Math.random()){ + //成功巨大化,移除数据 + bukkitScheduler.runTaskLater(CustomCrops.instance, () ->{ + CustomBlock.remove(seedLocation); + CustomBlock.place(cropInstance.getGiant(), seedLocation); + CustomBlock.remove(potLocation); + CustomBlock.place(ConfigReader.Basic.pot, potLocation); + }, random); + return true; + }else { + //失败,转湿为干 + bukkitScheduler.runTaskLater(CustomCrops.instance, () ->{ + CustomBlock.remove(potLocation); + CustomBlock.place(ConfigReader.Basic.pot, potLocation); + }, random); + } + }else { + //若无下一阶段,无巨大化,未启用季节,则移除无用数据 + if (!ConfigReader.Season.enable) return true; + bukkitScheduler.runTaskLater(CustomCrops.instance, () -> { + CustomBlock.remove(potLocation); + CustomBlock.place(ConfigReader.Basic.pot, potLocation); + }, random); + } + } + //干燥的种植盆 + else if(potNamespacedID.equals(ConfigReader.Basic.pot)){ + //未启用季节 + if(!ConfigReader.Season.enable) return false; + //农作物无视季节 + List seasons = cropInstance.getSeasons(); + if(seasons == null) return false; + //错误季节 + if(isWrongSeason(seedLocation, seasons, worldName)){ + bukkitScheduler.runTaskLater(CustomCrops.instance, () -> { + CustomBlock.remove(seedLocation); + CustomBlock.place(ConfigReader.Basic.dead, seedLocation); + }, new Random().nextInt(ConfigReader.Config.timeToGrow)); + return true; + } + } + //不是种植盆 + else { + return true; + } + return false; } /** @@ -444,4 +525,16 @@ public class CropManager { CustomBlock.place(stage, seedLocation); }, random); } + + /** + * 停滞阶段(消耗水) + * @param potLocation 种植盆位置 + * @param random 随机生长时间 + */ + private void notAddStage(Location potLocation, int random){ + bukkitScheduler.runTaskLater(CustomCrops.instance, () ->{ + CustomBlock.remove(potLocation); + CustomBlock.place(ConfigReader.Basic.pot, potLocation); + }, random); + } } \ No newline at end of file diff --git a/src/main/java/net/momirealms/customcrops/datamanager/MushroomManager.java b/src/main/java/net/momirealms/customcrops/datamanager/MushroomManager.java deleted file mode 100644 index d7a4031..0000000 --- a/src/main/java/net/momirealms/customcrops/datamanager/MushroomManager.java +++ /dev/null @@ -1,7 +0,0 @@ -package net.momirealms.customcrops.datamanager; - -public class MushroomManager { - - //A new feature coming - -} diff --git a/src/main/java/net/momirealms/customcrops/datamanager/SprinklerManager.java b/src/main/java/net/momirealms/customcrops/datamanager/SprinklerManager.java index 5e893d3..eaa4784 100644 --- a/src/main/java/net/momirealms/customcrops/datamanager/SprinklerManager.java +++ b/src/main/java/net/momirealms/customcrops/datamanager/SprinklerManager.java @@ -18,10 +18,12 @@ package net.momirealms.customcrops.datamanager; import dev.lone.itemsadder.api.CustomBlock; +import net.momirealms.customcrops.listener.JoinAndQuit; import net.momirealms.customcrops.utils.AdventureManager; import net.momirealms.customcrops.ConfigReader; import net.momirealms.customcrops.CustomCrops; import net.momirealms.customcrops.utils.IAFurniture; +import net.momirealms.customcrops.utils.SimpleLocation; import net.momirealms.customcrops.utils.Sprinkler; import org.apache.commons.lang.StringUtils; import org.bukkit.Bukkit; @@ -33,13 +35,19 @@ import org.bukkit.scheduler.BukkitScheduler; import java.io.File; import java.io.IOException; -import java.util.Random; +import java.util.*; import java.util.concurrent.ConcurrentHashMap; public class SprinklerManager { public YamlConfiguration data; - public static ConcurrentHashMap Cache = new ConcurrentHashMap<>(); + public static ConcurrentHashMap Cache = new ConcurrentHashMap<>(); + public static HashSet RemoveCache = new HashSet<>(); + private final BukkitScheduler bukkitScheduler; + + public SprinklerManager(){ + this.bukkitScheduler = Bukkit.getScheduler(); + } /** * 载入数据 @@ -85,48 +93,55 @@ public class SprinklerManager { } /** - * 将hashmap中的数据保存到data中 + * 将数据保存到data中 */ public void updateData(){ Cache.forEach((location, sprinklerData) -> { - String world = location.getWorld().getName(); - int x = location.getBlockX(); - int z = location.getBlockZ(); - StringBuilder stringBuilder = new StringBuilder().append(world).append(".").append(x/16).append(",").append(z/16).append(".").append(x).append(",").append(location.getBlockY()).append(",").append(z); + String world = location.getWorldName(); + int x = location.getX(); + int z = location.getZ(); + StringBuilder stringBuilder = new StringBuilder().append(world).append(".").append(x/16).append(",").append(z/16).append(".").append(x).append(",").append(location.getY()).append(",").append(z); data.set(stringBuilder+".range", sprinklerData.getRange()); data.set(stringBuilder+".water", sprinklerData.getWater()); + data.set(stringBuilder+".player", Optional.ofNullable(sprinklerData.getPlayer()).orElse("none")); }); Cache.clear(); + HashSet set = new HashSet<>(RemoveCache); + for (SimpleLocation location : set) { + String world = location.getWorldName(); + int x = location.getX(); + int z = location.getZ(); + data.set(world + "." + x / 16 + "," + z / 16 + "." + x + "," + location.getY() + "," + z, null); + } + RemoveCache.clear(); } /** - * 指定世界的洒水器工作 + * 洒水器工作,Mode 1 * @param worldName 世界名 */ - public void sprinklerWork(String worldName){ + public void workModeOne(String worldName){ Long time1 = System.currentTimeMillis(); - updateData(); - Long time2 = System.currentTimeMillis(); - if (ConfigReader.Config.logTime){ - AdventureManager.consoleMessage("性能监测: 洒水器数据更新" + (time2-time1) + "ms"); + if(!ConfigReader.Config.allWorld){ + updateData(); } + Long time2 = System.currentTimeMillis(); + if (ConfigReader.Config.logTime) AdventureManager.consoleMessage("性能监测: 洒水器数据更新" + (time2-time1) + "ms"); if (data.contains(worldName)){ - BukkitScheduler bukkitScheduler = Bukkit.getScheduler(); + World world = Bukkit.getWorld(worldName); data.getConfigurationSection(worldName).getKeys(false).forEach(chunk ->{ String[] split = StringUtils.split(chunk,","); - World world = Bukkit.getWorld(worldName); - if (ConfigReader.Config.onlyLoadedGrow || world.isChunkLoaded(Integer.parseInt(split[0]), Integer.parseInt(split[1]))) { + 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 location = new Location(world,Double.parseDouble(coordinate[0])+0.5,Double.parseDouble(coordinate[1])+0.5,Double.parseDouble(coordinate[2])+0.5); - int random = new Random().nextInt(ConfigReader.Config.timeToWork); if (value instanceof MemorySection map){ - bukkitScheduler.callSyncMethod(CustomCrops.instance, ()->{ + bukkitScheduler.runTask(CustomCrops.instance, ()->{ int water = (int) map.get("water"); int range = (int) map.get("range"); if(!IAFurniture.getFromLocation(location, world)){ data.set(worldName + "." + chunk + "." + key, null); - return null; + return; } if (water > 0){ data.set(worldName + "." + chunk + "." + key + ".water", water - 1); @@ -136,10 +151,9 @@ public class SprinklerManager { waterPot(location.clone().add(i,-1,j)); } } - }, random); + }, new Random().nextInt(ConfigReader.Config.timeToWork)); } if (range == 0) data.set(worldName + "." + chunk + "." + key, null); - return null; }); } }); @@ -147,73 +161,211 @@ public class SprinklerManager { }); } Long time3 = System.currentTimeMillis(); - if(ConfigReader.Config.logTime){ - AdventureManager.consoleMessage("性能监测: 洒水器工作过程" + (time3-time2) + "ms"); + if(ConfigReader.Config.logTime) AdventureManager.consoleMessage("性能监测: 洒水器工作过程" + (time3-time2) + "ms"); + if(!ConfigReader.Config.allWorld){ + saveData(); } - saveData(); Long time4 = System.currentTimeMillis(); - if(ConfigReader.Config.logTime){ - AdventureManager.consoleMessage("性能监测: 洒水器数据保存" + (time4-time3) + "ms"); + if(ConfigReader.Config.logTime) AdventureManager.consoleMessage("性能监测: 洒水器数据保存" + (time4-time3) + "ms"); + } + + /** + * 洒水器工作,Mode 2 + * @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 players = new HashSet<>(JoinAndQuit.onlinePlayers); + if (data.contains(worldName)){ + World world = Bukkit.getWorld(worldName); + data.getConfigurationSection(worldName).getKeys(false).forEach(chunk ->{ + data.getConfigurationSection(worldName + "." + chunk).getValues(false).forEach((key, value) -> { + if (value instanceof MemorySection map){ + String player = (String) map.get("player"); + if (player == null) { + data.set(worldName + "." + chunk + "." + key + ".player", "none"); + return; + } + 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.instance, ()->{ + int water = (int) map.get("water"); + int range = (int) map.get("range"); + if (water > 0){ + data.set(worldName + "." + chunk + "." + key + ".water", water - 1); + bukkitScheduler.runTaskLater(CustomCrops.instance, ()-> { + for(int i = -range; i <= range; i++){ + for (int j = -range; j <= range; j++){ + waterPot(location.clone().add(i,-1,j)); + } + } + }, 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"); + } + + /** + * 洒水器工作,Mode 3 + * @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 players = new HashSet<>(JoinAndQuit.onlinePlayers); + if (data.contains(worldName)){ + World world = Bukkit.getWorld(worldName); + 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 location = new Location(world,Double.parseDouble(coordinate[0])+0.5,Double.parseDouble(coordinate[1])+0.5,Double.parseDouble(coordinate[2])+0.5); + if (value instanceof MemorySection map){ + int water = (int) map.get("water"); + int range = (int) map.get("range"); + bukkitScheduler.runTask(CustomCrops.instance, ()->{ + if(!IAFurniture.getFromLocation(location, world)){ + data.set(worldName + "." + chunk + "." + key, null); + return; + } + if (water > 0){ + data.set(worldName + "." + chunk + "." + key + ".water", water - 1); + bukkitScheduler.runTaskLater(CustomCrops.instance, ()-> { + for(int i = -range; i <= range; i++){ + for (int j = -range; j <= range; j++){ + waterPot(location.clone().add(i,-1,j)); + } + } + }, new Random().nextInt(ConfigReader.Config.timeToWork)); + } + if (range == 0) data.set(worldName + "." + chunk + "." + key, null); + }); + } + }); + } + else { + data.getConfigurationSection(worldName + "." + chunk).getValues(false).forEach((key, value) -> { + if (value instanceof MemorySection map){ + String player = (String) map.get("player"); + if (player == null) { + data.set(worldName + "." + chunk + "." + key + ".player", "none"); + return; + } + 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); + int water = (int) map.get("water"); + int range = (int) map.get("range"); + if (water > 0){ + data.set(worldName + "." + chunk + "." + key + ".water", water - 1); + bukkitScheduler.runTaskLater(CustomCrops.instance, ()-> { + for(int i = -range; i <= range; i++){ + for (int j = -range; j <= range; j++){ + waterPot(location.clone().add(i,-1,j)); + } + } + }, new Random().nextInt(ConfigReader.Config.timeToWork)); + } + if (range == 0) data.set(worldName + "." + chunk + "." + key, 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"); + } + + /** + * 洒水器工作,Mode 4 + * @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 (data.contains(worldName)){ + World world = Bukkit.getWorld(worldName); + data.getConfigurationSection(worldName).getKeys(false).forEach(chunk ->{ + data.getConfigurationSection(worldName + "." + chunk).getValues(false).forEach((key, value) -> { + String[] coordinate = StringUtils.split(key, ","); + Location location = new Location(world,Double.parseDouble(coordinate[0])+0.5,Double.parseDouble(coordinate[1])+0.5,Double.parseDouble(coordinate[2])+0.5); + if (value instanceof MemorySection map){ + int water = (int) map.get("water"); + int range = (int) map.get("range"); + if (water > 0){ + data.set(worldName + "." + chunk + "." + key + ".water", water - 1); + bukkitScheduler.runTaskLater(CustomCrops.instance, ()-> { + for(int i = -range; i <= range; i++){ + for (int j = -range; j <= range; j++){ + waterPot(location.clone().add(i,-1,j)); + } + } + }, new Random().nextInt(ConfigReader.Config.timeToWork)); + } + if (range == 0) data.set(worldName + "." + chunk + "." + key, 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"); } /** * 所有世界的洒水器工作 */ public void sprinklerWorkAll(){ - Long time1 = System.currentTimeMillis(); updateData(); - Long time2 = System.currentTimeMillis(); - if (ConfigReader.Config.logTime){ - AdventureManager.consoleMessage("性能监测: 洒水器数据更新" + (time2-time1) + "ms"); - } - Bukkit.getWorlds().forEach(world -> { - String worldName = world.getName(); - if (data.contains(worldName)){ - BukkitScheduler bukkitScheduler = Bukkit.getScheduler(); - data.getConfigurationSection(worldName).getKeys(false).forEach(chunk ->{ - String[] split = StringUtils.split(chunk,","); - if (ConfigReader.Config.onlyLoadedGrow || world.isChunkLoaded(Integer.parseInt(split[0]), Integer.parseInt(split[1]))) { - data.getConfigurationSection(worldName + "." + chunk).getValues(false).forEach((key, value) -> { - String[] coordinate = StringUtils.split(key, ","); - Location location = new Location(world,Double.parseDouble(coordinate[0])+0.5,Double.parseDouble(coordinate[1])+0.5,Double.parseDouble(coordinate[2])+0.5); - int random = new Random().nextInt(ConfigReader.Config.timeToWork); - if (value instanceof MemorySection map){ - bukkitScheduler.callSyncMethod(CustomCrops.instance, ()->{ - int water = (int) map.get("water"); - int range = (int) map.get("range"); - if(!IAFurniture.getFromLocation(location, world)){ - data.set(worldName + "." + chunk + "." + key, null); - return null; - } - if (water > 0){ - data.set(worldName + "." + chunk + "." + key + ".water", water - 1); - bukkitScheduler.runTaskLater(CustomCrops.instance, ()-> { - for(int i = -range; i <= range; i++){ - for (int j = -range; j <= range; j++){ - waterPot(location.clone().add(i,-1,j)); - } - } - }, random); - } - if (range == 0) data.set(worldName + "." + chunk + "." + key, null); - return null; - }); - } - }); - } - }); - } - }); - Long time3 = System.currentTimeMillis(); - if(ConfigReader.Config.logTime){ - AdventureManager.consoleMessage("性能监测: 洒水器工作过程" + (time3-time2) + "ms"); + List worlds = Bukkit.getWorlds(); + for (int i = 0; i < worlds.size(); i++){ + String worldName = worlds.get(i).getName(); + bukkitScheduler.runTaskLaterAsynchronously(CustomCrops.instance, () -> { + switch (ConfigReader.Config.growMode){ + case 1 -> workModeOne(worldName); + case 2 -> workModeTwo(worldName); + case 3 -> workModeThree(worldName); + case 4 -> workModeFour(worldName); + } + }, i * 40L); } saveData(); - Long time4 = System.currentTimeMillis(); - if(ConfigReader.Config.logTime){ - AdventureManager.consoleMessage("性能监测: 洒水器数据保存" + (time4-time3) + "ms"); - } } /** diff --git a/src/main/java/net/momirealms/customcrops/listener/BreakFurniture.java b/src/main/java/net/momirealms/customcrops/listener/BreakFurniture.java new file mode 100644 index 0000000..3cdd638 --- /dev/null +++ b/src/main/java/net/momirealms/customcrops/listener/BreakFurniture.java @@ -0,0 +1,23 @@ +package net.momirealms.customcrops.listener; + +import dev.lone.itemsadder.api.Events.FurnitureBreakEvent; +import net.momirealms.customcrops.ConfigReader; +import net.momirealms.customcrops.datamanager.SprinklerManager; +import net.momirealms.customcrops.utils.SimpleLocation; +import net.momirealms.customcrops.utils.Sprinkler; +import org.apache.commons.lang.StringUtils; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; + +public class BreakFurniture implements Listener { + + @EventHandler + public void onBreakFurniture(FurnitureBreakEvent event){ + Sprinkler config = ConfigReader.SPRINKLERS.get(StringUtils.split(event.getNamespacedID(),":")[1]); + if (config != null){ + SimpleLocation simpleLocation = SimpleLocation.fromLocation(event.getBukkitEntity().getLocation()); + SprinklerManager.Cache.remove(simpleLocation); + SprinklerManager.RemoveCache.add(simpleLocation); + } + } +} \ No newline at end of file diff --git a/src/main/java/net/momirealms/customcrops/listener/InteractEntity.java b/src/main/java/net/momirealms/customcrops/listener/InteractEntity.java index ede9577..bec7eb5 100644 --- a/src/main/java/net/momirealms/customcrops/listener/InteractEntity.java +++ b/src/main/java/net/momirealms/customcrops/listener/InteractEntity.java @@ -20,15 +20,15 @@ package net.momirealms.customcrops.listener; import de.tr7zw.changeme.nbtapi.NBTCompound; import de.tr7zw.changeme.nbtapi.NBTItem; import dev.lone.itemsadder.api.CustomFurniture; +import dev.lone.itemsadder.api.Events.FurnitureBreakEvent; +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.CustomCrops; import net.momirealms.customcrops.datamanager.SprinklerManager; -import net.momirealms.customcrops.utils.AdventureManager; -import net.momirealms.customcrops.utils.HoloUtil; -import net.momirealms.customcrops.utils.Sprinkler; -import net.momirealms.customcrops.utils.WateringCan; +import net.momirealms.customcrops.utils.*; +import org.apache.commons.lang.StringUtils; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.entity.ArmorStand; @@ -54,106 +54,102 @@ public class InteractEntity implements Listener { } @EventHandler - public void onEntityInteract(PlayerInteractAtEntityEvent event){ - Entity entity = event.getRightClicked(); - if(entity instanceof ArmorStand armorStand){ - if(CustomFurniture.byAlreadySpawned(armorStand) == null) return; - Sprinkler config = ConfigReader.SPRINKLERS.get(CustomFurniture.byAlreadySpawned(armorStand).getId()); - if(config != null){ - long time = System.currentTimeMillis(); - Player player = event.getPlayer(); - if (time - (coolDown.getOrDefault(player, time - 250)) < 250) { - return; - } - coolDown.put(player, time); - ItemStack itemStack = player.getInventory().getItemInMainHand(); - Location location = armorStand.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(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 + ".water"; - currentWater = plugin.getSprinklerManager().data.getInt(path); - currentWater += ConfigReader.Config.sprinklerRefill; - if (currentWater > maxWater){ - currentWater = maxWater; - } - plugin.getSprinklerManager().data.set(path, currentWater); + public void onEntityInteract(FurnitureInteractEvent event){ + Sprinkler config = ConfigReader.SPRINKLERS.get(StringUtils.split(event.getNamespacedID(),":")[1]); + if(config != null){ + long time = System.currentTimeMillis(); + Player player = event.getPlayer(); + if (time - (coolDown.getOrDefault(player, time - 200)) < 200) { + return; + } + coolDown.put(player, time); + 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(SimpleLocation.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; } - AdventureManager.playerSound(player, ConfigReader.Sounds.addWaterToSprinklerSource, ConfigReader.Sounds.addWaterToSprinklerKey); + sprinkler.setWater(currentWater); + }else { + String path = world + "." + x / 16 + "," + z / 16 + "." + x + "," + location.getBlockY() + "," + z + ".water"; + currentWater = plugin.getSprinklerManager().data.getInt(path); + currentWater += ConfigReader.Config.sprinklerRefill; + if (currentWater > maxWater){ + currentWater = maxWater; + } + plugin.getSprinklerManager().data.set(path, currentWater); } - 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"); - Optional can = Optional.ofNullable(ConfigReader.CANS.get(id)); - if (can.isPresent()) { - WateringCan wateringCan = can.get(); - water--; - 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 + ".water"; - currentWater = plugin.getSprinklerManager().data.getInt(path); - currentWater++; - if (currentWater > maxWater){ - currentWater = maxWater; - } - plugin.getSprinklerManager().data.set(path, currentWater); + 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"); + Optional can = Optional.ofNullable(ConfigReader.CANS.get(id)); + if (can.isPresent()) { + WateringCan wateringCan = can.get(); + water--; + 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; } - if (ConfigReader.Message.hasWaterInfo){ - String string = ConfigReader.Message.waterLeft + ConfigReader.Message.waterFull.repeat(water) + - ConfigReader.Message.waterEmpty.repeat(wateringCan.getMax() - water) + ConfigReader.Message.waterRight; - AdventureManager.playerActionbar(player, string.replace("{max_water}", String.valueOf(wateringCan.getMax())).replace("{water}", String.valueOf(water))); + sprinkler.setWater(currentWater); + }else { + String path = world + "." + x / 16 + "," + z / 16 + "." + x + "," + location.getBlockY() + "," + z + ".water"; + currentWater = plugin.getSprinklerManager().data.getInt(path); + currentWater++; + if (currentWater > maxWater){ + currentWater = maxWater; } - 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 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()); + plugin.getSprinklerManager().data.set(path, currentWater); } + if (ConfigReader.Message.hasWaterInfo){ + String string = ConfigReader.Message.waterLeft + ConfigReader.Message.waterFull.repeat(water) + + ConfigReader.Message.waterEmpty.repeat(wateringCan.getMax() - water) + ConfigReader.Message.waterRight; + AdventureManager.playerActionbar(player, string.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 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 = getCurrentWater(location, world, x, z, sprinkler); } - } - else { + }else { currentWater = getCurrentWater(location, world, x, z, sprinkler); } } - if (ConfigReader.Message.hasSprinklerInfo){ - String string = ConfigReader.Message.sprinklerLeft + ConfigReader.Message.sprinklerFull.repeat(currentWater) + - ConfigReader.Message.sprinklerEmpty.repeat(maxWater - currentWater) + ConfigReader.Message.sprinklerRight; - if(HoloUtil.cache.get(location.add(0, ConfigReader.Message.sprinklerOffset,0)) == null) { - HoloUtil.showHolo(string.replace("{max_water}", String.valueOf(maxWater)).replace("{water}", String.valueOf(currentWater)), player, location, ConfigReader.Message.sprinklerTime); - } + else { + currentWater = getCurrentWater(location, world, x, z, sprinkler); + } + } + if (ConfigReader.Message.hasSprinklerInfo){ + String string = ConfigReader.Message.sprinklerLeft + ConfigReader.Message.sprinklerFull.repeat(currentWater) + + ConfigReader.Message.sprinklerEmpty.repeat(maxWater - currentWater) + ConfigReader.Message.sprinklerRight; + if(HoloUtil.cache.get(location.add(0, ConfigReader.Message.sprinklerOffset,0)) == null) { + HoloUtil.showHolo(string.replace("{max_water}", String.valueOf(maxWater)).replace("{water}", String.valueOf(currentWater)), player, location, ConfigReader.Message.sprinklerTime); } } } diff --git a/src/main/java/net/momirealms/customcrops/listener/JoinAndQuit.java b/src/main/java/net/momirealms/customcrops/listener/JoinAndQuit.java new file mode 100644 index 0000000..b1b1426 --- /dev/null +++ b/src/main/java/net/momirealms/customcrops/listener/JoinAndQuit.java @@ -0,0 +1,23 @@ +package net.momirealms.customcrops.listener; + +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.HashSet; + +public class JoinAndQuit implements Listener { + + public static HashSet onlinePlayers = new HashSet<>(); + + @EventHandler + public void onJoin(PlayerJoinEvent event){ + onlinePlayers.add(event.getPlayer().getName()); + } + + @EventHandler + public void onQuit(PlayerQuitEvent event){ + onlinePlayers.remove(event.getPlayer().getName()); + } +} diff --git a/src/main/java/net/momirealms/customcrops/listener/RightClick.java b/src/main/java/net/momirealms/customcrops/listener/RightClick.java index e79f9e3..aab510b 100644 --- a/src/main/java/net/momirealms/customcrops/listener/RightClick.java +++ b/src/main/java/net/momirealms/customcrops/listener/RightClick.java @@ -138,7 +138,7 @@ public class RightClick implements Listener { return; } itemStack.setAmount(itemStack.getAmount() - 1); - CropManager.Cache.put(location, cropName); + CropManager.Cache.put(location, player.getName()); CustomBlock.place((nbtCompound.getString("namespace") + ":" + cropName + "_stage_1"), location); AdventureManager.playerSound(player, ConfigReader.Sounds.plantSeedSource, ConfigReader.Sounds.plantSeedKey); return; @@ -279,8 +279,11 @@ public class RightClick implements Listener { return; } Sprinkler sprinklerData = new Sprinkler(sprinkler.getRange(), 0); + sprinklerData.setPlayer(player.getName()); itemStack.setAmount(itemStack.getAmount() - 1); - SprinklerManager.Cache.put(location.add(0,1,0), sprinklerData); + SimpleLocation simpleLocation = SimpleLocation.fromLocation(location.add(0,1,0)); + SprinklerManager.Cache.put(simpleLocation, sprinklerData); + SprinklerManager.RemoveCache.remove(simpleLocation); IAFurniture.placeFurniture(sprinkler.getNamespacedID_2(),location); AdventureManager.playerSound(player, ConfigReader.Sounds.placeSprinklerSource, ConfigReader.Sounds.placeSprinklerKey); return; @@ -420,7 +423,7 @@ public class RightClick implements Listener { AdventureManager.playerSound(player, ConfigReader.Sounds.harvestSource, ConfigReader.Sounds.harvestKey); if(cropInstance.getReturnStage() != null){ CustomBlock.place(cropInstance.getReturnStage(), location); - CropManager.Cache.put(location, cropNameList[0]); + CropManager.Cache.put(location, player.getName()); } } } diff --git a/src/main/java/net/momirealms/customcrops/timer/TimeCheck.java b/src/main/java/net/momirealms/customcrops/timer/TimeCheck.java index 1ee50be..1f50c54 100644 --- a/src/main/java/net/momirealms/customcrops/timer/TimeCheck.java +++ b/src/main/java/net/momirealms/customcrops/timer/TimeCheck.java @@ -49,10 +49,20 @@ public class TimeCheck extends BukkitRunnable { }, ConfigReader.Config.timeToGrow); }else { Bukkit.getScheduler().runTaskAsynchronously(CustomCrops.instance, () -> { - plugin.getCropManager().cropGrow(world.getName()); + switch (ConfigReader.Config.growMode){ + case 1 -> plugin.getCropManager().growModeOne(world.getName()); + case 2 -> plugin.getCropManager().growModeTwo(world.getName()); + case 3 -> plugin.getCropManager().growModeThree(world.getName()); + case 4 -> plugin.getCropManager().growModeFour(world.getName()); + } }); Bukkit.getScheduler().runTaskLaterAsynchronously(CustomCrops.instance, ()->{ - plugin.getSprinklerManager().sprinklerWork(world.getName()); + switch (ConfigReader.Config.growMode){ + case 1 -> plugin.getSprinklerManager().workModeOne(world.getName()); + case 2 -> plugin.getSprinklerManager().workModeTwo(world.getName()); + case 3 -> plugin.getSprinklerManager().workModeThree(world.getName()); + case 4 -> plugin.getSprinklerManager().workModeFour(world.getName()); + } }, ConfigReader.Config.timeToGrow); } } diff --git a/src/main/java/net/momirealms/customcrops/utils/IAFurniture.java b/src/main/java/net/momirealms/customcrops/utils/IAFurniture.java index 0f290e2..f8e32f5 100644 --- a/src/main/java/net/momirealms/customcrops/utils/IAFurniture.java +++ b/src/main/java/net/momirealms/customcrops/utils/IAFurniture.java @@ -37,6 +37,7 @@ public class IAFurniture { /** * 判断指定位置的盔甲架是不是洒水器 + * 仅限加载中的区块 * @param location 位置 * @param world 世界 * @return 是/否 diff --git a/src/main/java/net/momirealms/customcrops/utils/Sprinkler.java b/src/main/java/net/momirealms/customcrops/utils/Sprinkler.java index 81a3900..c36e1be 100644 --- a/src/main/java/net/momirealms/customcrops/utils/Sprinkler.java +++ b/src/main/java/net/momirealms/customcrops/utils/Sprinkler.java @@ -21,6 +21,7 @@ public class Sprinkler { private int water; private int range; + private String player; private String namespacedID_1; private String namespacedID_2; @@ -33,9 +34,11 @@ public class Sprinkler { public String getNamespacedID_1() {return namespacedID_1;} public String getNamespacedID_2() {return namespacedID_2;} public int getRange() {return range;} + public String getPlayer() {return player;} public void setRange(int range) {this.range = range;} public void setNamespacedID_2(String namespacedID_2) {this.namespacedID_2 = namespacedID_2;} public void setNamespacedID_1(String namespacedID_1) {this.namespacedID_1 = namespacedID_1;} public void setWater(int water) {this.water = water;} + public void setPlayer(String player) {this.player = player;} } diff --git a/src/main/resources/basic.yml b/src/main/resources/basic.yml index f6c6a27..f0ae695 100644 --- a/src/main/resources/basic.yml +++ b/src/main/resources/basic.yml @@ -1,3 +1,4 @@ +#=============================================================# #ItemsAdder items namespacedID basic: pot: customcrops:pot @@ -5,7 +6,7 @@ basic: greenhouse-glass: customcrops:greenhouse_glass dead-crop: customcrops:crop_stage_death soil-detector: customcrops:soil_detector - +#=============================================================# water-can: watering_can_1: item: customcrops:watering_can_1 @@ -29,7 +30,7 @@ water-can: max: 6 width: 3 length: 5 - +#=============================================================# lore: #Should lore be changed when using watering-can watering-can: @@ -45,7 +46,7 @@ lore: full: '뀁뀃' empty: '뀁뀄' right: '뀁뀅' - +#=============================================================# sprinkler: sprinkler_1: range: 1 @@ -58,3 +59,4 @@ sprinkler: max-water: 7 3Ditem: customcrops:sprinkler_2 2Ditem: customcrops:sprinkler_2_item +#=============================================================# \ No newline at end of file diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index a722f45..23e5eac 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -1,7 +1,8 @@ config: + #=============================================================# #english spanish chinese lang: english - + #=============================================================# integration: #integration to prevent other players' grief Residence: false @@ -16,31 +17,46 @@ config: AureliumSkills: false mcMMO: false MMOCore: false - + #=============================================================# + #Mode 1: + # Crops in loaded chunks will grow + #Mode 2: + # Online players' crops will grow + #Mode 3: + # Mode 1 + Mode 2 + #Mode 4: + # No support in this mode! + # All the crops will grow (May cause lag) + grow-mode: 3 #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-to-grow: 60 #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: false + #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. + all-world-grow: false + #=============================================================# quality: #If disabled, you need to configurate the loot in ItemsAdder config enable: true #Default ratio default-ratio: 17/2/1 - - #Async Time Check (requires restart) - #Crops might not grow when using async. - #It is not really necessary to be Async - async-time-check: false - + #=============================================================# #Water Amount to refill when using water bucket sprinkler-refill: 2 #Water Amount to refill with a sigle click to water block @@ -49,11 +65,13 @@ config: water-can-add-water-to-sprinkler: true #Should particles be displayed when using watering can? water-particles: true - - #Worlds where crops would grow - whitelist-worlds: - - world - + #=============================================================# + #Will bone meal accelerate the growth of crop + bone-meal: + enable: true + chance: 0.5 + success-particle: VILLAGER_HAPPY + #=============================================================# #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 @@ -61,38 +79,15 @@ config: enable: true crop: 64 sprinkler: 8 - - #Test performance - log-time-consume: false - - #Defaultly crops will only grow in loaded chunks. - #If you want a mechanic similar to OriginRealms just DISABLE SEASON and REPEATED HARVESTING. - #In this way crops data will be removed from file when it comes to its final stage. - #In other words, plugin will only record the crops still on growing. - #NEVER SET "only-grow-in-loaded-chunks" FALSE IF YOU ARE USING THE FEATURES MENTIONED ABOVE. - #Otherwise it would be laggy because too many data in cache. - only-grow-in-loaded-chunks: true - - #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. - all-world-grow: false - + #=============================================================# #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 harvest-with-empty-hand: true - #Should player be prevented from planting if wrong season prevent-plant-if-wrong-season: true #Should notify player of the wrong season? should-notify-if-wrong-season: true - - #Will bone meal accelerate the growth of crop - bone-meal: - enable: true - chance: 0.5 - success-particle: VILLAGER_HAPPY \ No newline at end of file + #=============================================================# \ No newline at end of file diff --git a/src/main/resources/fertilizer.yml b/src/main/resources/fertilizer.yml index 1c9ca82..d482620 100644 --- a/src/main/resources/fertilizer.yml +++ b/src/main/resources/fertilizer.yml @@ -27,7 +27,7 @@ speed: times: 14 item: customcrops:speed_3 before-plant: true - +#=============================================================# #Pot have a small chance to retain its water after crops grow retaining: retaining_1: @@ -50,7 +50,7 @@ retaining: times: 28 item: customcrops:retaining_3 before-plant: false - +#=============================================================# #When haveresting, players have a higher chance to get high quality crops. quality: quality_1: @@ -72,4 +72,5 @@ quality: times: 28 chance: 2/2/1 item: customcrops:quality_3 - before-plant: true \ No newline at end of file + before-plant: true +#=============================================================# \ No newline at end of file diff --git a/src/main/resources/season.yml b/src/main/resources/season.yml index 2cc89ba..41c1d90 100644 --- a/src/main/resources/season.yml +++ b/src/main/resources/season.yml @@ -1,5 +1,6 @@ season: + #require a restart to apply enable: true auto-season-change: diff --git a/src/main/resources/zh-cn/config.yml b/src/main/resources/zh-cn/config.yml index bc3fad9..1d2e12b 100644 --- a/src/main/resources/zh-cn/config.yml +++ b/src/main/resources/zh-cn/config.yml @@ -61,15 +61,16 @@ config: #记录生长判断和洒水所需的时间(测试性能用) log-time-consume: false - #是否只有加载中的区块农作物才会生长 - #如果你不使用季节、可重复收获特性 - #插件data只会记录正在生长中某个阶段的农作物数据 - #生长到最后一阶段农作物生长数据就会清除 - #那么可以尝试设置此值为false来让数据内全部农作物生长 - #如果你使用上述特性中的任意一个,请不要设置为false - #否则农作物生长到最后一阶段不会从数据中清除,过大的数据量 - #可能会导致服务器严重卡顿 - only-grow-in-loaded-chunks: true + #Mode 1: + # 加载中区块的农作物生长 + #Mode 2: + # 在线玩家的农作物生长 + #Mode 3: + # Mode 1 + Mode 2 + #Mode 4: + # 所有农作物生长 + # 可能会造成卡顿!不建议使用此模式 + grow-mode: 3 #是否所有加载中的世界都要进行生长判断 #本选项适用于使用玩家独立世界的服务器