diff --git a/src/main/java/net/momirealms/customcrops/CustomCrops.java b/src/main/java/net/momirealms/customcrops/CustomCrops.java index f4e58af..41a99e3 100644 --- a/src/main/java/net/momirealms/customcrops/CustomCrops.java +++ b/src/main/java/net/momirealms/customcrops/CustomCrops.java @@ -70,6 +70,9 @@ public final class CustomCrops extends JavaPlugin { ConfigUtil.reloadConfigs(); + if (MainConfig.cropMode) AdventureUtil.consoleMessage("[CustomCrops] Crop Mode: Tripwire"); + else AdventureUtil.consoleMessage("[CustomCrops] Crop Mode: ItemFrame"); + this.pluginCommand = new PluginCommand(); Objects.requireNonNull(Bukkit.getPluginCommand("customcrops")).setExecutor(pluginCommand); Objects.requireNonNull(Bukkit.getPluginCommand("customcrops")).setTabCompleter(pluginCommand); diff --git a/src/main/java/net/momirealms/customcrops/api/event/FertilizerUseEvent.java b/src/main/java/net/momirealms/customcrops/api/event/FertilizerUseEvent.java index 9aa3fa4..9c9ce79 100644 --- a/src/main/java/net/momirealms/customcrops/api/event/FertilizerUseEvent.java +++ b/src/main/java/net/momirealms/customcrops/api/event/FertilizerUseEvent.java @@ -36,6 +36,7 @@ public class FertilizerUseEvent extends PlayerEvent implements Cancellable { super(who); this.cancelled = false; this.potLoc = potLoc; + this.fertilizer = fertilizer; } @Override diff --git a/src/main/java/net/momirealms/customcrops/api/event/WaterEvent.java b/src/main/java/net/momirealms/customcrops/api/event/WaterEvent.java index 07257a4..67a30b5 100644 --- a/src/main/java/net/momirealms/customcrops/api/event/WaterEvent.java +++ b/src/main/java/net/momirealms/customcrops/api/event/WaterEvent.java @@ -33,6 +33,7 @@ public class WaterEvent extends PlayerEvent implements Cancellable { public WaterEvent(@NotNull Player who, ItemStack itemStack) { super(who); this.cancelled = false; + this.itemStack = itemStack; } @Override diff --git a/src/main/java/net/momirealms/customcrops/commands/AbstractSubCommand.java b/src/main/java/net/momirealms/customcrops/commands/AbstractSubCommand.java index 3581cb7..45aa65d 100644 --- a/src/main/java/net/momirealms/customcrops/commands/AbstractSubCommand.java +++ b/src/main/java/net/momirealms/customcrops/commands/AbstractSubCommand.java @@ -1,7 +1,9 @@ package net.momirealms.customcrops.commands; +import net.momirealms.customcrops.config.MainConfig; import net.momirealms.customcrops.config.MessageConfig; import net.momirealms.customcrops.utils.AdventureUtil; +import org.bukkit.World; import org.bukkit.command.CommandSender; import java.util.ArrayList; @@ -67,6 +69,17 @@ public abstract class AbstractSubCommand implements SubCommand { subCommandMap.put(command.getSubCommand(), command); } + public List getWorlds(List args) { + List worlds = MainConfig.getWorldsList(); + List worldNames = new ArrayList<>(); + for (World world : worlds) { + if (world.getName().startsWith(args.get(0))) { + worldNames.add(world.getName()); + } + } + return worldNames; + } + public void setSubCommandMap(Map subCommandMap) { this.subCommandMap = subCommandMap; } diff --git a/src/main/java/net/momirealms/customcrops/commands/PluginCommand.java b/src/main/java/net/momirealms/customcrops/commands/PluginCommand.java index 21cd34d..9c609c1 100644 --- a/src/main/java/net/momirealms/customcrops/commands/PluginCommand.java +++ b/src/main/java/net/momirealms/customcrops/commands/PluginCommand.java @@ -2,6 +2,7 @@ package net.momirealms.customcrops.commands; import net.momirealms.customcrops.commands.subcmd.ReloadCommand; import net.momirealms.customcrops.commands.subcmd.SetSeasonCommand; +import net.momirealms.customcrops.commands.subcmd.SimulateCommand; import net.momirealms.customcrops.config.MessageConfig; import net.momirealms.customcrops.utils.AdventureUtil; import org.bukkit.command.Command; @@ -40,6 +41,7 @@ public class PluginCommand implements TabExecutor { private void regDefaultSubCommands() { regSubCommand(ReloadCommand.INSTANCE); regSubCommand(SetSeasonCommand.INSTANCE); + regSubCommand(SimulateCommand.INSTANCE); } public void regSubCommand(SubCommand executor) { diff --git a/src/main/java/net/momirealms/customcrops/commands/subcmd/ReloadCommand.java b/src/main/java/net/momirealms/customcrops/commands/subcmd/ReloadCommand.java index 3657d95..db96e38 100644 --- a/src/main/java/net/momirealms/customcrops/commands/subcmd/ReloadCommand.java +++ b/src/main/java/net/momirealms/customcrops/commands/subcmd/ReloadCommand.java @@ -15,14 +15,6 @@ public final class ReloadCommand extends AbstractSubCommand { private ReloadCommand() { super("reload", null); - regSubCommand(new AbstractSubCommand("config", null) { - @Override - public boolean onCommand(CommandSender sender, List args) { - ConfigUtil.reloadConfigs(); - AdventureUtil.sendMessage(sender, MessageConfig.prefix + MessageConfig.reload); - return true; - } - }); } @Override diff --git a/src/main/java/net/momirealms/customcrops/commands/subcmd/SetSeasonCommand.java b/src/main/java/net/momirealms/customcrops/commands/subcmd/SetSeasonCommand.java index e86333b..af5054a 100644 --- a/src/main/java/net/momirealms/customcrops/commands/subcmd/SetSeasonCommand.java +++ b/src/main/java/net/momirealms/customcrops/commands/subcmd/SetSeasonCommand.java @@ -10,6 +10,7 @@ import org.bukkit.Bukkit; import org.bukkit.World; import org.bukkit.command.CommandSender; +import java.util.ArrayList; import java.util.List; public class SetSeasonCommand extends AbstractSubCommand { @@ -18,14 +19,6 @@ public class SetSeasonCommand extends AbstractSubCommand { public SetSeasonCommand() { super("setseason", null); - regSubCommand(new AbstractSubCommand("config", null) { - @Override - public boolean onCommand(CommandSender sender, List args) { - - AdventureUtil.sendMessage(sender, MessageConfig.prefix + MessageConfig.setSeason); - return true; - } - }); } @Override @@ -54,12 +47,21 @@ public class SetSeasonCommand extends AbstractSubCommand { return super.onCommand(sender, args); } - public static void setSeason() { - MainConfig.load(); - FertilizerConfig.load(); - MessageConfig.load(); - SeasonConfig.load(); - SprinklerConfig.load(); - WaterCanConfig.load(); + @Override + public List onTabComplete(CommandSender sender, List args) { + if (args.size() == 1) { + return getWorlds(args); + } + if (args.size() == 2) { + List seasons = List.of("Spring","Summer","Autumn","Winter"); + List seasonList = new ArrayList<>(); + for (String season : seasons) { + if (season.startsWith(args.get(1))) { + seasonList.add(season); + } + } + return seasonList; + } + return super.onTabComplete(sender, args); } } diff --git a/src/main/java/net/momirealms/customcrops/commands/subcmd/SimulateCommand.java b/src/main/java/net/momirealms/customcrops/commands/subcmd/SimulateCommand.java new file mode 100644 index 0000000..afba020 --- /dev/null +++ b/src/main/java/net/momirealms/customcrops/commands/subcmd/SimulateCommand.java @@ -0,0 +1,74 @@ +package net.momirealms.customcrops.commands.subcmd; + +import net.momirealms.customcrops.CustomCrops; +import net.momirealms.customcrops.commands.AbstractSubCommand; +import net.momirealms.customcrops.commands.SubCommand; +import net.momirealms.customcrops.config.MessageConfig; +import net.momirealms.customcrops.utils.AdventureUtil; +import org.bukkit.Bukkit; +import org.bukkit.World; +import org.bukkit.command.CommandSender; + +import java.util.List; + +public class SimulateCommand extends AbstractSubCommand { + + public static final SubCommand INSTANCE = new SimulateCommand(); + + private SimulateCommand() { + super("simulate", null); + } + + @Override + public boolean onCommand(CommandSender sender, List args) { + if (args.size() < 4) { + AdventureUtil.sendMessage(sender, MessageConfig.prefix + MessageConfig.lackArgs); + } + else { + World world = Bukkit.getWorld(args.get(0)); + if (world == null) { + AdventureUtil.sendMessage(sender, MessageConfig.prefix + MessageConfig.worldNotExists); + return true; + } + int sprinklerTime; + int growTime; + int dryTime; + try { + sprinklerTime = Integer.parseInt(args.get(1)); + growTime = Integer.parseInt(args.get(3)); + dryTime = Integer.parseInt(args.get(2)); + if (sprinklerTime <= 0 || growTime <= 0 || dryTime <= 0 || (sprinklerTime + growTime + dryTime) > 23999) { + AdventureUtil.sendMessage(sender, MessageConfig.prefix + "Time should be a positive number between 1-23999"); + return true; + } + } + catch (IllegalArgumentException e) { + AdventureUtil.sendMessage(sender, MessageConfig.prefix + "Time should be a positive number between 1-23999"); + e.printStackTrace(); + return true; + } + Bukkit.getScheduler().runTaskAsynchronously(CustomCrops.plugin, () -> { + CustomCrops.plugin.getCropManager().grow(world, growTime, sprinklerTime, dryTime); + }); + AdventureUtil.sendMessage(sender, MessageConfig.prefix + MessageConfig.growSimulation); + } + return true; + } + + @Override + public List onTabComplete(CommandSender sender, List args) { + if (args.size() == 1) { + return getWorlds(args); + } + if (args.size() == 2) { + return List.of(""); + } + if (args.size() == 3) { + return List.of(""); + } + if (args.size() == 4) { + return List.of(""); + } + return super.onTabComplete(sender, args); + } +} diff --git a/src/main/java/net/momirealms/customcrops/config/MainConfig.java b/src/main/java/net/momirealms/customcrops/config/MainConfig.java index 6e0127f..e8bbd85 100644 --- a/src/main/java/net/momirealms/customcrops/config/MainConfig.java +++ b/src/main/java/net/momirealms/customcrops/config/MainConfig.java @@ -37,11 +37,10 @@ public class MainConfig { public static World[] worlds; public static List worldList; public static boolean whiteOrBlack; - public static boolean asyncTimeCheck; public static String customPlugin; public static boolean OraxenHook; public static boolean realisticSeasonHook; - public static String cropMode; + public static boolean cropMode; public static List antiGriefs; public static SkillXP skillXP; public static double dryGrowChance; @@ -55,6 +54,8 @@ public class MainConfig { public static int waterToWaterCan; public static int wateringCanToSprinkler; public static int timeToGrow; + public static int timeToWork; + public static int timeToDry; public static String lang; public static boolean preventInWrongSeason; public static boolean notifyInWrongSeason; @@ -79,6 +80,10 @@ public class MainConfig { public static double fertilizerInfoY; public static int fertilizerInfoDuration; public static String fertilizerInfo; + public static boolean enableParticles; + public static boolean enableAnimations; + public static boolean autoGrow; + public static boolean enableCompensation; public static void load() { ConfigUtil.update("config.yml"); @@ -95,12 +100,18 @@ public class MainConfig { } } worldList = List.of(worlds); - cropMode = config.getString("crops.mode", "tripwire"); - asyncTimeCheck = config.getBoolean("optimization.async-time-check", false); + cropMode = config.getString("crops.mode", "tripwire").equals("tripwire"); limitation = config.getBoolean("optimization.limitation.enable", true); wireAmount = config.getInt("optimization.limitation.tripwire-amount", 64); frameAmount = config.getInt("optimization.limitation.itemframe-amount", 64); + autoGrow = config.getBoolean("mechanics.auto-grow.enable", true); + enableCompensation = config.getBoolean("mechanics.auto-grow.time-compensation", true); + timeToGrow = config.getInt("mechanics.auto-grow.crops-grow-time", 20000); + timeToWork = config.getInt("mechanics.auto-grow.sprinkler-work-time", 300); + timeToDry = config.getInt("mechanics.auto-grow.pot-dry-time", 200); + dryGrowChance = config.getDouble("mechanics.dry-pot-grow-chance", 0.5); + waterBucketToSprinkler = config.getInt("mechanics.fill.water-bucket-to-sprinkler", 3); waterToWaterCan = config.getInt("mechanics.fill.waterblock-to-watering-can", 1); wateringCanToSprinkler = config.getInt("mechanics.fill.watering-can-to-sprinkler", 1); @@ -113,6 +124,9 @@ public class MainConfig { enableBoneMeal = config.getBoolean("mechanics.bone-meal", true); boneMealChance = config.getDouble("mechanics.chance", 0.5); + enableParticles = !config.getBoolean("optimization.disable-water-particles", false); + enableAnimations = !config.getBoolean("optimization.disable-sprinkler-animation", false); + try { boneMealSuccess = Particle.valueOf(config.getString("mechanics.success-particle", "VILLAGER_HAPPY")); } diff --git a/src/main/java/net/momirealms/customcrops/config/MessageConfig.java b/src/main/java/net/momirealms/customcrops/config/MessageConfig.java index ad3e8f8..b4f71e0 100644 --- a/src/main/java/net/momirealms/customcrops/config/MessageConfig.java +++ b/src/main/java/net/momirealms/customcrops/config/MessageConfig.java @@ -45,6 +45,7 @@ public class MessageConfig { public static String noSeason; public static String worldNotExists; public static String seasonNotExists; + public static String wrongSeason; public static void load() { YamlConfiguration config = ConfigUtil.getConfig("messages" + File.separator + "messages_" + MainConfig.lang +".yml"); @@ -68,5 +69,6 @@ public class MessageConfig { noSeason = config.getString("messages.no-season"); worldNotExists = config.getString("messages.world-not-exist"); seasonNotExists = config.getString("messages.season-not-exist"); + wrongSeason = config.getString("messages.wrong-season"); } } diff --git a/src/main/java/net/momirealms/customcrops/integrations/customplugin/HandlerP.java b/src/main/java/net/momirealms/customcrops/integrations/customplugin/HandlerP.java index 554a18e..4af570f 100644 --- a/src/main/java/net/momirealms/customcrops/integrations/customplugin/HandlerP.java +++ b/src/main/java/net/momirealms/customcrops/integrations/customplugin/HandlerP.java @@ -34,10 +34,7 @@ import net.momirealms.customcrops.utils.FurnitureUtil; import net.momirealms.customcrops.utils.HologramUtil; import net.momirealms.customcrops.utils.LimitationUtil; import org.apache.commons.lang.StringUtils; -import org.bukkit.Bukkit; -import org.bukkit.GameMode; -import org.bukkit.Location; -import org.bukkit.Material; +import org.bukkit.*; import org.bukkit.block.Block; import org.bukkit.entity.Player; import org.bukkit.event.HandlerList; @@ -144,13 +141,13 @@ public abstract class HandlerP extends Function { if (canConfig == null) return; AdventureUtil.playerActionbar( - player, - (MainConfig.actionBarLeft + - MainConfig.actionBarFull.repeat(canWater) + - MainConfig.actionBarEmpty.repeat(canConfig.getMax() - canWater) + - MainConfig.actionBarRight) - .replace("{max_water}", String.valueOf(canConfig.getMax())) - .replace("{water}", String.valueOf(canWater)) + player, + (MainConfig.actionBarLeft + + MainConfig.actionBarFull.repeat(canWater) + + MainConfig.actionBarEmpty.repeat(canConfig.getMax() - canWater) + + MainConfig.actionBarRight) + .replace("{max_water}", String.valueOf(canConfig.getMax())) + .replace("{water}", String.valueOf(canWater)) ); } } @@ -159,15 +156,15 @@ public abstract class HandlerP extends Function { if (MainConfig.enableSprinklerInfo) HologramUtil.showHolo( - (MainConfig.sprinklerLeft + - MainConfig.sprinklerFull.repeat(sprinkler.getWater()) + - MainConfig.sprinklerEmpty.repeat(config.getWater() - sprinkler.getWater()) + - MainConfig.sprinklerRight) - .replace("{max_water}", String.valueOf(config.getWater())) - .replace("{water}", String.valueOf(sprinkler.getWater())), - player, - location.add(0, MainConfig.sprinklerInfoY - 1,0), - MainConfig.sprinklerInfoDuration); + (MainConfig.sprinklerLeft + + MainConfig.sprinklerFull.repeat(sprinkler.getWater()) + + MainConfig.sprinklerEmpty.repeat(config.getWater() - sprinkler.getWater()) + + MainConfig.sprinklerRight) + .replace("{max_water}", String.valueOf(config.getWater())) + .replace("{water}", String.valueOf(sprinkler.getWater())), + player, + location.add(0, MainConfig.sprinklerInfoY - 1,0), + MainConfig.sprinklerInfoDuration); } @@ -199,13 +196,13 @@ public abstract class HandlerP extends Function { } HologramUtil.showHolo( - MainConfig.fertilizerInfo - .replace("{fertilizer}", fertilizer.getName()) - .replace("{times}", String.valueOf(fertilizer.getTimes())) - .replace("{max_times}", String.valueOf(config.getTimes())), - player, - potLoc.add(0.5, MainConfig.fertilizerInfoY, 0.5), - MainConfig.fertilizerInfoDuration); + MainConfig.fertilizerInfo + .replace("{fertilizer}", fertilizer.getName()) + .replace("{times}", String.valueOf(fertilizer.getTimes())) + .replace("{max_times}", String.valueOf(config.getTimes())), + player, + potLoc.add(0.5, MainConfig.fertilizerInfoY, 0.5), + MainConfig.fertilizerInfoDuration); } return true; } @@ -318,6 +315,11 @@ public abstract class HandlerP extends Function { 1,1 ); } + + if (MainConfig.enableParticles) { + player.getWorld().spawnParticle(Particle.WATER_SPLASH, block.getLocation().add(0.5,1, 0.5),10,0.1,0.1,0.1); + } + } break; } @@ -363,6 +365,10 @@ public abstract class HandlerP extends Function { return true; } + if (fertilizer.getParticle() != null) { + potLoc.getWorld().spawnParticle(fertilizer.getParticle(), potLoc.clone().add(0.5,1.1,0.5), 5,0.25,0.1,0.25, 0); + } + if (SoundConfig.useFertilizer.isEnable()) { AdventureUtil.playerSound( player, @@ -373,7 +379,7 @@ public abstract class HandlerP extends Function { } if (player.getGameMode() != GameMode.CREATIVE) itemStack.setAmount(itemStack.getAmount() - 1); - customWorld.addFertilizer(potLoc, fertilizer); + customWorld.addFertilizer(potLoc, fertilizer.getWithTimes(fertilizer.getTimes())); return true; } @@ -388,6 +394,7 @@ public abstract class HandlerP extends Function { if (customWorld == null) return; //remove fertilizer customWorld.removeFertilizer(location); + customWorld.removeWatered(location); } public void onQuit(Player player) { @@ -395,6 +402,10 @@ public abstract class HandlerP extends Function { } public void waterPot(int width, int length, Location location, float yaw){ + //TODO + CustomWorld customWorld = cropManager.getCustomWorld(location.getWorld()); + if (customWorld == null) return; + int extend = width / 2; if (yaw < 45 && yaw > -135) { if (yaw > -45) { @@ -402,13 +413,8 @@ public abstract class HandlerP extends Function { Location tempLoc = location.clone().add(i, 0, -1); for (int j = 0; j < length; j++){ tempLoc.add(0,0,1); - String blockID = customInterface.getBlockID(tempLoc); - if(blockID != null){ - if(blockID.equals(BasicItemConfig.dryPot)){ - customInterface.removeBlock(tempLoc); - customInterface.placeNoteBlock(tempLoc, BasicItemConfig.wetPot); - } - } + customWorld.setPlayerWatered(tempLoc); + waterPot(tempLoc); } } } @@ -417,13 +423,8 @@ public abstract class HandlerP extends Function { Location tempLoc = location.clone().add(-1, 0, i); for (int j = 0; j < length; j++){ tempLoc.add(1,0,0); - String blockID = customInterface.getBlockID(tempLoc); - if(blockID != null){ - if(blockID.equals(BasicItemConfig.dryPot)){ - customInterface.removeBlock(tempLoc); - customInterface.placeNoteBlock(tempLoc, BasicItemConfig.wetPot); - } - } + customWorld.setPlayerWatered(tempLoc); + waterPot(tempLoc); } } } @@ -434,13 +435,8 @@ public abstract class HandlerP extends Function { Location tempLoc = location.clone().add(1, 0, i); for (int j = 0; j < length; j++){ tempLoc.subtract(1,0,0); - String blockID = customInterface.getBlockID(tempLoc); - if(blockID != null){ - if(blockID.equals(BasicItemConfig.dryPot)){ - customInterface.removeBlock(tempLoc); - customInterface.placeNoteBlock(tempLoc, BasicItemConfig.wetPot); - } - } + customWorld.setPlayerWatered(tempLoc); + waterPot(tempLoc); } } } @@ -449,16 +445,24 @@ public abstract class HandlerP extends Function { Location tempLoc = location.clone().add(i, 0, 1); for (int j = 0; j < length; j++){ tempLoc.subtract(0,0,1); - String blockID = customInterface.getBlockID(tempLoc); - if(blockID != null){ - if(blockID.equals(BasicItemConfig.dryPot)){ - customInterface.removeBlock(tempLoc); - customInterface.placeNoteBlock(tempLoc, BasicItemConfig.wetPot); - } - } + customWorld.setPlayerWatered(tempLoc); + waterPot(tempLoc); } } } } } + + private void waterPot(Location tempLoc) { + String blockID = customInterface.getBlockID(tempLoc); + if(blockID != null){ + if(blockID.equals(BasicItemConfig.dryPot)){ + customInterface.removeBlock(tempLoc); + customInterface.placeNoteBlock(tempLoc, BasicItemConfig.wetPot); + if (MainConfig.enableParticles) { + tempLoc.getWorld().spawnParticle(Particle.WATER_SPLASH, tempLoc.clone().add(0.5,1, 0.5),3,0.1,0.1,0.1); + } + } + } + } } diff --git a/src/main/java/net/momirealms/customcrops/integrations/customplugin/itemsadder/ItemsAdderHandler.java b/src/main/java/net/momirealms/customcrops/integrations/customplugin/itemsadder/ItemsAdderHandler.java index 67017fe..ff47458 100644 --- a/src/main/java/net/momirealms/customcrops/integrations/customplugin/itemsadder/ItemsAdderHandler.java +++ b/src/main/java/net/momirealms/customcrops/integrations/customplugin/itemsadder/ItemsAdderHandler.java @@ -25,16 +25,20 @@ import dev.lone.itemsadder.api.Events.CustomBlockBreakEvent; import dev.lone.itemsadder.api.Events.CustomBlockInteractEvent; import dev.lone.itemsadder.api.Events.FurnitureBreakEvent; import dev.lone.itemsadder.api.Events.FurnitureInteractEvent; +import net.kyori.adventure.key.Key; import net.momirealms.customcrops.CustomCrops; import net.momirealms.customcrops.api.crop.Crop; import net.momirealms.customcrops.api.event.WaterEvent; import net.momirealms.customcrops.config.CropConfig; +import net.momirealms.customcrops.config.MainConfig; +import net.momirealms.customcrops.config.SoundConfig; import net.momirealms.customcrops.config.WaterCanConfig; import net.momirealms.customcrops.integrations.customplugin.HandlerP; import net.momirealms.customcrops.integrations.customplugin.itemsadder.listeners.ItemsAdderBlockListener; import net.momirealms.customcrops.integrations.customplugin.itemsadder.listeners.ItemsAdderFurnitureListener; import net.momirealms.customcrops.managers.CropManager; import net.momirealms.customcrops.objects.WaterCan; +import net.momirealms.customcrops.utils.AdventureUtil; import org.apache.commons.lang.StringUtils; import org.bukkit.Bukkit; import org.bukkit.Location; @@ -82,7 +86,8 @@ public abstract class ItemsAdderHandler extends HandlerP { if (action == Action.RIGHT_CLICK_BLOCK || action == Action.RIGHT_CLICK_AIR) { Block block = event.getClickedBlock(); - if (block != null && (block.getType().isInteractable() || block.getType() == Material.TRIPWIRE)) return; + + if (block != null && ((block.getType().isInteractable() && block.getType() != Material.NOTE_BLOCK) || block.getType() == Material.TRIPWIRE)) return; ItemStack item = event.getItem(); if (item == null || item.getType() == Material.AIR) return; @@ -126,16 +131,11 @@ public abstract class ItemsAdderHandler extends HandlerP { private boolean useWateringCan(Location potLoc, String namespacedID, Player player, @NotNull CustomStack can) { WaterCan waterCan = WaterCanConfig.CANS.get(namespacedID); + if (waterCan == null) return false; - if (can.hasCustomDurability()) { - if (can.getDurability() > 0) { - can.setDurability(can.getDurability() - 1); - } - else return true; - } - - NBTItem nbtItem = new NBTItem(can.getItemStack()); + ItemStack itemStack = can.getItemStack(); + NBTItem nbtItem = new NBTItem(itemStack); int water = nbtItem.getInteger("WaterAmount"); if (water > 0) { @@ -145,9 +145,49 @@ public abstract class ItemsAdderHandler extends HandlerP { return true; } - nbtItem.setInteger("WaterAmount", water - 1); - //TODO check - can.getItemStack().setItemMeta(nbtItem.getItem().getItemMeta()); + NBTCompound nbtCompound = nbtItem.getCompound("itemsadder"); + if (nbtCompound.hasKey("custom_durability")){ + int dur = nbtCompound.getInteger("custom_durability"); + int max_dur = nbtCompound.getInteger("max_custom_durability"); + if (dur > 0){ + nbtCompound.setInteger("custom_durability", dur - 1); + nbtCompound.setDouble("fake_durability", (int) itemStack.getType().getMaxDurability() * (double) (dur/max_dur)); + nbtItem.setInteger("Damage", (int) (itemStack.getType().getMaxDurability() * (1 - (double) dur/max_dur))); + } + else { + AdventureUtil.playerSound(player, net.kyori.adventure.sound.Sound.Source.PLAYER, Key.key("minecraft:item.shield.break"), 1, 1); + itemStack.setAmount(itemStack.getAmount() - 1); + } + } + + nbtItem.setInteger("WaterAmount", --water); + + if (SoundConfig.waterPot.isEnable()) { + AdventureUtil.playerSound( + player, + SoundConfig.waterPot.getSource(), + SoundConfig.waterPot.getKey(), + 1,1 + ); + } + + if (MainConfig.enableActionBar) { + String canID = customInterface.getItemID(itemStack); + WaterCan canConfig = WaterCanConfig.CANS.get(canID); + if (canConfig == null) return true; + + AdventureUtil.playerActionbar( + player, + (MainConfig.actionBarLeft + + MainConfig.actionBarFull.repeat(water) + + MainConfig.actionBarEmpty.repeat(canConfig.getMax() - water) + + MainConfig.actionBarRight) + .replace("{max_water}", String.valueOf(canConfig.getMax())) + .replace("{water}", String.valueOf(water)) + ); + } + + itemStack.setItemMeta(nbtItem.getItem().getItemMeta()); super.waterPot(waterCan.width(), waterCan.getLength(), potLoc, player.getLocation().getYaw()); } diff --git a/src/main/java/net/momirealms/customcrops/integrations/customplugin/itemsadder/ItemsAdderWireHandler.java b/src/main/java/net/momirealms/customcrops/integrations/customplugin/itemsadder/ItemsAdderWireHandler.java index 8ea3a84..934b372 100644 --- a/src/main/java/net/momirealms/customcrops/integrations/customplugin/itemsadder/ItemsAdderWireHandler.java +++ b/src/main/java/net/momirealms/customcrops/integrations/customplugin/itemsadder/ItemsAdderWireHandler.java @@ -29,6 +29,7 @@ import net.momirealms.customcrops.api.crop.Crop; import net.momirealms.customcrops.api.event.SeedPlantEvent; import net.momirealms.customcrops.config.*; import net.momirealms.customcrops.integrations.AntiGrief; +import net.momirealms.customcrops.integrations.season.CCSeason; import net.momirealms.customcrops.managers.CropManager; import net.momirealms.customcrops.managers.CustomWorld; import net.momirealms.customcrops.objects.Sprinkler; @@ -104,20 +105,17 @@ public class ItemsAdderWireHandler extends ItemsAdderHandler { final String blockID = cb.getNamespacedID(); //interact crop if (blockID.contains("_stage_")) { + //ripe crops + if (!blockID.equals(BasicItemConfig.deadCrop) && !hasNextStage(blockID) && MainConfig.canRightClickHarvest) { + if (MainConfig.emptyHand && event.hasItem()) return; + Location seedLoc = block.getLocation(); + CustomBlock.remove(seedLoc); + this.onInteractRipeCrop(seedLoc, blockID, event.getPlayer()); + } - if (!blockID.equals(BasicItemConfig.deadCrop)) { - //ripe crops - if (!hasNextStage(blockID) && MainConfig.canRightClickHarvest) { - if (MainConfig.emptyHand && event.hasItem()) return; - Location seedLoc = block.getLocation(); - CustomBlock.remove(seedLoc); - this.onInteractRipeCrop(seedLoc, blockID, event.getPlayer()); - } - - else { - Location potLoc = block.getLocation().clone().subtract(0,1,0); - super.tryMisc(player, event.getItem(), potLoc); - } + else { + Location potLoc = block.getLocation().clone().subtract(0,1,0); + super.tryMisc(player, event.getItem(), potLoc); } } @@ -162,6 +160,14 @@ public class ItemsAdderWireHandler extends ItemsAdderHandler { return; } + CCSeason[] seasons = crop.getSeasons(); + if (seasons != null) { + if (cropManager.isWrongSeason(seedLoc, seasons)) { + if (MainConfig.notifyInWrongSeason) AdventureUtil.playerMessage(player, MessageConfig.prefix + MessageConfig.wrongSeason); + if (MainConfig.preventInWrongSeason) return; + } + } + SeedPlantEvent seedPlantEvent = new SeedPlantEvent(player, seedLoc, crop); Bukkit.getPluginManager().callEvent(seedPlantEvent); if (seedPlantEvent.isCancelled()) { diff --git a/src/main/java/net/momirealms/customcrops/managers/CropManager.java b/src/main/java/net/momirealms/customcrops/managers/CropManager.java index 5667411..a8aea27 100644 --- a/src/main/java/net/momirealms/customcrops/managers/CropManager.java +++ b/src/main/java/net/momirealms/customcrops/managers/CropManager.java @@ -46,7 +46,9 @@ import net.momirealms.customcrops.objects.QualityRatio; import net.momirealms.customcrops.objects.actions.ActionInterface; import net.momirealms.customcrops.objects.fertilizer.Fertilizer; import net.momirealms.customcrops.objects.fertilizer.QualityCrop; +import net.momirealms.customcrops.objects.fertilizer.RetainingSoil; import net.momirealms.customcrops.objects.fertilizer.YieldIncreasing; +import net.momirealms.customcrops.utils.AdventureUtil; import org.bukkit.Bukkit; import org.bukkit.GameMode; import org.bukkit.Location; @@ -83,26 +85,26 @@ public class CropManager extends Function { this.itemSpawnListener = new ItemSpawnListener(this); this.worldListener = new WorldListener(this); - //new Time Check task - this.timerTask = new TimerTask(this); - if (MainConfig.asyncTimeCheck) this.timerTask.runTaskTimerAsynchronously(CustomCrops.plugin, 1, 100); - else this.timerTask.runTaskTimer(CustomCrops.plugin, 1,100); - - //Crop mode - if (MainConfig.cropMode.equalsIgnoreCase("tripwire")) this.cropMode = new WireCropImpl(this); - else this.cropMode = new FrameCropImpl(this); - + //Custom Plugin if (MainConfig.customPlugin.equals("itemsadder")) { customInterface = new ItemsAdderHook(); - if (MainConfig.cropMode.equalsIgnoreCase("tripwire")) this.handler = new ItemsAdderWireHandler(this); + if (MainConfig.cropMode) this.handler = new ItemsAdderWireHandler(this); else this.handler = new ItemsAdderFrameHandler(this); } else if (MainConfig.customPlugin.equals("oraxen")){ customInterface = new OraxenHook(); - if (MainConfig.cropMode.equalsIgnoreCase("tripwire")) this.handler = new OraxenWireHandler(this); + if (MainConfig.cropMode) this.handler = new OraxenWireHandler(this); else this.handler = new OraxenFrameHandler(this); } + //Crop mode + if (MainConfig.cropMode) this.cropMode = new WireCropImpl(this); + else this.cropMode = new FrameCropImpl(this); + + //new Time Check task + this.timerTask = new TimerTask(this); + this.timerTask.runTaskTimerAsynchronously(CustomCrops.plugin, 1,100); + handler.load(); if (SeasonConfig.enable) { @@ -141,6 +143,11 @@ public class CropManager extends Function { if (MainConfig.getWorldsList().contains(world)) { CustomWorld customWorld = new CustomWorld(world, this); customWorlds.put(world, customWorld); + if (MainConfig.autoGrow && MainConfig.enableCompensation) { + if (world.getTime() < 24000 - MainConfig.timeToWork - MainConfig.timeToDry - 1200 && world.getTime() > 1500) { + Bukkit.getScheduler().runTaskLaterAsynchronously(CustomCrops.plugin, () -> grow(world, MainConfig.timeToGrow, MainConfig.timeToWork, MainConfig.timeToDry), 100); + } + } } } @@ -152,11 +159,11 @@ public class CropManager extends Function { seasonInterface.unloadWorld(world); } - public void grow(World world, int time) { + public void grow(World world, int cropTime, int sprinklerTime, int dryTime) { CustomWorld customWorld = customWorlds.get(world); if (customWorld == null) return; - if (MainConfig.cropMode.equals("tripwire")) customWorld.growWire(time); - else customWorld.growFrame(time); + if (MainConfig.cropMode) customWorld.growWire(cropTime, sprinklerTime, dryTime); + else customWorld.growFrame(cropTime, sprinklerTime, dryTime); } public CropModeInterface getCropMode() { @@ -199,15 +206,18 @@ public class CropManager extends Function { public void potDryJudge(Location potLoc) { World world = potLoc.getWorld(); CustomWorld customWorld = customWorlds.get(world); - if (customWorld == null) { + if (customWorld == null) return; + if (!customWorld.isPotWet(potLoc)) { makePotDry(potLoc); + return; } - else if (!customWorld.isPotWet(potLoc)) { + Fertilizer fertilizer = customWorld.getFertilizer(potLoc); + if (!(fertilizer instanceof RetainingSoil retainingSoil && Math.random() < retainingSoil.getChance())) { makePotDry(potLoc); } } - private void makePotDry(Location potLoc) { + public void makePotDry(Location potLoc) { customInterface.removeBlock(potLoc); customInterface.placeNoteBlock(potLoc, BasicItemConfig.dryPot); } @@ -216,8 +226,10 @@ public class CropManager extends Function { String potID = customInterface.getBlockID(potLoc); if (potID == null) return; if (!potID.equals(BasicItemConfig.dryPot)) return; - customInterface.removeBlock(potLoc); - customInterface.placeNoteBlock(potLoc, BasicItemConfig.wetPot); + Bukkit.getScheduler().runTask(CustomCrops.plugin, () -> { + customInterface.removeBlock(potLoc); + customInterface.placeNoteBlock(potLoc, BasicItemConfig.wetPot); + }); } @Nullable diff --git a/src/main/java/net/momirealms/customcrops/managers/CustomWorld.java b/src/main/java/net/momirealms/customcrops/managers/CustomWorld.java index ffb6bed..846bac4 100644 --- a/src/main/java/net/momirealms/customcrops/managers/CustomWorld.java +++ b/src/main/java/net/momirealms/customcrops/managers/CustomWorld.java @@ -17,6 +17,11 @@ package net.momirealms.customcrops.managers; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.google.gson.stream.JsonReader; import net.momirealms.customcrops.CustomCrops; import net.momirealms.customcrops.api.event.CustomWorldEvent; import net.momirealms.customcrops.config.ConfigUtil; @@ -34,11 +39,12 @@ import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.World; import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scheduler.BukkitScheduler; +import org.bukkit.scheduler.BukkitTask; import org.jetbrains.annotations.Nullable; -import java.io.File; -import java.io.IOException; +import java.io.*; import java.util.*; import java.util.concurrent.ConcurrentHashMap; @@ -49,19 +55,28 @@ public class CustomWorld { private final ConcurrentHashMap sprinklerCache; private final ConcurrentHashMap fertilizerCache; private final Set watered; + private HashSet tempWatered; + private final HashSet playerWatered; private final CropManager cropManager; + private final HashSet tasksCache; + private final BukkitScheduler bukkitScheduler; public CustomWorld(World world, CropManager cropManager) { this.world = world; this.cropCache = new ConcurrentHashMap<>(4096); this.fertilizerCache = new ConcurrentHashMap<>(2048); this.sprinklerCache = new ConcurrentHashMap<>(1024); + this.tasksCache = new HashSet<>(4096); this.cropManager = cropManager; + this.bukkitScheduler = Bukkit.getScheduler(); this.watered = Collections.synchronizedSet(new HashSet<>()); + this.playerWatered = new HashSet<>(); + this.tempWatered = new HashSet<>(); Bukkit.getScheduler().runTaskAsynchronously(CustomCrops.plugin, () -> { loadCropCache(); loadSprinklerCache(); loadFertilizerCache(); + loadPot(); Bukkit.getScheduler().runTask(CustomCrops.plugin, () -> { CustomWorldEvent customWorldEvent = new CustomWorldEvent(world, WorldState.LOAD); Bukkit.getPluginManager().callEvent(customWorldEvent); @@ -74,12 +89,18 @@ public class CustomWorld { unloadCrop(); unloadSprinkler(); unloadFertilizer(); + unloadPot(); } else { Bukkit.getScheduler().runTaskAsynchronously(CustomCrops.plugin, () -> { unloadCrop(); unloadSprinkler(); unloadFertilizer(); + unloadPot(); + for (BukkitTask task : tasksCache) { + task.cancel(); + } + tasksCache.clear(); Bukkit.getScheduler().runTask(CustomCrops.plugin, () -> { CustomWorldEvent customWorldEvent = new CustomWorldEvent(world, WorldState.UNLOAD); Bukkit.getPluginManager().callEvent(customWorldEvent); @@ -88,6 +109,44 @@ public class CustomWorld { } } + public void loadPot() { + try { + JsonParser jsonParser = new JsonParser(); + JsonElement json= jsonParser.parse(new FileReader(new File(CustomCrops.plugin.getDataFolder().getParentFile().getParentFile(), world.getName() + File.separator + "customcrops_data" + File.separator + "pot.json"))); + if (json.isJsonObject()) { + JsonObject jsonObject = json.getAsJsonObject(); + if (jsonObject.has("pot")) { + JsonArray jsonArray = jsonObject.getAsJsonArray("pot"); + String name = world.getName(); + for (JsonElement jsonElement : jsonArray) { + String loc = jsonElement.getAsString(); + String[] locs = StringUtils.split(loc, ","); + watered.add(new SimpleLocation(name, Integer.parseInt(locs[0]), Integer.parseInt(locs[1]), Integer.parseInt(locs[2]))); + } + } + } + } + catch (FileNotFoundException e) { + //bypass + } + } + + public void unloadPot() { + JsonObject jsonObject = new JsonObject(); + JsonArray jsonArray = new JsonArray(); + watered.addAll(playerWatered); + for (SimpleLocation simpleLocation : watered) { + jsonArray.add(simpleLocation.getX() + "," + simpleLocation.getY() + "," + simpleLocation.getZ()); + } + watered.clear(); + jsonObject.add("pot", jsonArray); + try (FileWriter fileWriter = new FileWriter(new File(CustomCrops.plugin.getDataFolder().getParentFile().getParentFile(), world.getName() + File.separator + "customcrops_data" + File.separator + "pot.json"))){ + fileWriter.write(jsonObject.toString().replace("\\\\", "\\")); + } catch (IOException e) { + e.printStackTrace(); + } + } + private void loadFertilizerCache() { YamlConfiguration data = loadData("fertilizers", world.getName()); for (String key : data.getKeys(false)) { @@ -181,51 +240,89 @@ public class CustomWorld { } } - public void growWire(int time) { - BukkitScheduler bukkitScheduler = Bukkit.getScheduler(); - CropModeInterface cropMode = cropManager.getCropMode(); - bukkitScheduler.runTaskAsynchronously(CustomCrops.plugin, () -> { - route(); - for (SimpleLocation location : cropCache.keySet()) { - bukkitScheduler.runTaskLaterAsynchronously(CustomCrops.plugin, () -> { - Location seedLoc = MiscUtils.getLocation(location); - if (seedLoc == null) return; - if (cropMode.growJudge(seedLoc)) { - cropCache.remove(location); - } - }, new Random().nextInt(time)); - } - }); - } + public void growWire(int cropTime, int sprinklerTime, int dryTime) { - public void growFrame(int time) { - BukkitScheduler bukkitScheduler = Bukkit.getScheduler(); + route(sprinklerTime); + Random randomGenerator = new Random(); CropModeInterface cropMode = cropManager.getCropMode(); - bukkitScheduler.runTaskAsynchronously(CustomCrops.plugin, () -> { - route(); - for (SimpleLocation location : cropCache.keySet()) { - long random = new Random().nextInt(time); - bukkitScheduler.runTaskLater(CustomCrops.plugin, () -> { - Location seedLoc = MiscUtils.getLocation(location); - if (seedLoc == null) return; - cropMode.loadChunk(seedLoc); - }, random); - bukkitScheduler.runTaskLater(CustomCrops.plugin, () -> { - Location seedLoc = MiscUtils.getLocation(location); - if (seedLoc == null) return; - if (cropMode.growJudge(seedLoc)) { - cropCache.remove(location); - } - }, random + 5); - } - }); - } - private void route() { - watered.clear(); - for (Map.Entry sprinklerEntry : sprinklerCache.entrySet()) { - sprinklerWork(sprinklerEntry.getKey(), sprinklerEntry.getValue()); + tempWatered.removeAll(watered); + for (SimpleLocation simpleLocation : tempWatered) { + bukkitScheduler.runTaskLater(CustomCrops.plugin, () -> { + Location dryLoc = MiscUtils.getLocation(simpleLocation); + if (dryLoc == null) return; + cropManager.potDryJudge(dryLoc); + }, sprinklerTime + randomGenerator.nextInt(dryTime)); } + + for (SimpleLocation location : cropCache.keySet()) { + BukkitTask task = bukkitScheduler.runTaskLaterAsynchronously(CustomCrops.plugin, () -> { + Location seedLoc = MiscUtils.getLocation(location); + if (seedLoc == null) return; + if (cropMode.growJudge(seedLoc)) { + cropCache.remove(location); + } + }, sprinklerTime + dryTime + randomGenerator.nextInt(cropTime)); + tasksCache.add(task); + } + } + + public void growFrame(int cropTime, int sprinklerTime, int dryTime) { + + route(sprinklerTime); + Random randomGenerator = new Random(); + CropModeInterface cropMode = cropManager.getCropMode(); + + tempWatered.removeAll(watered); + for (SimpleLocation simpleLocation : tempWatered) { + bukkitScheduler.runTaskLaterAsynchronously(CustomCrops.plugin, () -> { + Location dryLoc = MiscUtils.getLocation(simpleLocation); + if (dryLoc == null) return; + cropManager.potDryJudge(dryLoc); + }, sprinklerTime + randomGenerator.nextInt(dryTime)); + } + + for (SimpleLocation location : cropCache.keySet()) { + long random = randomGenerator.nextInt(cropTime); + BukkitTask task1 = bukkitScheduler.runTaskLater(CustomCrops.plugin, () -> { + Location seedLoc = MiscUtils.getLocation(location); + if (seedLoc == null) return; + cropMode.loadChunk(seedLoc); + }, random + dryTime + random); + BukkitTask task2 = bukkitScheduler.runTaskLater(CustomCrops.plugin, () -> { + Location seedLoc = MiscUtils.getLocation(location); + if (seedLoc == null) return; + if (cropMode.growJudge(seedLoc)) { + cropCache.remove(location); + } + }, sprinklerTime + dryTime + random + 5); + tasksCache.add(task1); + tasksCache.add(task2); + } + } + + private void route(int sprinklerTime) { + + for (BukkitTask task : tasksCache) { + task.cancel(); + } + tasksCache.clear(); + + tempWatered = new HashSet<>(watered); + watered.clear(); + watered.addAll(playerWatered); + playerWatered.clear(); + + Random randomGenerator = new Random(); + for (Map.Entry sprinklerEntry : sprinklerCache.entrySet()) { + + BukkitTask task = bukkitScheduler.runTaskLaterAsynchronously(CustomCrops.plugin, () -> { + sprinklerWork(sprinklerEntry.getKey(), sprinklerEntry.getValue()); + }, randomGenerator.nextInt(sprinklerTime)); + + tasksCache.add(task); + } + for (Map.Entry fertilizerEntry : fertilizerCache.entrySet()) { Fertilizer fertilizer = fertilizerEntry.getValue(); if (fertilizer.getTimes() > 1) { @@ -273,6 +370,10 @@ public class CustomWorld { fertilizerCache.remove(MiscUtils.getSimpleLocation(potLoc)); } + public void removeWatered(Location potLoc) { + watered.remove(MiscUtils.getSimpleLocation(potLoc)); + } + public void addFertilizer(Location potLoc, Fertilizer fertilizer) { fertilizerCache.put(MiscUtils.getSimpleLocation(potLoc), fertilizer); } @@ -297,4 +398,12 @@ public class CustomWorld { public void addSprinkler(Location location, Sprinkler sprinkler) { sprinklerCache.put(MiscUtils.getSimpleLocation(location), sprinkler); } + + public void setPotWet(Location location) { + watered.add(MiscUtils.getSimpleLocation(location)); + } + + public void setPlayerWatered(Location location) { + playerWatered.add(MiscUtils.getSimpleLocation(location)); + } } diff --git a/src/main/java/net/momirealms/customcrops/managers/FrameCropImpl.java b/src/main/java/net/momirealms/customcrops/managers/FrameCropImpl.java index 16f0b32..bffac7c 100644 --- a/src/main/java/net/momirealms/customcrops/managers/FrameCropImpl.java +++ b/src/main/java/net/momirealms/customcrops/managers/FrameCropImpl.java @@ -79,14 +79,7 @@ public class FrameCropImpl implements CropModeInterface { if (potID == null) return true; Fertilizer fertilizer = cropManager.getFertilizer(potLoc); - - boolean certainGrow = false; - if (potID.equals(BasicItemConfig.wetPot)) { - if (!(fertilizer instanceof RetainingSoil retainingSoil && Math.random() < retainingSoil.getChance())) { - cropManager.potDryJudge(potLoc); - } - certainGrow = true; - } + boolean certainGrow = potID.equals(BasicItemConfig.wetPot); int nextStage = Integer.parseInt(cropNameList[2]) + 1; String temp = StringUtils.chop(id); diff --git a/src/main/java/net/momirealms/customcrops/managers/WireCropImpl.java b/src/main/java/net/momirealms/customcrops/managers/WireCropImpl.java index 8bcac47..1514abe 100644 --- a/src/main/java/net/momirealms/customcrops/managers/WireCropImpl.java +++ b/src/main/java/net/momirealms/customcrops/managers/WireCropImpl.java @@ -17,6 +17,7 @@ package net.momirealms.customcrops.managers; +import net.momirealms.customcrops.CustomCrops; import net.momirealms.customcrops.api.crop.Crop; import net.momirealms.customcrops.config.BasicItemConfig; import net.momirealms.customcrops.config.CropConfig; @@ -28,6 +29,7 @@ import net.momirealms.customcrops.objects.fertilizer.Gigantic; import net.momirealms.customcrops.objects.fertilizer.RetainingSoil; import net.momirealms.customcrops.objects.fertilizer.SpeedGrow; import org.apache.commons.lang.StringUtils; +import org.bukkit.Bukkit; import org.bukkit.Chunk; import org.bukkit.Location; @@ -58,8 +60,10 @@ public class WireCropImpl implements CropModeInterface{ Crop crop = CropConfig.CROPS.get(cropKey); if (crop == null) return true; if (cropManager.isWrongSeason(location, crop.getSeasons())) { - customInterface.removeBlock(location); - customInterface.placeWire(location, BasicItemConfig.deadCrop); + Bukkit.getScheduler().runTask(CustomCrops.plugin, () -> { + customInterface.removeBlock(location); + customInterface.placeWire(location, BasicItemConfig.deadCrop); + }); return true; } Location potLoc = location.clone().subtract(0,1,0); @@ -68,13 +72,7 @@ public class WireCropImpl implements CropModeInterface{ Fertilizer fertilizer = cropManager.getFertilizer(potLoc); - boolean certainGrow = false; - if (potID.equals(BasicItemConfig.wetPot)) { - if (!(fertilizer instanceof RetainingSoil retainingSoil && Math.random() < retainingSoil.getChance())) { - cropManager.potDryJudge(potLoc); - } - certainGrow = true; - } + boolean certainGrow = potID.equals(BasicItemConfig.wetPot); int nextStage = Integer.parseInt(cropNameList[2]) + 1; String temp = StringUtils.chop(blockID); @@ -96,13 +94,15 @@ public class WireCropImpl implements CropModeInterface{ chance += gigantic.getChance(); } if (Math.random() < chance) { - customInterface.removeBlock(location); - if (giganticCrop.isBlock()) { - customInterface.placeWire(location, giganticCrop.getBlockID()); - } - else { - customInterface.placeFurniture(location, giganticCrop.getBlockID()); - } + Bukkit.getScheduler().runTask(CustomCrops.plugin, () -> { + customInterface.removeBlock(location); + if (giganticCrop.isBlock()) { + customInterface.placeWire(location, giganticCrop.getBlockID()); + } + else { + customInterface.placeFurniture(location, giganticCrop.getBlockID()); + } + }); } } return true; @@ -111,7 +111,9 @@ public class WireCropImpl implements CropModeInterface{ } private void addStage(Location seedLoc, String stage) { - customInterface.removeBlock(seedLoc); - customInterface.placeWire(seedLoc, stage); + Bukkit.getScheduler().runTask(CustomCrops.plugin, () -> { + customInterface.removeBlock(seedLoc); + customInterface.placeWire(seedLoc, stage); + }); } } diff --git a/src/main/java/net/momirealms/customcrops/managers/timer/TimerTask.java b/src/main/java/net/momirealms/customcrops/managers/timer/TimerTask.java index 79f6c21..5242e32 100644 --- a/src/main/java/net/momirealms/customcrops/managers/timer/TimerTask.java +++ b/src/main/java/net/momirealms/customcrops/managers/timer/TimerTask.java @@ -32,10 +32,11 @@ public class TimerTask extends BukkitRunnable { @Override public void run() { + if (!MainConfig.autoGrow) return; for (World world : MainConfig.getWorldsList()) { long time = world.getTime(); if (time > 950 && time < 1051) { - cropManager.grow(world, MainConfig.timeToGrow); + cropManager.grow(world, MainConfig.timeToGrow, MainConfig.timeToWork, MainConfig.timeToDry); } } } diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 85bcfa0..9d84a8d 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -39,9 +39,7 @@ worlds: -crops: - # Mode: tripwire/item_frame - mode: tripwire + @@ -52,12 +50,37 @@ optimization: tripwire-amount: 64 itemframe-amount: 64 - # Async time check - async-time-check: false - + # Disable the water particles when using watering-cans + disable-water-particles: false + # Disable the animation when sprinkler works + disable-sprinkler-animation: false mechanics: + + # Mode: tripwire/item_frame + crops-mode: tripwire + + # If enabled, crops would start growing at about 7am(at most 5 seconds inaccuracy) and finish growing in the rest of the day + # Note: All the crops can only start growing when a world's time is about 7am, so when a world is loaded and its time is 8am, + # crops would not grow in this day. You can enable time compensation make the crops grow when starting the server. + auto-grow: + enable: true + # For example, the time to start growing is 1000ticks(7am), + # sprinklers would finish their work in a random time between 1000~1300ticks, + # Pot would start drying in a random time between 1300~1500ticks + # and crops would grow in a random time between 1500~21300ticks + sprinkler-work-time: 300 + pot-dry-time: 200 + crops-grow-time: 20000 + # Crops would start growing instantly when the world is loaded instead of waiting for the second day's 7am + time-compensation: true + # If the pot is wet, crop would 100% grow a stage per day + # Otherwise they would have a lower chance to grow. + # Recommend setting it to a value higher than 0 to make sure every crop can be ripe even if + # players don't take care of them, this is good for server performance because crop data would + # be removed from data file when the crop is ripe to avoid affecting server performance in the long term + dry-pot-grow-chance: 0.5 # Can player harvest crops with right click? # if set "false" crops can't be harvested repeatedly right-click-harvest: diff --git a/src/main/resources/fertilizers_itemsadder.yml b/src/main/resources/fertilizers_itemsadder.yml index 9a6119d..2105edf 100644 --- a/src/main/resources/fertilizers_itemsadder.yml +++ b/src/main/resources/fertilizers_itemsadder.yml @@ -13,19 +13,21 @@ speed: before-plant: true #The particle to be displayed when using fertilizer #https://hub.spigotmc.org/javadocs/spigot/org/bukkit/Particle.html - particle: VILLAGER_HAPPY + particle: SPELL_WITCH speed_2: name: '뀍' chance: 0.2 times: 14 item: customcrops:speed_2 before-plant: true + particle: SPELL_WITCH speed_3: name: '뀎' chance: 0.3 times: 14 item: customcrops:speed_3 before-plant: true + particle: SPELL_WITCH #Pot have a small chance to retain its water after crops grow @@ -36,18 +38,21 @@ retaining: times: 28 item: customcrops:retaining_1 before-plant: false + particle: SPELL retaining_2: name: '뀊' chance: 0.2 times: 28 item: customcrops:retaining_2 before-plant: false + particle: SPELL retaining_3: name: '뀋' chance: 0.3 times: 28 item: customcrops:retaining_3 before-plant: false + particle: SPELL #When haveresting, players have a higher chance to get high quality crops. @@ -59,6 +64,7 @@ quality: ratio: 7/2/1 item: customcrops:quality_1 before-plant: true + particle: SCRAPE quality_2: name: '뀇' chance: 1 @@ -66,6 +72,7 @@ quality: ratio: 11/6/3 item: customcrops:quality_2 before-plant: true + particle: SCRAPE quality_3: name: '뀈' chance: 1 @@ -73,6 +80,7 @@ quality: ratio: 2/2/1 item: customcrops:quality_3 before-plant: true + particle: SCRAPE #When haveresting, players have a higher chance to get more crops. @@ -84,6 +92,7 @@ quantity: bonus: 1 item: customcrops:quantity_1 before-plant: true + particle: TOTEM quantity_2: name: '뀐' times: 14 @@ -91,6 +100,7 @@ quantity: bonus: 2 item: customcrops:quantity_2 before-plant: true + particle: TOTEM quantity_3: name: '뀑' times: 14 @@ -98,6 +108,7 @@ quantity: bonus: 2 item: customcrops:quantity_3 before-plant: true + particle: TOTEM #Crops have a higher chance to be gigantic @@ -108,15 +119,18 @@ gigantic: chance: 0.5 item: customcrops:gigantic_1 before-plant: true + particle: SPELL_MOB gigantic_2: name: '뀐' times: 14 chance: 0.5 item: customcrops:gigantic_2 before-plant: true + particle: SPELL_MOB gigantic_3: name: '뀑' times: 14 chance: 0.8 item: customcrops:gigantic_3 - before-plant: true \ No newline at end of file + before-plant: true + particle: SPELL_MOB \ No newline at end of file diff --git a/src/main/resources/fertilizers_oraxen.yml b/src/main/resources/fertilizers_oraxen.yml index 9ef8d17..a3d209a 100644 --- a/src/main/resources/fertilizers_oraxen.yml +++ b/src/main/resources/fertilizers_oraxen.yml @@ -13,19 +13,21 @@ speed: before-plant: true #The particle to be displayed when using fertilizer #https://hub.spigotmc.org/javadocs/spigot/org/bukkit/Particle.html - particle: VILLAGER_HAPPY + particle: SPELL_WITCH speed_2: name: '뀍' chance: 0.2 times: 14 item: speed_2 before-plant: true + particle: SPELL_WITCH speed_3: name: '뀎' chance: 0.3 times: 14 item: speed_3 before-plant: true + particle: SPELL_WITCH #Pot have a small chance to retain its water after crops grow @@ -36,18 +38,21 @@ retaining: times: 28 item: retaining_1 before-plant: false + particle: SPELL retaining_2: name: '뀊' chance: 0.2 times: 28 item: retaining_2 before-plant: false + particle: SPELL retaining_3: name: '뀋' chance: 0.3 times: 28 item: retaining_3 before-plant: false + particle: SPELL #When haveresting, players have a higher chance to get high quality crops. @@ -59,6 +64,7 @@ quality: ratio: 7/2/1 item: quality_1 before-plant: true + particle: SCRAPE quality_2: name: '뀇' times: 28 @@ -66,6 +72,7 @@ quality: ratio: 11/6/3 item: quality_2 before-plant: true + particle: SCRAPE quality_3: name: '뀈' times: 28 @@ -73,6 +80,7 @@ quality: ratio: 2/2/1 item: quality_3 before-plant: true + particle: SCRAPE #When haveresting, players have a higher chance to get more crops. @@ -84,6 +92,7 @@ quantity: bonus: 1 item: quantity_1 before-plant: true + particle: TOTEM quantity_2: name: '뀐' times: 14 @@ -91,6 +100,7 @@ quantity: bonus: 2 item: quantity_2 before-plant: true + particle: TOTEM quantity_3: name: '뀑' times: 14 @@ -98,6 +108,7 @@ quantity: bonus: 2 item: quantity_3 before-plant: true + particle: TOTEM #Crops have a higher chance to be gigantic @@ -109,15 +120,18 @@ gigantic: chance: 0.02 item: gigantic_1 before-plant: true + particle: SPELL_MOB gigantic_2: name: '뀐' times: 14 chance: 0.04 item: gigantic_2 before-plant: true + particle: SPELL_MOB gigantic_3: name: '뀑' times: 14 chance: 0.08 item: gigantic_3 - before-plant: true \ No newline at end of file + before-plant: true + particle: SPELL_MOB \ No newline at end of file diff --git a/src/main/resources/messages/messages_chinese.yml b/src/main/resources/messages/messages_chinese.yml index 72ba287..0b1cef2 100644 --- a/src/main/resources/messages/messages_chinese.yml +++ b/src/main/resources/messages/messages_chinese.yml @@ -16,6 +16,7 @@ messages: back-up: '已完成数据备份!' set-season: '成功切换世界 {world} 的季节为 {season}!' before-plant: '这种肥料必须在种植前使用!' + wrong-season: '当前季节不适合这个农作物生长' no-season: '此世界没有季节' season-disabled: '季节系统已被禁用'