From aa8be827d78159843d6860ee04ff376f79aedd2a Mon Sep 17 00:00:00 2001 From: Xiao-MoMi <70987828+Xiao-MoMi@users.noreply.github.com> Date: Sun, 21 Aug 2022 22:25:02 +0800 Subject: [PATCH] 1.6.0 --- build.gradle | 2 +- .../momirealms/customcrops/ConfigReader.java | 38 +- .../momirealms/customcrops/CustomCrops.java | 40 +- .../customcrops/commands/Completer.java | 5 +- .../customcrops/commands/Executor.java | 73 ++- .../customcrops/datamanager/CropManager.java | 615 +++++++++++++----- .../datamanager/SeasonManager.java | 7 +- .../datamanager/SprinklerManager.java | 93 +-- .../customcrops/helper/LibraryLoader.java | 2 - .../momirealms/customcrops/helper/Log.java | 13 +- .../customcrops/helper/MavenLibraries.java | 6 +- .../customcrops/helper/MavenLibrary.java | 12 +- .../customcrops/helper/NonnullByDefault.java | 46 -- .../customcrops/helper/Repository.java | 3 - .../helper/URLClassLoaderAccess.java | 10 +- .../customcrops/hook/RealisticSeason.java | 17 + .../customcrops/integrations/skill/mcMMO.java | 2 +- .../limits/SprinklersPerChunk.java | 4 +- .../customcrops/listener/JoinAndQuit.java | 4 + .../listener/itemframe/BreakBlockI.java | 74 +++ .../listener/itemframe/BreakFurnitureI.java | 83 +++ .../itemframe/InteractFurnitureI.java | 293 +++++++++ .../listener/itemframe/RightClickI.java | 260 ++++++++ .../BreakBlockT.java} | 48 +- .../BreakFurnitureT.java} | 12 +- .../InteractFurnitureT.java} | 117 ++-- .../RightClickT.java} | 192 ++---- .../momirealms/customcrops/objects/Crop.java | 6 + .../customcrops/objects/SimpleLocation.java | 11 - .../customcrops/utils/DropUtil.java | 31 + .../customcrops/utils/FurnitureUtil.java | 97 +++ .../customcrops/utils/IAFurnitureUtil.java | 55 -- .../momirealms/customcrops/utils/LocUtil.java | 15 + .../momirealms/customcrops/utils/PotUtil.java | 111 ++++ src/main/resources/config.yml | 130 ++-- src/main/resources/crops.yml | 18 +- src/main/resources/plugin.yml | 2 +- src/main/resources/zh-cn/config.yml | 185 ++++-- src/main/resources/zh-cn/crops.yml | 63 +- src/main/resources/zh-cn/messages.yml | 60 -- 40 files changed, 1991 insertions(+), 864 deletions(-) delete mode 100644 src/main/java/net/momirealms/customcrops/helper/NonnullByDefault.java create mode 100644 src/main/java/net/momirealms/customcrops/listener/itemframe/BreakBlockI.java create mode 100644 src/main/java/net/momirealms/customcrops/listener/itemframe/BreakFurnitureI.java create mode 100644 src/main/java/net/momirealms/customcrops/listener/itemframe/InteractFurnitureI.java create mode 100644 src/main/java/net/momirealms/customcrops/listener/itemframe/RightClickI.java rename src/main/java/net/momirealms/customcrops/listener/{BreakBlock.java => tripwire/BreakBlockT.java} (85%) rename src/main/java/net/momirealms/customcrops/listener/{BreakFurniture.java => tripwire/BreakFurnitureT.java} (57%) rename src/main/java/net/momirealms/customcrops/listener/{InteractEntity.java => tripwire/InteractFurnitureT.java} (54%) rename src/main/java/net/momirealms/customcrops/listener/{RightClick.java => tripwire/RightClickT.java} (77%) create mode 100644 src/main/java/net/momirealms/customcrops/utils/DropUtil.java create mode 100644 src/main/java/net/momirealms/customcrops/utils/FurnitureUtil.java delete mode 100644 src/main/java/net/momirealms/customcrops/utils/IAFurnitureUtil.java create mode 100644 src/main/java/net/momirealms/customcrops/utils/LocUtil.java create mode 100644 src/main/java/net/momirealms/customcrops/utils/PotUtil.java delete mode 100644 src/main/resources/zh-cn/messages.yml diff --git a/build.gradle b/build.gradle index f5a0927..52c861f 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ plugins { group = 'net.momirealms' -version = '1.5.26.4' +version = '1.6.0' repositories { mavenCentral() diff --git a/src/main/java/net/momirealms/customcrops/ConfigReader.java b/src/main/java/net/momirealms/customcrops/ConfigReader.java index ced5c11..a98e036 100644 --- a/src/main/java/net/momirealms/customcrops/ConfigReader.java +++ b/src/main/java/net/momirealms/customcrops/ConfigReader.java @@ -75,10 +75,8 @@ public class ConfigReader { public static List 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")) - cropInstance.setGiant(config.getString("crops." + key + ".gigantic.block")); - cropInstance.setGiantChance(config.getDouble("crops." + key + ".gigantic.chance")); + if (config.contains("crops." + key + ".gigantic.block")){ + cropInstance.setGiant(config.getString("crops." + key + ".gigantic.block")); + 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){ diff --git a/src/main/java/net/momirealms/customcrops/CustomCrops.java b/src/main/java/net/momirealms/customcrops/CustomCrops.java index ceb6a74..b9e79e8 100644 --- a/src/main/java/net/momirealms/customcrops/CustomCrops.java +++ b/src/main/java/net/momirealms/customcrops/CustomCrops.java @@ -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("[CustomCrops] 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(); - checkIAConfig(); - if (!Objects.equals(ConfigReader.Config.version, "3")){ - ConfigUtil.update(); + if (ConfigReader.Config.cropMode.equalsIgnoreCase("item_frame")){ + this.cropManager = new CropManager(true); + AdventureManager.consoleMessage("[CustomCrops] 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("[CustomCrops] 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(); } + this.cropManager.loadData(); AdventureManager.consoleMessage("[CustomCrops] Plugin Enabled!"); } diff --git a/src/main/java/net/momirealms/customcrops/commands/Completer.java b/src/main/java/net/momirealms/customcrops/commands/Completer.java index 4351300..5efd685 100644 --- a/src/main/java/net/momirealms/customcrops/commands/Completer.java +++ b/src/main/java/net/momirealms/customcrops/commands/Completer.java @@ -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 onTabComplete(CommandSender sender, Command command, String alias, String[] args) { + public @Nullable List onTabComplete(CommandSender sender, @NotNull Command command, @NotNull String alias, String[] args) { if (!(sender.isOp() || sender.hasPermission("customcrops.admin"))){ return null; } diff --git a/src/main/java/net/momirealms/customcrops/commands/Executor.java b/src/main/java/net/momirealms/customcrops/commands/Executor.java index 0349bb9..a7a9cd6 100644 --- a/src/main/java/net/momirealms/customcrops/commands/Executor.java +++ b/src/main/java/net/momirealms/customcrops/commands/Executor.java @@ -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,37 +111,39 @@ public class Executor implements CommandExecutor { lackArgs(sender); return true; } - switch (args[1]){ - case "all" -> { - plugin.getSprinklerManager().updateData(); - plugin.getSprinklerManager().saveData(); - if (ConfigReader.Season.enable && !ConfigReader.Season.seasonChange){ - plugin.getSeasonManager().saveData(); + Bukkit.getScheduler().runTaskAsynchronously(CustomCrops.plugin, ()->{ + switch (args[1]){ + case "all" -> { + plugin.getSprinklerManager().updateData(); + plugin.getSprinklerManager().saveData(); + if (ConfigReader.Season.enable && !ConfigReader.Season.seasonChange){ + plugin.getSeasonManager().saveData(); + } + plugin.getCropManager().updateData(); + plugin.getCropManager().saveData(); + plugin.getPotManager().saveData(); + forceSave(sender); } - plugin.getCropManager().updateData(); - plugin.getCropManager().saveData(); - plugin.getPotManager().saveData(); - forceSave(sender); - } - case "crop" -> { - plugin.getCropManager().updateData(); - plugin.getCropManager().saveData(); - forceSave(sender); - } - case "pot" -> { - plugin.getPotManager().saveData(); - forceSave(sender); - } - case "season" -> { - plugin.getSeasonManager().saveData(); - forceSave(sender); - } - case "sprinkler" -> { - plugin.getSprinklerManager().updateData(); - plugin.getSprinklerManager().saveData(); - forceSave(sender); - } - } + case "crop" -> { + plugin.getCropManager().updateData(); + plugin.getCropManager().saveData(); + forceSave(sender); + } + case "pot" -> { + plugin.getPotManager().saveData(); + forceSave(sender); + } + case "season" -> { + plugin.getSeasonManager().saveData(); + forceSave(sender); + } + case "sprinkler" -> { + plugin.getSprinklerManager().updateData(); + plugin.getSprinklerManager().saveData(); + forceSave(sender); + } + } + }); } case "backup" -> { FileUtil.backUpData(); diff --git a/src/main/java/net/momirealms/customcrops/datamanager/CropManager.java b/src/main/java/net/momirealms/customcrops/datamanager/CropManager.java index c034c83..44d0de3 100644 --- a/src/main/java/net/momirealms/customcrops/datamanager/CropManager.java +++ b/src/main/java/net/momirealms/customcrops/datamanager/CropManager.java @@ -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 Cache = new ConcurrentHashMap<>(); + public static ConcurrentHashMap Cache = new ConcurrentHashMap<>(); + public static HashSet 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 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); - 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); - } - }); - } - }); + 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 players = new HashSet<>(JoinAndQuit.onlinePlayers); + if(!ConfigReader.Config.allWorld) updateData(); + if(!ConfigReader.Config.allWorld) saveData(); HashSet players = getPlayers(); 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); - } + 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,48 +233,72 @@ 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 players = new HashSet<>(JoinAndQuit.onlinePlayers); + if(!ConfigReader.Config.allWorld) updateData(); + if(!ConfigReader.Config.allWorld) saveData(); HashSet players = getPlayers(); 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); - } - }); - } - }); + 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 + "." + 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 ->{ + 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); - 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); - } + if (!isEntity){ + 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.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("[CustomCrops] Unknown fertilizer, Auto removed!"); - 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()){ + + if (cropInstance.isBlock()){ + bukkitScheduler.runTask(CustomCrops.plugin, () ->{ + CustomBlock.remove(seedLocation); + CustomBlock.place(cropInstance.getGiant(), seedLocation); + CustomBlock.remove(potLocation); + CustomBlock.place(ConfigReader.Basic.pot, potLocation); + }); + }else { + bukkitScheduler.runTask(CustomCrops.plugin, () ->{ + //加载区块哦亲 + CustomBlock.remove(seedLocation); + CustomFurniture.spawn(cropInstance.getGiant(), seedLocation.getBlock()); + CustomBlock.remove(potLocation); + CustomBlock.place(ConfigReader.Basic.pot, potLocation); + }); + } //成功巨大化,移除数据 - bukkitScheduler.runTaskLater(CustomCrops.plugin, () ->{ - CustomBlock.remove(seedLocation); - CustomBlock.place(cropInstance.getGiant(), seedLocation); - CustomBlock.remove(potLocation); - CustomBlock.place(ConfigReader.Basic.pot, potLocation); - }, random); 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("[CustomCrops] Unknown fertilizer, Auto removed!"); + 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 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 getPlayers(){ diff --git a/src/main/java/net/momirealms/customcrops/datamanager/SeasonManager.java b/src/main/java/net/momirealms/customcrops/datamanager/SeasonManager.java index 2231c36..55eacb6 100644 --- a/src/main/java/net/momirealms/customcrops/datamanager/SeasonManager.java +++ b/src/main/java/net/momirealms/customcrops/datamanager/SeasonManager.java @@ -82,8 +82,11 @@ public class SeasonManager{ */ public void getSeason(World world) { if (ConfigReader.Config.realisticSeason){ - SEASON.put(world.getName(), RealisticSeason.getSeason(world)); - }else { + Bukkit.getScheduler().runTaskLater(CustomCrops.plugin, ()->{ + SEASON.put(world.getName(), RealisticSeason.getSeason(world)); + },60); + } + else { int season = (int) ((world.getFullTime() / 24000L) % (ConfigReader.Season.duration * 4)) / ConfigReader.Season.duration; switch (season) { case 0 -> SEASON.put(world.getName(), "spring"); diff --git a/src/main/java/net/momirealms/customcrops/datamanager/SprinklerManager.java b/src/main/java/net/momirealms/customcrops/datamanager/SprinklerManager.java index 0d36262..d329043 100644 --- a/src/main/java/net/momirealms/customcrops/datamanager/SprinklerManager.java +++ b/src/main/java/net/momirealms/customcrops/datamanager/SprinklerManager.java @@ -39,7 +39,7 @@ import java.util.concurrent.ConcurrentHashMap; public class SprinklerManager { - public YamlConfiguration data; + public static YamlConfiguration data; public static ConcurrentHashMap Cache = new ConcurrentHashMap<>(); public static HashSet RemoveCache = new HashSet<>(); private final BukkitScheduler bukkitScheduler; @@ -62,7 +62,7 @@ public class SprinklerManager { AdventureManager.consoleMessage("[CustomCrops] 洒水器数据文件生成失败!"); } } - 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 players = new HashSet<>(JoinAndQuit.onlinePlayers); + if(!ConfigReader.Config.allWorld) updateData(); + if(!ConfigReader.Config.allWorld) saveData(); HashSet 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 players = new HashSet<>(JoinAndQuit.onlinePlayers); + if(!ConfigReader.Config.allWorld) updateData(); + if(!ConfigReader.Config.allWorld) saveData(); HashSet 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; + } } diff --git a/src/main/java/net/momirealms/customcrops/helper/LibraryLoader.java b/src/main/java/net/momirealms/customcrops/helper/LibraryLoader.java index 9ee09e9..298bab1 100644 --- a/src/main/java/net/momirealms/customcrops/helper/LibraryLoader.java +++ b/src/main/java/net/momirealms/customcrops/helper/LibraryLoader.java @@ -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; diff --git a/src/main/java/net/momirealms/customcrops/helper/Log.java b/src/main/java/net/momirealms/customcrops/helper/Log.java index cd727cd..d4b6600 100644 --- a/src/main/java/net/momirealms/customcrops/helper/Log.java +++ b/src/main/java/net/momirealms/customcrops/helper/Log.java @@ -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); } diff --git a/src/main/java/net/momirealms/customcrops/helper/MavenLibraries.java b/src/main/java/net/momirealms/customcrops/helper/MavenLibraries.java index 4a692b3..8f13ff0 100644 --- a/src/main/java/net/momirealms/customcrops/helper/MavenLibraries.java +++ b/src/main/java/net/momirealms/customcrops/helper/MavenLibraries.java @@ -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 {}; } diff --git a/src/main/java/net/momirealms/customcrops/helper/MavenLibrary.java b/src/main/java/net/momirealms/customcrops/helper/MavenLibrary.java index 6dc2037..40c4884 100644 --- a/src/main/java/net/momirealms/customcrops/helper/MavenLibrary.java +++ b/src/main/java/net/momirealms/customcrops/helper/MavenLibrary.java @@ -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"); } diff --git a/src/main/java/net/momirealms/customcrops/helper/NonnullByDefault.java b/src/main/java/net/momirealms/customcrops/helper/NonnullByDefault.java deleted file mode 100644 index d1de9ac..0000000 --- a/src/main/java/net/momirealms/customcrops/helper/NonnullByDefault.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * This file is part of helper, licensed under the MIT License. - * - * Copyright (c) lucko (Luck) - * 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 { - -} diff --git a/src/main/java/net/momirealms/customcrops/helper/Repository.java b/src/main/java/net/momirealms/customcrops/helper/Repository.java index cadf89b..b38215f 100644 --- a/src/main/java/net/momirealms/customcrops/helper/Repository.java +++ b/src/main/java/net/momirealms/customcrops/helper/Repository.java @@ -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(); } diff --git a/src/main/java/net/momirealms/customcrops/helper/URLClassLoaderAccess.java b/src/main/java/net/momirealms/customcrops/helper/URLClassLoaderAccess.java index 2adc36b..e8ac038 100644 --- a/src/main/java/net/momirealms/customcrops/helper/URLClassLoaderAccess.java +++ b/src/main/java/net/momirealms/customcrops/helper/URLClassLoaderAccess.java @@ -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(); } } diff --git a/src/main/java/net/momirealms/customcrops/hook/RealisticSeason.java b/src/main/java/net/momirealms/customcrops/hook/RealisticSeason.java index 06df7b2..134b9b2 100644 --- a/src/main/java/net/momirealms/customcrops/hook/RealisticSeason.java +++ b/src/main/java/net/momirealms/customcrops/hook/RealisticSeason.java @@ -1,3 +1,20 @@ +/* + * Copyright (C) <2022> + * + * 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 . + */ + package net.momirealms.customcrops.hook; import me.casperge.realisticseasons.api.SeasonsAPI; diff --git a/src/main/java/net/momirealms/customcrops/integrations/skill/mcMMO.java b/src/main/java/net/momirealms/customcrops/integrations/skill/mcMMO.java index 9a4de6c..53f23ed 100644 --- a/src/main/java/net/momirealms/customcrops/integrations/skill/mcMMO.java +++ b/src/main/java/net/momirealms/customcrops/integrations/skill/mcMMO.java @@ -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"); } } \ No newline at end of file diff --git a/src/main/java/net/momirealms/customcrops/limits/SprinklersPerChunk.java b/src/main/java/net/momirealms/customcrops/limits/SprinklersPerChunk.java index ef04cf9..cbf6e61 100644 --- a/src/main/java/net/momirealms/customcrops/limits/SprinklersPerChunk.java +++ b/src/main/java/net/momirealms/customcrops/limits/SprinklersPerChunk.java @@ -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; } diff --git a/src/main/java/net/momirealms/customcrops/listener/JoinAndQuit.java b/src/main/java/net/momirealms/customcrops/listener/JoinAndQuit.java index 17ec447..e3a94ff 100644 --- a/src/main/java/net/momirealms/customcrops/listener/JoinAndQuit.java +++ b/src/main/java/net/momirealms/customcrops/listener/JoinAndQuit.java @@ -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 onlinePlayers = new HashSet<>(); + public static HashMap 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()); } } \ No newline at end of file diff --git a/src/main/java/net/momirealms/customcrops/listener/itemframe/BreakBlockI.java b/src/main/java/net/momirealms/customcrops/listener/itemframe/BreakBlockI.java new file mode 100644 index 0000000..48792e9 --- /dev/null +++ b/src/main/java/net/momirealms/customcrops/listener/itemframe/BreakBlockI.java @@ -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); + } + } + } + } + } + } +} diff --git a/src/main/java/net/momirealms/customcrops/listener/itemframe/BreakFurnitureI.java b/src/main/java/net/momirealms/customcrops/listener/itemframe/BreakFurnitureI.java new file mode 100644 index 0000000..19f6cc9 --- /dev/null +++ b/src/main/java/net/momirealms/customcrops/listener/itemframe/BreakFurnitureI.java @@ -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 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); + } + } + } +} diff --git a/src/main/java/net/momirealms/customcrops/listener/itemframe/InteractFurnitureI.java b/src/main/java/net/momirealms/customcrops/listener/itemframe/InteractFurnitureI.java new file mode 100644 index 0000000..597e916 --- /dev/null +++ b/src/main/java/net/momirealms/customcrops/listener/itemframe/InteractFurnitureI.java @@ -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 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 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 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()); + } + } + } +} diff --git a/src/main/java/net/momirealms/customcrops/listener/itemframe/RightClickI.java b/src/main/java/net/momirealms/customcrops/listener/itemframe/RightClickI.java new file mode 100644 index 0000000..2106bdf --- /dev/null +++ b/src/main/java/net/momirealms/customcrops/listener/itemframe/RightClickI.java @@ -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 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 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 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); + } + } + } + } + } + } + } +} diff --git a/src/main/java/net/momirealms/customcrops/listener/BreakBlock.java b/src/main/java/net/momirealms/customcrops/listener/tripwire/BreakBlockT.java similarity index 85% rename from src/main/java/net/momirealms/customcrops/listener/BreakBlock.java rename to src/main/java/net/momirealms/customcrops/listener/tripwire/BreakBlockT.java index 439976a..b411a76 100644 --- a/src/main/java/net/momirealms/customcrops/listener/BreakBlock.java +++ b/src/main/java/net/momirealms/customcrops/listener/tripwire/BreakBlockT.java @@ -15,19 +15,22 @@ * along with this program. If not, see . */ -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 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()); - } - } - } } diff --git a/src/main/java/net/momirealms/customcrops/listener/BreakFurniture.java b/src/main/java/net/momirealms/customcrops/listener/tripwire/BreakFurnitureT.java similarity index 57% rename from src/main/java/net/momirealms/customcrops/listener/BreakFurniture.java rename to src/main/java/net/momirealms/customcrops/listener/tripwire/BreakFurnitureT.java index efa2cc4..57887ca 100644 --- a/src/main/java/net/momirealms/customcrops/listener/BreakFurniture.java +++ b/src/main/java/net/momirealms/customcrops/listener/tripwire/BreakFurnitureT.java @@ -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); - SprinklerManager.RemoveCache.add(simpleLocation); + SimpleLocation simpleLocation = LocUtil.fromLocation(event.getBukkitEntity().getLocation()); + if(SprinklerManager.Cache.remove(simpleLocation) == null){ + 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/tripwire/InteractFurnitureT.java similarity index 54% rename from src/main/java/net/momirealms/customcrops/listener/InteractEntity.java rename to src/main/java/net/momirealms/customcrops/listener/tripwire/InteractFurnitureT.java index 41907dd..3e55301 100644 --- a/src/main/java/net/momirealms/customcrops/listener/InteractEntity.java +++ b/src/main/java/net/momirealms/customcrops/listener/tripwire/InteractFurnitureT.java @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -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 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) { + 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,40 +96,44 @@ 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()); } - 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 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); + } + 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 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 currentWater = SprinklerManager.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; - } } diff --git a/src/main/java/net/momirealms/customcrops/listener/RightClick.java b/src/main/java/net/momirealms/customcrops/listener/tripwire/RightClickT.java similarity index 77% rename from src/main/java/net/momirealms/customcrops/listener/RightClick.java rename to src/main/java/net/momirealms/customcrops/listener/tripwire/RightClickT.java index 031dd24..ac10e46 100644 --- a/src/main/java/net/momirealms/customcrops/listener/RightClick.java +++ b/src/main/java/net/momirealms/customcrops/listener/tripwire/RightClickT.java @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -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 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); - AdventureManager.playerSound(player, ConfigReader.Sounds.waterPotSource, ConfigReader.Sounds.waterPotKey); - waterPot(wateringCan.getWidth(), wateringCan.getLength(), block.getLocation(), player.getLocation().getYaw()); + 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 - 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 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); - AdventureManager.playerSound(player, ConfigReader.Sounds.waterPotSource, ConfigReader.Sounds.waterPotKey); - waterPot(wateringCan.getWidth(), wateringCan.getLength(), block.getLocation().subtract(0,1,0), player.getLocation().getYaw()); + if (water > 0) { + nbtItem.setInteger("WaterAmount", --water); + AdventureManager.playerSound(player, ConfigReader.Sounds.waterPotSource, ConfigReader.Sounds.waterPotKey); + 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 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 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()); } } } diff --git a/src/main/java/net/momirealms/customcrops/objects/Crop.java b/src/main/java/net/momirealms/customcrops/objects/Crop.java index 5ed2192..5a5f712 100644 --- a/src/main/java/net/momirealms/customcrops/objects/Crop.java +++ b/src/main/java/net/momirealms/customcrops/objects/Crop.java @@ -27,6 +27,7 @@ public class Crop { private String giant; private List requirements; private List seasons; + private List otherLoots; private String returnStage; private final int min; private final int max; @@ -37,6 +38,7 @@ public class Crop { private boolean dropIALoot; private List 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 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 otherLoots) {this.otherLoots = otherLoots;} } diff --git a/src/main/java/net/momirealms/customcrops/objects/SimpleLocation.java b/src/main/java/net/momirealms/customcrops/objects/SimpleLocation.java index 8149918..08ef6c3 100644 --- a/src/main/java/net/momirealms/customcrops/objects/SimpleLocation.java +++ b/src/main/java/net/momirealms/customcrops/objects/SimpleLocation.java @@ -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;} diff --git a/src/main/java/net/momirealms/customcrops/utils/DropUtil.java b/src/main/java/net/momirealms/customcrops/utils/DropUtil.java new file mode 100644 index 0000000..dceea92 --- /dev/null +++ b/src/main/java/net/momirealms/customcrops/utils/DropUtil.java @@ -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()); + } + } + } + +} diff --git a/src/main/java/net/momirealms/customcrops/utils/FurnitureUtil.java b/src/main/java/net/momirealms/customcrops/utils/FurnitureUtil.java new file mode 100644 index 0000000..6641f3b --- /dev/null +++ b/src/main/java/net/momirealms/customcrops/utils/FurnitureUtil.java @@ -0,0 +1,97 @@ +/* + * Copyright (C) <2022> + * + * 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 . + */ + +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; + } +} \ No newline at end of file diff --git a/src/main/java/net/momirealms/customcrops/utils/IAFurnitureUtil.java b/src/main/java/net/momirealms/customcrops/utils/IAFurnitureUtil.java deleted file mode 100644 index 5d9d1e2..0000000 --- a/src/main/java/net/momirealms/customcrops/utils/IAFurnitureUtil.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) <2022> - * - * 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 . - */ - -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; - } -} \ No newline at end of file diff --git a/src/main/java/net/momirealms/customcrops/utils/LocUtil.java b/src/main/java/net/momirealms/customcrops/utils/LocUtil.java new file mode 100644 index 0000000..0fd609b --- /dev/null +++ b/src/main/java/net/momirealms/customcrops/utils/LocUtil.java @@ -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()); + } +} diff --git a/src/main/java/net/momirealms/customcrops/utils/PotUtil.java b/src/main/java/net/momirealms/customcrops/utils/PotUtil.java new file mode 100644 index 0000000..f3d0e69 --- /dev/null +++ b/src/main/java/net/momirealms/customcrops/utils/PotUtil.java @@ -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); + } +} diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 981ee9b..c663eab 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -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 \ No newline at end of file diff --git a/src/main/resources/crops.yml b/src/main/resources/crops.yml index 4ca5116..ac7f02a 100644 --- a/src/main/resources/crops.yml +++ b/src/main/resources/crops.yml @@ -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' diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 5ba13bd..46c32b1 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -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 diff --git a/src/main/resources/zh-cn/config.yml b/src/main/resources/zh-cn/config.yml index c3fdde7..7b0e73c 100644 --- a/src/main/resources/zh-cn/config.yml +++ b/src/main/resources/zh-cn/config.yml @@ -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 \ No newline at end of file + # 是否告知玩家这是错误的季节 + should-notify-if-wrong-season: true \ No newline at end of file diff --git a/src/main/resources/zh-cn/crops.yml b/src/main/resources/zh-cn/crops.yml index 59898a0..262de50 100644 --- a/src/main/resources/zh-cn/crops.yml +++ b/src/main/resources/zh-cn/crops.yml @@ -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 diff --git a/src/main/resources/zh-cn/messages.yml b/src/main/resources/zh-cn/messages.yml deleted file mode 100644 index 1b22a55..0000000 --- a/src/main/resources/zh-cn/messages.yml +++ /dev/null @@ -1,60 +0,0 @@ -#MiniMessage Format -#https://docs.adventure.kyori.net/minimessage/format.html -messages: - prefix: '[CustomCrops] ' - reload: '重载成功! 耗时 {time}ms' - no-perm: '权限不足!' - lack-args: '参数不足!' - wrong-args: '参数错误!' - spring: '春' - summer: '夏' - autumn: '秋' - winter: '冬' - sprinkler-limit: '此区块的洒水器已到达上限{max}' - crop-limit: '此区块的农作物数量已到达上限{max}' - not-configed: '此种子未在配置文件中配置!' - bad-Y: '此高度不适合这种农作物生长!' - bad-biome: '此生物群系不适合这种农作物生长!' - bad-perm: '你还没有权限种植这种农作物呢!' - bad-world: '这个农作物无法在这个世界生长!' - bad-season: '当前季节不适合这种农作物生长!' - force-grow: '成功强制 {world} 的农作物生长!' - force-water: '成功强制 {world} 的洒水器洒水!' - force-save: '成功强制保存缓存信息!' - back-up: '已完成数据备份!' - set-season: '成功切换世界 {world} 的季节为 {season}!' - before-plant: '这种肥料必须在种植前使用!' - no-season: '当前世界没有季节' - -#全息信息显示 -hologram: - #农作物肥料信息 - grow-info: - enable: true - #悬浮信息高度偏移 - y-offset: 0.8 - #悬浮信息持续时间(秒) - duration: 1 - #悬浮信息内容 - #可用变量 {fertilizer}肥料名 {times}剩余生效次数 {max_times}最大生效次数 - text: '{fertilizer} {times}/{max_times}' - #洒水器信息 - sprinkler-info: - enable: true - y-offset: -0.2 - duration: 1 - #可用变量 {water}当前水量 {max_water}最大蓄水量 - left: '뀂' - full: '뀁뀃' - empty: '뀁뀄' - right: '뀁뀅' - -actionbar: - #使用水壶的时候是否发送actionbar - watering-can: - enable: true - #可用变量 {water}当前水量 {max_water}最大蓄水量 - left: '뀂' - full: '뀁뀃' - empty: '뀁뀄' - right: '뀁뀅' \ No newline at end of file