From c123782dbd316de316f695237c88ca91d07b3195 Mon Sep 17 00:00:00 2001 From: Xiao-MoMi <70987828+Xiao-MoMi@users.noreply.github.com> Date: Mon, 15 May 2023 23:33:58 +0800 Subject: [PATCH] 3.2.0 --- build.gradle | 2 +- .../api/customplugin/PlatformManager.java | 83 +++- .../api/object/basic/ConfigManager.java | 2 + .../api/object/migrate/MigrateWorld.java | 6 +- .../customcrops/api/object/pot/PotConfig.java | 4 + .../customcrops/api/object/world/CCChunk.java | 39 +- .../customcrops/api/object/world/CCWorld.java | 355 ++++++++++++------ .../api/object/world/SimpleLocation.java | 3 +- .../api/object/world/WorldDataManager.java | 26 +- .../api/object/world/WorldListener.java | 4 +- .../customcrops/api/util/ConfigUtils.java | 21 +- .../command/CustomCropsCommand.java | 1 + .../command/subcmd/FixCommand.java | 45 +++ .../command/subcmd/MigrateCommand.java | 9 +- .../customcrops/helper/LibraryLoader.java | 3 +- .../integration/papi/SeasonPapi.java | 11 +- src/main/resources/config.yml | 17 +- 17 files changed, 459 insertions(+), 172 deletions(-) create mode 100644 src/main/java/net/momirealms/customcrops/command/subcmd/FixCommand.java diff --git a/build.gradle b/build.gradle index 000f81e..a7825d3 100644 --- a/build.gradle +++ b/build.gradle @@ -4,7 +4,7 @@ plugins { } group = 'net.momirealms' -version = '3.1.3' +version = '3.2.0' repositories { mavenCentral() diff --git a/src/main/java/net/momirealms/customcrops/api/customplugin/PlatformManager.java b/src/main/java/net/momirealms/customcrops/api/customplugin/PlatformManager.java index d58d6d7..6b0a377 100644 --- a/src/main/java/net/momirealms/customcrops/api/customplugin/PlatformManager.java +++ b/src/main/java/net/momirealms/customcrops/api/customplugin/PlatformManager.java @@ -90,6 +90,7 @@ public class PlatformManager extends Function { public void onBreakVanilla(BlockBreakEvent event) { if (event.isCancelled()) return; Block block = event.getBlock(); + if (block.getType() == Material.NOTE_BLOCK) plugin.getWorldDataManager().removeCorrupted(SimpleLocation.getByBukkitLocation(block.getLocation())); onBreakSomething(event.getPlayer(), block.getLocation(), block.getType().name(), event); } @@ -227,12 +228,83 @@ public class PlatformManager extends Function { return; } + if (onInteractBrokenPot(id, location)) { + return; + } + if (onInteractWithWateringCan(player, item_in_hand_id, item_in_hand, id, location)) { return; } } } + private boolean onInteractBrokenPot(String id, Location location) { + if (!id.equals("NOTE_BLOCK")) { + return false; + } + SimpleLocation simpleLocation = SimpleLocation.getByBukkitLocation(location); + String replacer; + String potKey = plugin.getWorldDataManager().removeCorrupted(simpleLocation); + Pot pot = plugin.getWorldDataManager().getPotData(simpleLocation); + if (pot != null) { + replacer = pot.isWet() ? pot.getConfig().getWetPot(pot.getFertilizer()) : pot.getConfig().getDryPot(pot.getFertilizer()); + } else { + if (potKey == null) { + return false; + } + PotConfig potConfig = plugin.getPotManager().getPotConfig(potKey); + if (potConfig == null) { + return true; + } + replacer = potConfig.getDryPot(null); + } + plugin.getPlatformInterface().placeNoteBlock(location, replacer); + furtherFix(location, 1); + return true; + } + + public void furtherFix(Location location, int range) { + if (range >= ConfigManager.fixRange) return; + List locations = new ArrayList<>(); + for (int i = -range; i <= range; i++) { + for (int j = -range; j <= range; j++) { + if (i == -range || i == range || j == range || j == -range) { + locations.add(location.clone().add(i, 0, j)); + } + } + } + int success = 0; + for (Location check : locations) { + SimpleLocation simpleLocation = SimpleLocation.getByBukkitLocation(check); + String id = plugin.getPlatformInterface().getBlockID(check.getBlock()); + String potKey = plugin.getWorldDataManager().removeCorrupted(simpleLocation); + if (!id.equals("NOTE_BLOCK")) { + continue; + } + + String replacer; + Pot pot = plugin.getWorldDataManager().getPotData(simpleLocation); + if (pot != null) { + replacer = pot.isWet() ? pot.getConfig().getWetPot(pot.getFertilizer()) : pot.getConfig().getDryPot(pot.getFertilizer()); + } else { + if (potKey == null) { + continue; + } + PotConfig potConfig = plugin.getPotManager().getPotConfig(potKey); + if (potConfig == null) { + continue; + } + replacer = potConfig.getDryPot(null); + } + plugin.getPlatformInterface().placeNoteBlock(check, replacer); + success++; + } + + if (success != 0) { + furtherFix(location, range + 1); + } + } + public boolean onBreakGlass(Player player, String id, Location location, Cancellable event) { if (!id.equals(ConfigManager.greenhouseBlock)) { return false; @@ -499,7 +571,7 @@ public class PlatformManager extends Function { } event.setCancelled(true); - doPassiveFillAction(player, item_in_hand, passiveFillMethod, bottomLoc); + doPassiveFillAction(player, item_in_hand, passiveFillMethod, location); plugin.getWorldDataManager().addWaterToPot(SimpleLocation.getByBukkitLocation(bottomLoc), potWaterEvent.getWater(), pot_id); return true; } @@ -921,8 +993,7 @@ public class PlatformManager extends Function { tryToWaterPot(tempLoc, id, particle, water); } } - } - else { + } else { for (int i = -extend; i <= extend; i++) { Location tempLoc = location.clone().add(-1, 0, i); for (int j = 0; j < length; j++){ @@ -931,8 +1002,7 @@ public class PlatformManager extends Function { } } } - } - else { + } else { if (yaw > 45 && yaw < 135) { for (int i = -extend; i <= extend; i++) { Location tempLoc = location.clone().add(1, 0, i); @@ -941,8 +1011,7 @@ public class PlatformManager extends Function { tryToWaterPot(tempLoc, id, particle, water); } } - } - else { + } else { for (int i = -extend; i <= extend; i++) { Location tempLoc = location.clone().add(i, 0, 1); for (int j = 0; j < length; j++){ diff --git a/src/main/java/net/momirealms/customcrops/api/object/basic/ConfigManager.java b/src/main/java/net/momirealms/customcrops/api/object/basic/ConfigManager.java index 2e24c6d..376fc01 100644 --- a/src/main/java/net/momirealms/customcrops/api/object/basic/ConfigManager.java +++ b/src/main/java/net/momirealms/customcrops/api/object/basic/ConfigManager.java @@ -62,6 +62,7 @@ public class ConfigManager extends Function { public static int cacheSaveInterval; public static int intervalConsume; public static int intervalWork; + public static int fixRange; public static boolean disableMoistureMechanic; public static boolean preventTrampling; public static boolean onlyInLoadedChunks; @@ -148,6 +149,7 @@ public class ConfigManager extends Function { private void loadOtherSetting(ConfigurationSection section) { enableSkillBonus = section.getBoolean("skill-bonus.enable", false); bonusFormula = section.getString("skill-bonus.formula"); + fixRange = section.getInt("corrupt-fix-range", 4); } public int getCropLimit(String world) { diff --git a/src/main/java/net/momirealms/customcrops/api/object/migrate/MigrateWorld.java b/src/main/java/net/momirealms/customcrops/api/object/migrate/MigrateWorld.java index 3ae0cac..a845870 100644 --- a/src/main/java/net/momirealms/customcrops/api/object/migrate/MigrateWorld.java +++ b/src/main/java/net/momirealms/customcrops/api/object/migrate/MigrateWorld.java @@ -46,7 +46,7 @@ public class MigrateWorld extends Function { @Override @SuppressWarnings("ResultOfMethodCallIgnored") public void init() { - File chunks_folder = ConfigUtils.getChunkFolder(worldName); + File chunks_folder = ConfigUtils.getFile(worldName, "chunks"); if (!chunks_folder.exists()) chunks_folder.mkdirs(); File[] data_files = chunks_folder.listFiles(); if (data_files == null) return; @@ -68,7 +68,7 @@ public class MigrateWorld extends Function { @Override @SuppressWarnings("ResultOfMethodCallIgnored") public void disable() { - File chunks_folder = ConfigUtils.getChunkFolder(worldName); + File chunks_folder = ConfigUtils.getFile(worldName, "chunks"); if (!chunks_folder.exists()) chunks_folder.mkdirs(); for (Map.Entry entry : chunkMap.entrySet()) { ChunkCoordinate chunkCoordinate = entry.getKey(); @@ -194,7 +194,7 @@ public class MigrateWorld extends Function { return chunk.getSprinklerData(simpleLocation); } - public void addWaterToPot(SimpleLocation simpleLocation, int amount, @Nullable String pot_id) { + public void addWaterToPot(SimpleLocation simpleLocation, int amount, @NotNull String pot_id) { CCChunk chunk = chunkMap.get(simpleLocation.getChunkCoordinate()); if (chunk != null) { chunk.addWaterToPot(simpleLocation, amount, pot_id); diff --git a/src/main/java/net/momirealms/customcrops/api/object/pot/PotConfig.java b/src/main/java/net/momirealms/customcrops/api/object/pot/PotConfig.java index 8eadbcc..6878bae 100644 --- a/src/main/java/net/momirealms/customcrops/api/object/pot/PotConfig.java +++ b/src/main/java/net/momirealms/customcrops/api/object/pot/PotConfig.java @@ -109,4 +109,8 @@ public class PotConfig { public String getKey() { return key; } + + public boolean isEnableFertilized() { + return enableFertilized; + } } diff --git a/src/main/java/net/momirealms/customcrops/api/object/world/CCChunk.java b/src/main/java/net/momirealms/customcrops/api/object/world/CCChunk.java index dd2965f..0f8dcdc 100644 --- a/src/main/java/net/momirealms/customcrops/api/object/world/CCChunk.java +++ b/src/main/java/net/momirealms/customcrops/api/object/world/CCChunk.java @@ -130,24 +130,17 @@ public class CCChunk implements Serializable { sprinklerMap.put(simpleLocation, sprinkler); } - public void addWaterToPot(SimpleLocation simpleLocation, int amount, @Nullable String pot_id) { + public void addWaterToPot(SimpleLocation simpleLocation, int amount, @NotNull String pot_id) { Pot pot = potMap.get(simpleLocation); if (pot != null) { if (pot.addWater(amount)) { - CustomCrops.getInstance().getScheduler().runTask(() -> changePotModel(simpleLocation, pot)); + changePotModel(simpleLocation, pot); } return; } - if (pot_id == null) { - Location bukkitLoc = simpleLocation.getBukkitLocation(); - if (bukkitLoc == null) return; - String id = CustomCrops.getInstance().getPlatformInterface().getBlockID(bukkitLoc.getBlock()); - pot_id = CustomCrops.getInstance().getPotManager().getPotKeyByBlockID(id); - if (pot_id == null) return; - } Pot newPot = new Pot(pot_id, null, amount); potMap.put(simpleLocation, newPot); - CustomCrops.getInstance().getScheduler().runTask(() -> changePotModel(simpleLocation, newPot)); + changePotModel(simpleLocation, newPot); } public void addFertilizerToPot(SimpleLocation simpleLocation, Fertilizer fertilizer, @NotNull String pot_id) { @@ -173,6 +166,7 @@ public class CCChunk implements Serializable { public void scheduleSprinklerTask(CCWorld ccWorld, int force) { Random randomGenerator = ThreadLocalRandom.current(); int delay = force == -1 ? ConfigManager.pointGainInterval * 1000 : force * 1000; + delay = Math.max(delay - 10000, 10000); for (SimpleLocation simpleLocation : sprinklerMap.keySet()) { ccWorld.pushSprinklerTask(simpleLocation, randomGenerator.nextInt(delay)); } @@ -189,19 +183,20 @@ public class CCChunk implements Serializable { public void changePotModel(SimpleLocation simpleLocation, Pot pot) { Location location = simpleLocation.getBukkitLocation(); if (location == null) return; - if (CustomCrops.getInstance().getPlatformInterface().removeAnyBlock(location)) { - String replacer = pot.isWet() ? pot.getConfig().getWetPot(pot.getFertilizer()) : pot.getConfig().getDryPot(pot.getFertilizer()); - if (ConfigUtils.isVanillaItem(replacer)) { - Block block = location.getBlock(); - block.setType(Material.valueOf(replacer)); - if (block.getBlockData() instanceof Farmland farmland && ConfigManager.disableMoistureMechanic) { - farmland.setMoisture(pot.isWet() ? farmland.getMaximumMoisture() : 0); - block.setBlockData(farmland); - } - } - else CustomCrops.getInstance().getPlatformInterface().placeNoteBlock(location, replacer); - } else { + if (!CustomCrops.getInstance().getPlatformInterface().removeAnyBlock(location)) { CustomCrops.getInstance().getWorldDataManager().removePotData(simpleLocation); + return; + } + String replacer = pot.isWet() ? pot.getConfig().getWetPot(pot.getFertilizer()) : pot.getConfig().getDryPot(pot.getFertilizer()); + if (ConfigUtils.isVanillaItem(replacer)) { + Block block = location.getBlock(); + block.setType(Material.valueOf(replacer)); + if (block.getBlockData() instanceof Farmland farmland && ConfigManager.disableMoistureMechanic) { + farmland.setMoisture(pot.isWet() ? farmland.getMaximumMoisture() : 0); + block.setBlockData(farmland); + } + } else { + CustomCrops.getInstance().getPlatformInterface().placeNoteBlock(location, replacer); } } } \ No newline at end of file diff --git a/src/main/java/net/momirealms/customcrops/api/object/world/CCWorld.java b/src/main/java/net/momirealms/customcrops/api/object/world/CCWorld.java index a270bf9..3a4c3e1 100644 --- a/src/main/java/net/momirealms/customcrops/api/object/world/CCWorld.java +++ b/src/main/java/net/momirealms/customcrops/api/object/world/CCWorld.java @@ -18,7 +18,6 @@ package net.momirealms.customcrops.api.object.world; import net.momirealms.customcrops.CustomCrops; -import net.momirealms.customcrops.api.customplugin.PlatformInterface; import net.momirealms.customcrops.api.object.Function; import net.momirealms.customcrops.api.object.ItemMode; import net.momirealms.customcrops.api.object.action.Action; @@ -35,7 +34,6 @@ import net.momirealms.customcrops.api.object.fertilizer.SoilRetain; import net.momirealms.customcrops.api.object.fertilizer.SpeedGrow; import net.momirealms.customcrops.api.object.pot.Pot; import net.momirealms.customcrops.api.object.pot.PotConfig; -import net.momirealms.customcrops.api.object.pot.PotManager; import net.momirealms.customcrops.api.object.season.CCSeason; import net.momirealms.customcrops.api.object.season.SeasonData; import net.momirealms.customcrops.api.object.sprinkler.Sprinkler; @@ -68,16 +66,24 @@ public class CCWorld extends Function { private final Reference world; private final ConcurrentHashMap chunkMap; private final ScheduledThreadPoolExecutor schedule; - private long current_day; + private long currentDay; private ScheduledFuture timerTask; private int pointTimer; private int cacheTimer; private int workCounter; private int consumeCounter; - private final HashSet plantToday; - private File chunks_folder; + private final HashSet plantInPoint; + private final ConcurrentHashMap corruptedPot; + private final File chunksFolder; + private final File dateFile; + private final File corruptedFile; + private final CustomCrops plugin; - public CCWorld(World world) { + public CCWorld(World world, CustomCrops plugin) { + this.plugin = plugin; + this.chunksFolder = ConfigUtils.getFile(world, "chunks"); + this.dateFile = ConfigUtils.getFile(world, "data.yml"); + this.corruptedFile = ConfigUtils.getFile(world, "corrupted.yml"); this.world = new WeakReference<>(world); this.worldName = world.getName(); this.chunkMap = new ConcurrentHashMap<>(64); @@ -85,13 +91,15 @@ public class CCWorld extends Function { this.schedule.setMaximumPoolSize(ConfigManager.maxPoolSize); this.schedule.setKeepAliveTime(ConfigManager.keepAliveTime, TimeUnit.SECONDS); this.schedule.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy()); - this.plantToday = new HashSet<>(128); + this.plantInPoint = new HashSet<>(128); + this.corruptedPot = new ConcurrentHashMap<>(128); this.cacheTimer = ConfigManager.cacheSaveInterval; } @Override public void init() { loadDateData(); + loadCorruptedPots(); if (!ConfigManager.onlyInLoadedChunks) { loadAllChunkData(); } @@ -101,15 +109,50 @@ public class CCWorld extends Function { public void disable() { closePool(); saveDateData(); + saveCorruptedPots(); saveAllChunkData(); - CustomCrops.getInstance().getSeasonManager().unloadSeasonData(worldName); + plugin.getSeasonManager().unloadSeasonData(worldName); + } + + public void load() { + this.pointTimer = ConfigManager.pointGainInterval; + this.cacheTimer = ConfigManager.cacheSaveInterval; + this.consumeCounter = ConfigManager.intervalConsume; + this.workCounter = ConfigManager.intervalWork; + this.scheduleTask(); + } + + public void unload() { + if (this.timerTask != null) { + this.timerTask.cancel(false); + this.timerTask = null; + } + } + + public void loadCorruptedPots() { + YamlConfiguration dataFile = ConfigUtils.readData(corruptedFile); + for (Map.Entry entry : dataFile.getValues(false).entrySet()) { + corruptedPot.put(SimpleLocation.getByString(entry.getKey(), worldName), (String) entry.getValue()); + } + } + + public void saveCorruptedPots() { + YamlConfiguration dataFile = new YamlConfiguration(); + for (Map.Entry entry : corruptedPot.entrySet()) { + SimpleLocation simpleLocation = entry.getKey(); + dataFile.set(simpleLocation.getX() + "," + simpleLocation.getY() + "," + simpleLocation.getZ(), entry.getValue()); + } + try { + dataFile.save(corruptedFile); + } catch (IOException e) { + AdventureUtils.consoleMessage("[CustomCrops] Failed to save corrupted data for world: " + worldName); + } } @SuppressWarnings("ResultOfMethodCallIgnored") public void loadAllChunkData() { - chunks_folder = ConfigUtils.getChunkFolder(worldName); - if (!chunks_folder.exists()) chunks_folder.mkdirs(); - File[] data_files = chunks_folder.listFiles(); + if (!chunksFolder.exists()) chunksFolder.mkdirs(); + File[] data_files = chunksFolder.listFiles(); if (data_files == null) return; List outdated = new ArrayList<>(); for (File file : data_files) { @@ -132,32 +175,13 @@ public class CCWorld extends Function { } } - public void loadDateData() { - YamlConfiguration dataFile; - if (ConfigManager.worldFolderPath.equals("")) { - dataFile = ConfigUtils.readData(new File(CustomCrops.getInstance().getDataFolder().getParentFile().getParentFile(), worldName + File.separator + "customcrops" + File.separator + "data.yml")); - } else { - dataFile = ConfigUtils.readData(new File(ConfigManager.worldFolderPath + worldName + File.separator + "customcrops" + File.separator + "data.yml")); - } - if (ConfigManager.enableSeason) { - SeasonData seasonData; - if (dataFile.contains("season") && dataFile.contains("date")) { - seasonData = new SeasonData(worldName, CCSeason.valueOf(dataFile.getString("season")), dataFile.getInt("date")); - } else { - seasonData = new SeasonData(worldName); - } - CustomCrops.getInstance().getSeasonManager().loadSeasonData(seasonData); - } - this.current_day = dataFile.getLong("day", 0); - } - @SuppressWarnings("ResultOfMethodCallIgnored") public void saveAllChunkData() { for (Map.Entry entry : chunkMap.entrySet()) { ChunkCoordinate chunkCoordinate = entry.getKey(); CCChunk chunk = entry.getValue(); String fileName = chunkCoordinate.getFileName() + ".ccdata"; - File file = new File(chunks_folder, fileName); + File file = new File(chunksFolder, fileName); if (chunk.isUseless() && file.exists()) { file.delete(); continue; @@ -173,7 +197,7 @@ public class CCWorld extends Function { public void saveDateData() { YamlConfiguration dataFile = new YamlConfiguration(); if (ConfigManager.enableSeason && !ConfigManager.rsHook) { - SeasonData seasonData = CustomCrops.getInstance().getSeasonManager().getSeasonData(worldName); + SeasonData seasonData = plugin.getSeasonManager().getSeasonData(worldName); if (seasonData == null) { dataFile.set("season", "SPRING"); dataFile.set("date", 1); @@ -182,32 +206,31 @@ public class CCWorld extends Function { dataFile.set("date", seasonData.getDate()); } } - dataFile.set("day", current_day); + dataFile.set("day", currentDay); try { - dataFile.save(new File(CustomCrops.getInstance().getDataFolder().getParentFile().getParentFile(), ConfigManager.worldFolderPath + worldName + File.separator + "customcrops" + File.separator + "data.yml")); + dataFile.save(dateFile); } catch (IOException e) { AdventureUtils.consoleMessage("[CustomCrops] Failed to save season data for world: " + worldName); } } - public void load() { - this.pointTimer = ConfigManager.pointGainInterval; - this.cacheTimer = ConfigManager.cacheSaveInterval; - this.consumeCounter = ConfigManager.intervalConsume; - this.workCounter = ConfigManager.intervalWork; - this.scheduleTask(); - } - - public void unload() { - if (this.timerTask != null) { - this.timerTask.cancel(false); - this.timerTask = null; + public void loadDateData() { + YamlConfiguration dataFile = ConfigUtils.readData(dateFile); + if (ConfigManager.enableSeason) { + SeasonData seasonData; + if (dataFile.contains("season") && dataFile.contains("date")) { + seasonData = new SeasonData(worldName, CCSeason.valueOf(dataFile.getString("season")), dataFile.getInt("date")); + } else { + seasonData = new SeasonData(worldName); + } + plugin.getSeasonManager().loadSeasonData(seasonData); } + this.currentDay = dataFile.getLong("day", 0); } private void scheduleTask() { if (this.timerTask == null) { - this.timerTask = CustomCrops.getInstance().getScheduler().runTaskTimerAsync(() -> { + this.timerTask = plugin.getScheduler().runTaskTimerAsync(() -> { World current = world.get(); if (current != null) { if (ConfigManager.debug) { @@ -227,10 +250,10 @@ public class CCWorld extends Function { } private void tryDayCycleTask(long time, long day) { - if (time < 100 && day != current_day) { - current_day = day; + if (time < 100 && day != currentDay) { + currentDay = day; if (ConfigManager.enableSeason && !ConfigManager.rsHook && ConfigManager.autoSeasonChange) { - CustomCrops.getInstance().getSeasonManager().addDate(worldName); + plugin.getSeasonManager().addDate(worldName); } } if (ConfigManager.cacheSaveInterval != -1) { @@ -239,6 +262,7 @@ public class CCWorld extends Function { if (ConfigManager.debug) Log.info("== Save cache =="); cacheTimer = ConfigManager.cacheSaveInterval; schedule.execute(this::saveDateData); + schedule.execute(this::saveCorruptedPots); schedule.execute(this::saveAllChunkData); } } @@ -255,7 +279,7 @@ public class CCWorld extends Function { public void onReachPoint() { if (ConfigManager.enableScheduleSystem) { if (ConfigManager.debug) Log.info("== Grow point =="); - plantToday.clear(); + plantInPoint.clear(); int size = schedule.getQueue().size(); if (size != 0) { schedule.getQueue().clear(); @@ -264,14 +288,18 @@ public class CCWorld extends Function { for (CCChunk chunk : chunkMap.values()) { chunk.scheduleGrowTask(this, -1); } - workCounter--; - consumeCounter--; - if (consumeCounter <= 0) { + if (workCounter > 0) { + workCounter--; + } + if (consumeCounter > 0) { + consumeCounter--; + } + if (consumeCounter == 0) { consumeCounter = ConfigManager.intervalConsume; if (ConfigManager.debug) Log.info("== Consume time =="); scheduleConsumeTask(-1); } - if (workCounter <= 0) { + if (workCounter == 0) { workCounter = ConfigManager.intervalWork; if (ConfigManager.debug) Log.info("== Work time =="); scheduleSprinklerWork(-1); @@ -285,9 +313,10 @@ public class CCWorld extends Function { @SuppressWarnings("ResultOfMethodCallIgnored") public void unloadChunk(ChunkCoordinate chunkCoordinate) { + if (!ConfigManager.onlyInLoadedChunks) return; CCChunk chunk = chunkMap.remove(chunkCoordinate); if (chunk != null) { - File file = new File(chunks_folder, chunkCoordinate.getFileName() + ".ccdata"); + File file = new File(chunksFolder, chunkCoordinate.getFileName() + ".ccdata"); if (chunk.isUseless() && file.exists()) { file.delete(); return; @@ -302,7 +331,8 @@ public class CCWorld extends Function { @SuppressWarnings("ResultOfMethodCallIgnored") public void loadChunk(ChunkCoordinate chunkCoordinate) { - File file = new File(chunks_folder, chunkCoordinate.getFileName() + ".ccdata"); + if (!ConfigManager.onlyInLoadedChunks) return; + File file = new File(chunksFolder, chunkCoordinate.getFileName() + ".ccdata"); if (file.exists()) { boolean delete = false; try (FileInputStream fis = new FileInputStream(file); ObjectInputStream ois = new ObjectInputStream(fis)) { @@ -335,6 +365,46 @@ public class CCWorld extends Function { schedule.schedule(new ConsumeCheckTask(simpleLocation), delay, TimeUnit.MILLISECONDS); } + public String removeCorrupted(SimpleLocation simpleLocation) { + return corruptedPot.remove(simpleLocation); + } + + public void fixCorruptedData() { + for (SimpleLocation simpleLocation : corruptedPot.keySet()) { + CustomCrops.getInstance().getScheduler().runTaskAsyncLater(new FixTask(simpleLocation), ThreadLocalRandom.current().nextInt(30000)); + } + } + + public class FixTask implements Runnable { + + private final SimpleLocation simpleLocation; + + public FixTask(SimpleLocation simpleLocation) { + this.simpleLocation = simpleLocation; + } + + @Override + public void run() { + String key = corruptedPot.remove(simpleLocation); + PotConfig potConfig = plugin.getPotManager().getPotConfig(key); + if (potConfig == null) return; + Pot pot = getPotData(simpleLocation); + boolean wet = false; + Fertilizer fertilizer = null; + if (pot != null) { + wet = pot.isWet(); + fertilizer = pot.getFertilizer(); + } + Location location = simpleLocation.getBukkitLocation(); + if (location == null) return; + String replacer = wet ? potConfig.getWetPot(fertilizer) : potConfig.getDryPot(fertilizer); + CompletableFuture asyncGetChunk = location.getWorld().getChunkAtAsync(location.getBlockX() >> 4, location.getBlockZ() >> 4); + asyncGetChunk.whenComplete((result, throwable) -> + plugin.getScheduler().runTask(() -> plugin.getPlatformInterface().placeNoteBlock(location, replacer) + )); + } + } + public class ConsumeCheckTask implements Runnable { private final SimpleLocation simpleLocation; @@ -344,25 +414,39 @@ public class CCWorld extends Function { } public void run() { + Pot pot = getPotData(simpleLocation); if (pot == null) return; - if (pot.isWet() && CustomCrops.getInstance().getFertilizerManager().getConfigByFertilizer(pot.getFertilizer()) instanceof SoilRetain soilRetain && soilRetain.canTakeEffect()) { + if (pot.isWet() && plugin.getFertilizerManager().getConfigByFertilizer(pot.getFertilizer()) instanceof SoilRetain soilRetain && soilRetain.canTakeEffect()) { pot.setWater(pot.getWater() + 1); } + if (pot.reduceWater() | pot.reduceFertilizer()) { - PotConfig potConfig = pot.getConfig(); + Fertilizer fertilizer = pot.getFertilizer(); boolean wet = pot.isWet(); if (!wet && fertilizer == null) { removePotData(simpleLocation); } + Location location = simpleLocation.getBukkitLocation(); if (location == null) { return; } - CustomCrops.getInstance().getScheduler().runTask(() -> { - if (CustomCrops.getInstance().getPlatformInterface().removeAnyBlock(location)) { + + PotConfig potConfig = pot.getConfig(); + if (wet && fertilizer == null && !potConfig.isEnableFertilized()) { + return; + } + + CompletableFuture asyncGetChunk = location.getWorld().getChunkAtAsync(location.getBlockX() >> 4, location.getBlockZ() >> 4); + asyncGetChunk.whenComplete((result, throwable) -> + plugin.getScheduler().runTask(() -> { + if (!plugin.getPlatformInterface().removeAnyBlock(location)) { + plugin.getWorldDataManager().removePotData(simpleLocation); + return; + } String replacer = wet ? potConfig.getWetPot(fertilizer) : potConfig.getDryPot(fertilizer); if (ConfigUtils.isVanillaItem(replacer)) { Block block = location.getBlock(); @@ -372,12 +456,10 @@ public class CCWorld extends Function { block.setBlockData(farmland); } } else { - CustomCrops.getInstance().getPlatformInterface().placeNoteBlock(location, replacer); + plugin.getPlatformInterface().placeNoteBlock(location, replacer); } - } else { - CustomCrops.getInstance().getWorldDataManager().removePotData(SimpleLocation.getByBukkitLocation(location)); } - }); + )); } } } @@ -399,10 +481,11 @@ public class CCWorld extends Function { removeSprinklerData(simpleLocation); return; } + int water = sprinkler.getWater(); - if (water < 1) { + sprinkler.setWater(--water); + if (water <= 0) { removeSprinklerData(simpleLocation); - return; } SprinklerAnimation sprinklerAnimation = sprinklerConfig.getSprinklerAnimation(); @@ -416,50 +499,91 @@ public class CCWorld extends Function { } } - sprinkler.setWater(--water); - if (water == 0) { - removeSprinklerData(simpleLocation); - } - int range = sprinklerConfig.getRange(); - PlatformInterface platformInterface = CustomCrops.getInstance().getPlatformInterface(); - PotManager potManager = CustomCrops.getInstance().getPotManager(); - String[] whiteList = sprinklerConfig.getPotWhitelist(); int amount = sprinklerConfig.getWaterFillAbility(); - if (whiteList == null) { - for (int i = -range; i <= range; i++) { - for (int j = -range; j <= range; j++) { - SimpleLocation potLoc = simpleLocation.add(i, -1, j); - Location bLoc = potLoc.getBukkitLocation(); - if (bLoc != null) { - String blockID = platformInterface.getBlockID(potLoc.getBukkitLocation().getBlock()); - String current_id = potManager.getPotKeyByBlockID(blockID); - if (current_id != null) { - addWaterToPot(potLoc, amount, current_id); - } - } - } + int random = sprinklerAnimation == null ? 10000 : sprinklerAnimation.duration() * 1000; + String[] whiteList = sprinklerConfig.getPotWhitelist(); + for (int i = -range; i <= range; i++) { + for (int j = -range; j <= range; j++) { + SimpleLocation potSLoc = simpleLocation.add(i, -1, j); + schedule.schedule(new WaterPotTask(potSLoc, amount, whiteList), ThreadLocalRandom.current().nextInt(random), TimeUnit.MILLISECONDS); } - } else { - for (int i = -range; i <= range; i++) { - outer: - for (int j = -range; j <= range; j++) { - SimpleLocation potLoc = simpleLocation.add(i, -1, j); - Location bLoc = potLoc.getBukkitLocation(); - if (bLoc != null) { - String blockID = platformInterface.getBlockID(bLoc.getBlock()); - String current_id = potManager.getPotKeyByBlockID(blockID); - if (current_id == null) continue; - for (String pot : whiteList) { - if (pot.equals(current_id)) { - addWaterToPot(potLoc, amount, current_id); - continue outer; + } + } + } + + public class WaterPotTask implements Runnable { + + @NotNull + private final SimpleLocation simpleLocation; + private final int amount; + @Nullable + private final String[] whitelist; + + public WaterPotTask(@NotNull SimpleLocation simpleLocation, int amount, @Nullable String[] whitelist) { + this.simpleLocation = simpleLocation; + this.amount = amount; + this.whitelist = whitelist; + } + + @Override + public void run() { + Location location = simpleLocation.getBukkitLocation(); + if (location == null) return; + CompletableFuture asyncGetChunk = location.getWorld().getChunkAtAsync(location.getBlockX() >> 4, location.getBlockZ() >> 4); + asyncGetChunk.whenComplete((result, throwable) -> + plugin.getScheduler().runTask(() -> { + String blockID = plugin.getPlatformInterface().getBlockID(location.getBlock()); + String potKey = plugin.getPotManager().getPotKeyByBlockID(blockID); + if (potKey != null) { + if (whitelist != null) { + for (String pot : whitelist) { + if (pot.equals(potKey)) { + addWaterToPot(simpleLocation, amount, potKey); + break; + } + } + } else { + addWaterToPot(simpleLocation, amount, potKey); + } + } else if (blockID.equals("NOTE_BLOCK")) { + // Only ItemsAdder can go to this step + Pot pot = getPotData(simpleLocation); + if (pot != null) { + // mark it as glitched + potKey = pot.getPotKey(); + corruptedPot.put(simpleLocation, potKey); + if (ConfigManager.debug) AdventureUtils.consoleMessage("[CustomCrops] Trying to fix corrupted pot found at: " + simpleLocation); + + if (whitelist == null) { + pot.addWater(amount); + } else { + for (String potID : whitelist) { + if (potID.equals(potKey)) { + pot.addWater(amount); + break; + } + } + } + + // only custom blocks would corrupt + String replacer = pot.getConfig().getWetPot(pot.getFertilizer()); + plugin.getPlatformInterface().placeNoteBlock(location, replacer); + } else { + potKey = corruptedPot.get(simpleLocation); + if (potKey != null) { + PotConfig potConfig = plugin.getPotManager().getPotConfig(potKey); + if (potConfig != null) { + String replacer = potConfig.getDryPot(null); + plugin.getPlatformInterface().placeNoteBlock(location, replacer); + } else { + corruptedPot.remove(simpleLocation); } } } } } - } + )); } } @@ -503,9 +627,9 @@ public class CCWorld extends Function { } int points = 1; - Pot pot = CustomCrops.getInstance().getWorldDataManager().getPotData(simpleLocation.add(0,-1,0)); + Pot pot = plugin.getWorldDataManager().getPotData(simpleLocation.add(0,-1,0)); if (pot != null) { - FertilizerConfig fertilizerConfig = CustomCrops.getInstance().getFertilizerManager().getConfigByFertilizer(pot.getFertilizer()); + FertilizerConfig fertilizerConfig = plugin.getFertilizerManager().getConfigByFertilizer(pot.getFertilizer()); if (fertilizerConfig instanceof SpeedGrow speedGrow) { points += speedGrow.getPointBonus(); } @@ -564,9 +688,9 @@ public class CCWorld extends Function { return chunk.isEntitiesLoaded(); }); loadEntities.whenComplete((result, throwable) -> - CustomCrops.getInstance().getScheduler().runTask(() -> { - if (CustomCrops.getInstance().getPlatformInterface().removeCustomItem(location, itemMode)) { - CustomCrops.getInstance().getPlatformInterface().placeCustomItem(location, finalNextModel, itemMode); + plugin.getScheduler().runTask(() -> { + if (plugin.getPlatformInterface().removeCustomItem(location, itemMode)) { + plugin.getPlatformInterface().placeCustomItem(location, finalNextModel, itemMode); } else { removeCropData(simpleLocation); } @@ -574,9 +698,9 @@ public class CCWorld extends Function { } else { asyncGetChunk.whenComplete((result, throwable) -> - CustomCrops.getInstance().getScheduler().runTask(() -> { - if (CustomCrops.getInstance().getPlatformInterface().removeCustomItem(location, itemMode)) { - CustomCrops.getInstance().getPlatformInterface().placeCustomItem(location, finalNextModel, itemMode); + plugin.getScheduler().runTask(() -> { + if (plugin.getPlatformInterface().removeCustomItem(location, itemMode)) { + plugin.getPlatformInterface().placeCustomItem(location, finalNextModel, itemMode); } else { removeCropData(simpleLocation); } @@ -613,11 +737,11 @@ public class CCWorld extends Function { } private void growIfNotDuplicated(SimpleLocation simpleLocation) { - if (plantToday.contains(simpleLocation)) { + if (plantInPoint.contains(simpleLocation)) { return; } pushCropTask(simpleLocation, ThreadLocalRandom.current().nextInt(ConfigManager.pointGainInterval * 1000)); - plantToday.add(simpleLocation); + plantInPoint.add(simpleLocation); } public GrowingCrop getCropData(SimpleLocation simpleLocation) { @@ -766,4 +890,9 @@ public class CCWorld extends Function { } }); } + + @Nullable + public String getCorruptedPotOriginalKey(SimpleLocation simpleLocation) { + return corruptedPot.get(simpleLocation); + } } \ No newline at end of file diff --git a/src/main/java/net/momirealms/customcrops/api/object/world/SimpleLocation.java b/src/main/java/net/momirealms/customcrops/api/object/world/SimpleLocation.java index d8e5132..7fd959b 100644 --- a/src/main/java/net/momirealms/customcrops/api/object/world/SimpleLocation.java +++ b/src/main/java/net/momirealms/customcrops/api/object/world/SimpleLocation.java @@ -17,7 +17,6 @@ package net.momirealms.customcrops.api.object.world; -import org.apache.commons.lang3.StringUtils; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.World; @@ -115,7 +114,7 @@ public class SimpleLocation implements Serializable { } public static SimpleLocation getByString(String location, String world) { - String[] loc = StringUtils.split(location, ","); + String[] loc = location.split(","); return new SimpleLocation(world, Integer.parseInt(loc[0]), Integer.parseInt(loc[1]), Integer.parseInt(loc[2])); } diff --git a/src/main/java/net/momirealms/customcrops/api/object/world/WorldDataManager.java b/src/main/java/net/momirealms/customcrops/api/object/world/WorldDataManager.java index feeebc3..abf4512 100644 --- a/src/main/java/net/momirealms/customcrops/api/object/world/WorldDataManager.java +++ b/src/main/java/net/momirealms/customcrops/api/object/world/WorldDataManager.java @@ -72,7 +72,7 @@ public class WorldDataManager extends Function { public void loadWorld(World world) { if (!isWorldAllowed(world)) return; - CCWorld ccWorld = new CCWorld(world); + CCWorld ccWorld = new CCWorld(world, plugin); ccWorld.init(); ccWorld.load(); ccWorld.onReachPoint(); @@ -262,4 +262,28 @@ public class WorldDataManager extends Function { ccWorld.unloadChunk(new ChunkCoordinate(chunk.getX(), chunk.getZ())); } } + + @Nullable + public String getCorruptedPotOriginalKey(SimpleLocation simpleLocation) { + CCWorld ccWorld = worldMap.get(simpleLocation.getWorldName()); + if (ccWorld != null) { + return ccWorld.getCorruptedPotOriginalKey(simpleLocation); + } + return null; + } + + public String removeCorrupted(SimpleLocation simpleLocation) { + CCWorld ccWorld = worldMap.get(simpleLocation.getWorldName()); + if (ccWorld != null) { + return ccWorld.removeCorrupted(simpleLocation); + } + return null; + } + + public void fixCorruptedData(String world) { + CCWorld ccWorld = worldMap.get(world); + if (ccWorld != null) { + ccWorld.fixCorruptedData(); + } + } } diff --git a/src/main/java/net/momirealms/customcrops/api/object/world/WorldListener.java b/src/main/java/net/momirealms/customcrops/api/object/world/WorldListener.java index 388fee7..2a88caf 100644 --- a/src/main/java/net/momirealms/customcrops/api/object/world/WorldListener.java +++ b/src/main/java/net/momirealms/customcrops/api/object/world/WorldListener.java @@ -17,7 +17,6 @@ package net.momirealms.customcrops.api.object.world; -import net.momirealms.customcrops.api.object.basic.ConfigManager; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.world.ChunkLoadEvent; @@ -45,13 +44,12 @@ public class WorldListener implements Listener { @EventHandler public void onChunkLoad(ChunkLoadEvent event) { - if (!ConfigManager.onlyInLoadedChunks || event.isNewChunk()) return; + if (event.isNewChunk()) return; worldManager.loadChunk(event.getChunk(), event.getWorld()); } @EventHandler public void onChunkUnload(ChunkUnloadEvent event) { - if (!ConfigManager.onlyInLoadedChunks) return; worldManager.unloadChunk(event.getChunk(), event.getWorld()); } } diff --git a/src/main/java/net/momirealms/customcrops/api/util/ConfigUtils.java b/src/main/java/net/momirealms/customcrops/api/util/ConfigUtils.java index 8004f30..6e5ba09 100644 --- a/src/main/java/net/momirealms/customcrops/api/util/ConfigUtils.java +++ b/src/main/java/net/momirealms/customcrops/api/util/ConfigUtils.java @@ -45,6 +45,7 @@ import net.momirealms.customcrops.api.object.requirement.*; import net.momirealms.customcrops.api.object.season.CCSeason; import net.momirealms.customcrops.helper.Log; import org.bukkit.Particle; +import org.bukkit.World; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.MemorySection; import org.bukkit.configuration.file.YamlConfiguration; @@ -473,13 +474,23 @@ public class ConfigUtils { return (a << 24) | (r << 16) | (g << 8) | b; } - public static File getChunkFolder(String world) { - File chunks_folder; + public static File getFile(String world, String fileName) { + File file; if (ConfigManager.worldFolderPath.equals("")) { - chunks_folder = new File(CustomCrops.getInstance().getDataFolder().getParentFile().getParentFile(), world + File.separator + "customcrops" + File.separator + "chunks"); + file = new File(CustomCrops.getInstance().getDataFolder().getParentFile().getParentFile(), world + File.separator + "customcrops" + File.separator + fileName); } else { - chunks_folder = new File(ConfigManager.worldFolderPath, world + File.separator + "customcrops" + File.separator + "chunks"); + file = new File(ConfigManager.worldFolderPath, world + File.separator + "customcrops" + File.separator + fileName); } - return chunks_folder; + return file; + } + + public static File getFile(World world, String fileName) { + File file; + if (ConfigManager.worldFolderPath.equals("")) { + file = new File(world.getWorldFolder(), "customcrops" + File.separator + fileName); + } else { + file = new File(ConfigManager.worldFolderPath, world + File.separator + "customcrops" + File.separator + fileName); + } + return file; } } \ No newline at end of file diff --git a/src/main/java/net/momirealms/customcrops/command/CustomCropsCommand.java b/src/main/java/net/momirealms/customcrops/command/CustomCropsCommand.java index c774e97..ed65e13 100644 --- a/src/main/java/net/momirealms/customcrops/command/CustomCropsCommand.java +++ b/src/main/java/net/momirealms/customcrops/command/CustomCropsCommand.java @@ -30,6 +30,7 @@ public class CustomCropsCommand extends AbstractMainCommand { regSubCommand(ForceCommand.INSTANCE); regSubCommand(MigrateCommand.INSTANCE); regSubCommand(ConvertCommand.INSTANCE); + regSubCommand(FixCommand.INSTANCE); // regSubCommand(CorruptionTest.INSTANCE); // regSubCommand(PerformanceTest.INSTANCE); } diff --git a/src/main/java/net/momirealms/customcrops/command/subcmd/FixCommand.java b/src/main/java/net/momirealms/customcrops/command/subcmd/FixCommand.java new file mode 100644 index 0000000..8efdcd1 --- /dev/null +++ b/src/main/java/net/momirealms/customcrops/command/subcmd/FixCommand.java @@ -0,0 +1,45 @@ +/* + * 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.command.subcmd; + +import net.momirealms.customcrops.CustomCrops; +import net.momirealms.customcrops.api.object.basic.MessageManager; +import net.momirealms.customcrops.api.util.AdventureUtils; +import net.momirealms.customcrops.command.AbstractSubCommand; +import org.bukkit.command.CommandSender; + +import java.util.List; + +public class FixCommand extends AbstractSubCommand { + + public static final FixCommand INSTANCE = new FixCommand(); + + public FixCommand() { + super("fixcorrupted"); + } + + @Override + public boolean onCommand(CommandSender sender, List args) { + if (lackArgs(sender, 1, args.size())) return true; + + String world = args.get(0); + CustomCrops.getInstance().getWorldDataManager().fixCorruptedData(world); + AdventureUtils.sendMessage(sender, MessageManager.prefix + "Fixing would be ongoing in next 30s"); + return true; + } +} diff --git a/src/main/java/net/momirealms/customcrops/command/subcmd/MigrateCommand.java b/src/main/java/net/momirealms/customcrops/command/subcmd/MigrateCommand.java index 836212f..46453e3 100644 --- a/src/main/java/net/momirealms/customcrops/command/subcmd/MigrateCommand.java +++ b/src/main/java/net/momirealms/customcrops/command/subcmd/MigrateCommand.java @@ -29,7 +29,6 @@ import net.momirealms.customcrops.api.object.season.SeasonData; import net.momirealms.customcrops.api.object.world.SimpleLocation; import net.momirealms.customcrops.api.util.AdventureUtils; import net.momirealms.customcrops.command.AbstractSubCommand; -import org.apache.commons.lang3.StringUtils; import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import org.bukkit.configuration.file.YamlConfiguration; @@ -123,7 +122,7 @@ public class MigrateCommand extends AbstractSubCommand { JsonArray jsonArray = jsonObject.getAsJsonArray("pot"); for (JsonElement jsonElement : jsonArray) { String loc = jsonElement.getAsString(); - String[] locs = StringUtils.split(loc, ","); + String[] locs = loc.split(","); SimpleLocation simpleLocation = new SimpleLocation(worldName, Integer.parseInt(locs[0]), Integer.parseInt(locs[1]), Integer.parseInt(locs[2])); migrateWorld.addWaterToPot(simpleLocation, 1, "default"); } @@ -136,7 +135,7 @@ public class MigrateCommand extends AbstractSubCommand { YamlConfiguration data = YamlConfiguration.loadConfiguration(new File(ccDataFolder, "fertilizers.yml")); for (String key : data.getKeys(false)) { - String[] loc = StringUtils.split(key, ","); + String[] loc = key.split(","); SimpleLocation location = new SimpleLocation(worldName, Integer.parseInt(loc[0]), Integer.parseInt(loc[1]), Integer.parseInt(loc[2])); String fertilizer = data.getString(key + ".type"); int times = data.getInt(key + ".times"); @@ -158,7 +157,7 @@ public class MigrateCommand extends AbstractSubCommand { JsonArray jsonArray = en.getValue().getAsJsonArray(); int size = jsonArray.size(); for (int i = 0; i < size; i++) { - String[] loc = StringUtils.split(jsonArray.get(i).getAsString(), ","); + String[] loc = jsonArray.get(i).getAsString().split(","); migrateWorld.addScarecrow(new SimpleLocation(worldName, Integer.parseInt(loc[0]), Integer.parseInt(loc[1]), Integer.parseInt(loc[2]))); } } @@ -177,7 +176,7 @@ public class MigrateCommand extends AbstractSubCommand { String stageStr = crop.substring(crop.indexOf("_stage_") + 7); int stage = Integer.parseInt(stageStr); growingCrop = new GrowingCrop(crop.substring(0, crop.indexOf("_stage_")), stage); - String[] loc = StringUtils.split(entry.getKey(), ","); + String[] loc = entry.getKey().split(","); SimpleLocation simpleLocation = new SimpleLocation(worldName, Integer.parseInt(loc[0]), Integer.parseInt(loc[1]), Integer.parseInt(loc[2])); migrateWorld.addCropData(simpleLocation, growingCrop); } diff --git a/src/main/java/net/momirealms/customcrops/helper/LibraryLoader.java b/src/main/java/net/momirealms/customcrops/helper/LibraryLoader.java index 932e553..db32c78 100644 --- a/src/main/java/net/momirealms/customcrops/helper/LibraryLoader.java +++ b/src/main/java/net/momirealms/customcrops/helper/LibraryLoader.java @@ -28,7 +28,6 @@ package net.momirealms.customcrops.helper; import com.google.common.base.Supplier; import com.google.common.base.Suppliers; import net.momirealms.customcrops.CustomCrops; -import org.apache.commons.lang3.StringUtils; import java.io.File; import java.io.InputStream; @@ -110,7 +109,7 @@ public final class LibraryLoader { File serverDir = pluginDataFolder.getParentFile().getParentFile(); File helperDir = new File(serverDir, "libraries"); - String[] split = StringUtils.split(dependency.groupId(), "."); + String[] split = dependency.groupId().split("\\."); File jarDir; StringJoiner stringJoiner = new StringJoiner(File.separator); for (String str : split) { diff --git a/src/main/java/net/momirealms/customcrops/integration/papi/SeasonPapi.java b/src/main/java/net/momirealms/customcrops/integration/papi/SeasonPapi.java index abe6175..a624740 100644 --- a/src/main/java/net/momirealms/customcrops/integration/papi/SeasonPapi.java +++ b/src/main/java/net/momirealms/customcrops/integration/papi/SeasonPapi.java @@ -19,6 +19,7 @@ package net.momirealms.customcrops.integration.papi; import me.clip.placeholderapi.expansion.PlaceholderExpansion; import net.momirealms.customcrops.CustomCrops; +import net.momirealms.customcrops.api.object.basic.ConfigManager; import org.bukkit.OfflinePlayer; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; @@ -26,7 +27,7 @@ import org.jetbrains.annotations.Nullable; public class SeasonPapi extends PlaceholderExpansion { - private CustomCrops plugin; + private final CustomCrops plugin; public SeasonPapi(CustomCrops plugin) { this.plugin = plugin; @@ -68,6 +69,11 @@ public class SeasonPapi extends PlaceholderExpansion { if (online_player == null) return null; return String.valueOf(plugin.getIntegrationManager().getSeasonInterface().getDate(player.getPlayer().getWorld().getName())); } + case "daysleft" -> { + Player online_player = player.getPlayer(); + if (online_player == null) return null; + return String.valueOf(1 + ConfigManager.seasonInterval - plugin.getIntegrationManager().getSeasonInterface().getDate(player.getPlayer().getWorld().getName())); + } } } case 2 -> { @@ -78,6 +84,9 @@ public class SeasonPapi extends PlaceholderExpansion { case "date" -> { return String.valueOf(plugin.getIntegrationManager().getSeasonInterface().getDate(split[1])); } + case "daysleft" -> { + return String.valueOf(1 + ConfigManager.seasonInterval - plugin.getIntegrationManager().getSeasonInterface().getDate(split[1])); + } } } } diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 36c08c3..2e6f64f 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -25,11 +25,12 @@ schedule-system: enable: true # The average interval for a crop to gain one point (measured in seconds) # 平均每个农作物获得一生长点的时间间隔(秒) - point-gain-interval: 600 - # Water amount and fertilizer would reduce every two points are gained - # As the default point-gain-interval is 600s, so here it would be 1200s(20min = a minecraft day) - # 默认每两个生长点进行一次水分、肥料消耗/洒水器工作 - consume-water-fertilizer-every-x-point: 2 + point-gain-interval: 300 + # Water amount and fertilizer would reduce every 4 points are gained + # set it to -1 if you don't want CustomCrops to control consumption/sprinkler tasks + # 默认每四个生长点进行一次水分、肥料消耗/洒水器工作 + # 设置为-1以禁用CustomCrops对水分、肥料消耗/洒水器任务的掌管 + consume-water-fertilizer-every-x-point: 4 # Sprinkler would work every two points are gained sprinkler-work-every-x-point: 2 # Save cache to file interval (seconds) @@ -65,7 +66,7 @@ optimization: mechanics: # Does the system only work in loaded chunks (Requires you to stop the server before changing this setting) # 插件是否只在加载中的区块工作 (需要关闭服务器再设置此项) - only-work-in-loaded-chunks: false + only-work-in-loaded-chunks: true # 17/2/1 = 85%/10%/5% # 2/2/1 = 40%/40%/20% default-quality-ratio: 17/2/1 @@ -112,4 +113,6 @@ other-settings: formula: '{base} + {level} * 0.01' # MMOCore profession name # MMOCore职业名 - MMOCore-profession-name: 'farmer' \ No newline at end of file + MMOCore-profession-name: 'farmer' + # Fixed corrupted pots when interacting + corrupt-fix-range: 4 \ No newline at end of file