From 4f92c268e62d4f1664292a5ebf1fbbd56dcff616 Mon Sep 17 00:00:00 2001 From: Xiao-MoMi <70987828+Xiao-MoMi@users.noreply.github.com> Date: Thu, 20 Apr 2023 17:20:16 +0800 Subject: [PATCH] 3.0.1 --- build.gradle | 2 +- .../api/customplugin/PlatformManager.java | 7 +- .../api/object/basic/ConfigManager.java | 4 +- .../customcrops/api/object/world/CCWorld.java | 16 +- .../command/CustomCropsCommand.java | 1 + .../command/subcmd/ConvertCommand.java | 183 ++++++++++++++++++ .../command/subcmd/MigrateCommand.java | 12 ++ src/main/resources/config.yml | 11 +- .../resources/messages/messages_spanish.yml | 24 +++ src/main/resources/plugin.yml | 3 + 10 files changed, 258 insertions(+), 5 deletions(-) create mode 100644 src/main/java/net/momirealms/customcrops/command/subcmd/ConvertCommand.java diff --git a/build.gradle b/build.gradle index 26f9d88..a9c758d 100644 --- a/build.gradle +++ b/build.gradle @@ -4,7 +4,7 @@ plugins { } group = 'net.momirealms' -version = '3.0.0' +version = '3.0.1' 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 3583a0f..b0f4adb 100644 --- a/src/main/java/net/momirealms/customcrops/api/customplugin/PlatformManager.java +++ b/src/main/java/net/momirealms/customcrops/api/customplugin/PlatformManager.java @@ -716,8 +716,13 @@ public class PlatformManager extends Function { WaterAmountHologram waterAmountHologram = potConfig.getWaterAmountHologram(); if (waterAmountHologram != null && potData != null) { + double offset = 0; + StageConfig stageConfig = plugin.getCropManager().getStageConfig(plugin.getPlatformInterface().getAnyItemIDAt(location.clone().add(0,1,0))); + if (stageConfig != null) { + offset = stageConfig.getOffsetCorrection(); + } plugin.getHologramManager().showHologram(player, - location.clone().add(0.5,waterAmountHologram.getOffset(),0.5), + location.clone().add(0.5,waterAmountHologram.getOffset() + offset,0.5), AdventureUtils.getComponentFromMiniMessage(waterAmountHologram.getContent(potData.getWater(), potConfig.getMaxStorage())), waterAmountHologram.getDuration() * 1000, waterAmountHologram.getMode(), 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 28ce79e..adb0972 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 @@ -56,6 +56,7 @@ public class ConfigManager extends Function { public static String referenceWorld; public static boolean enableLimitation; public static int maxCropPerChunk; + public static int cacheSaveInterval; public static boolean setUpMode; private final CustomCrops plugin; @@ -95,11 +96,12 @@ public class ConfigManager extends Function { } private void loadScheduleSystem(ConfigurationSection section) { - enableScheduleSystem = section.getBoolean("enable"); + enableScheduleSystem = section.getBoolean("default-schedule"); pointGainInterval = section.getInt("point-gain-interval", 1000); corePoolSize = section.getInt("thread-pool-settings.corePoolSize", 2); maxPoolSize = section.getInt("thread-pool-settings.maximumPoolSize", 4); keepAliveTime = section.getInt("thread-pool-settings.keepAliveTime", 10); + cacheSaveInterval = section.getInt("cache-save-interval", 7200); } private void loadMechanic(ConfigurationSection section) { 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 8e7337b..19901da 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.object.CrowTask; import net.momirealms.customcrops.api.object.Function; import net.momirealms.customcrops.api.object.ItemMode; import net.momirealms.customcrops.api.object.action.Action; @@ -74,6 +73,7 @@ public class CCWorld extends Function { private long lastConsumeDay; private ScheduledFuture timerTask; private int timer; + private int cacheTimer; public CCWorld(World world) { this.world = new WeakReference<>(world); @@ -93,6 +93,7 @@ public class CCWorld extends Function { this.consumeTaskPool.setMaxTotal(10); this.consumeTaskPool.setMinIdle(1); this.timer = 10; + this.cacheTimer = ConfigManager.cacheSaveInterval; } @Override @@ -133,6 +134,10 @@ public class CCWorld extends Function { @SuppressWarnings("ResultOfMethodCallIgnored") public void disable() { closePool(); + saveCache(); + } + + public void saveCache() { File chunks_folder = new File(CustomCrops.getInstance().getDataFolder().getParentFile().getParentFile(), ConfigManager.worldFolderPath + worldName + File.separator + "customcrops" + File.separator + "chunks"); if (!chunks_folder.exists()) chunks_folder.mkdirs(); for (Map.Entry entry : chunkMap.entrySet()) { @@ -203,8 +208,17 @@ public class CCWorld extends Function { chunk.scheduleGrowTask(this); } } + if (ConfigManager.cacheSaveInterval != -1) { + cacheTimer--; + if (cacheTimer <= 0) { + if (ConfigManager.debug) Log.info("== Save cache =="); + cacheTimer = ConfigManager.cacheSaveInterval; + schedule.execute(this::saveCache); + } + } } else { + AdventureUtils.consoleMessage("[CustomCrops] Unexpected world: " + worldName + " unloaded. Shutdown the schedule."); this.schedule.shutdown(); } }, 1000, 1000L); diff --git a/src/main/java/net/momirealms/customcrops/command/CustomCropsCommand.java b/src/main/java/net/momirealms/customcrops/command/CustomCropsCommand.java index f19eb8b..13c15c4 100644 --- a/src/main/java/net/momirealms/customcrops/command/CustomCropsCommand.java +++ b/src/main/java/net/momirealms/customcrops/command/CustomCropsCommand.java @@ -29,6 +29,7 @@ public class CustomCropsCommand extends AbstractMainCommand { regSubCommand(SetDateCommand.INSTANCE); regSubCommand(ForceCommand.INSTANCE); regSubCommand(MigrateCommand.INSTANCE); + regSubCommand(ConvertCommand.INSTANCE); // regSubCommand(PerformanceTest.INSTANCE); } } diff --git a/src/main/java/net/momirealms/customcrops/command/subcmd/ConvertCommand.java b/src/main/java/net/momirealms/customcrops/command/subcmd/ConvertCommand.java new file mode 100644 index 0000000..5329011 --- /dev/null +++ b/src/main/java/net/momirealms/customcrops/command/subcmd/ConvertCommand.java @@ -0,0 +1,183 @@ +package net.momirealms.customcrops.command.subcmd; + +import net.momirealms.customcrops.CustomCrops; +import net.momirealms.customcrops.api.util.AdventureUtils; +import net.momirealms.customcrops.command.AbstractSubCommand; +import org.bukkit.command.CommandSender; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.YamlConfiguration; + +import java.io.File; +import java.io.IOException; +import java.util.HashSet; +import java.util.List; + +public class ConvertCommand extends AbstractSubCommand { + + public static final ConvertCommand INSTANCE = new ConvertCommand(); + + private final HashSet confirm; + + public ConvertCommand() { + super("convert"); + confirm = new HashSet<>(); + } + + @Override + public boolean onCommand(CommandSender sender, List args) { + if (lackArgs(sender, 1, args.size())) return true; + + if (!confirm.contains(sender.getName())) { + confirm.add(sender.getName()); + AdventureUtils.sendMessage(sender, "[CustomCrops] Type the command again to confirm."); + return true; + } + + confirm.remove(sender.getName()); + + String mode = args.get(0).toUpperCase(); + + String platform = CustomCrops.getInstance().getPlatform().name().toLowerCase(); + YamlConfiguration oldConfig = YamlConfiguration.loadConfiguration(new File(CustomCrops.getInstance().getDataFolder(), "crops_" + platform + ".yml")); + String namespace = oldConfig.getString("namespace", ""); + if (!namespace.equals("")) namespace = namespace + ":"; + + for (String crop : oldConfig.getKeys(false)) { + + ConfigurationSection oldSection = oldConfig.getConfigurationSection(crop); + if (oldSection == null) continue; + int max_stage = oldSection.getInt("max-stage"); + + YamlConfiguration newConfig = new YamlConfiguration(); + ConfigurationSection newSection = newConfig.createSection(crop); + newSection.set("type", mode); + newSection.set("pot-whitelist", List.of("default")); + newSection.set("seed", namespace + crop + "_seeds"); + newSection.set("max-points", max_stage -1); + + ConfigurationSection pointSec = newSection.createSection("points"); + for (int i = 0; i < max_stage; i++) { + pointSec.set(i + ".model", namespace + crop + "_stage_" + (i+1)); + } + + if (oldSection.contains("gigantic-crop")) { + newSection.set("max-points", max_stage); + boolean isBlock = oldSection.contains("gigantic-crop.block"); + newSection.set("points." + max_stage + ".events.grow.action_gigantic.type", "variation"); + newSection.set("points." + max_stage + ".events.grow.action_gigantic.value.gigantic.item", isBlock ? oldSection.getString("gigantic-crop.block") : oldSection.getString("gigantic-crop.furniture")); + newSection.set("points." + max_stage + ".events.grow.action_gigantic.value.gigantic.type", isBlock ? "TRIPWIRE" : "ITEM_FRAME"); + newSection.set("points." + max_stage + ".events.grow.action_gigantic.value.gigantic.chance", oldSection.getDouble("gigantic-crop.chance")); + } + + if (oldSection.contains("return")) { + newSection.set("points." + (max_stage-1) + ".events.interact-by-hand.action_break.type", "break"); + newSection.set("points." + (max_stage-1) + ".events.interact-by-hand.action_break.value", true); + newSection.set("points." + (max_stage-1) + ".events.interact-by-hand.action_replant.type", "replant"); + newSection.set("points." + (max_stage-1) + ".events.interact-by-hand.action_replant.value.point", Integer.parseInt(oldSection.getString("return", "1").substring(oldSection.getString("return", "1").length()-1)) - 1); + newSection.set("points." + (max_stage-1) + ".events.interact-by-hand.action_replant.value.crop", crop); + newSection.set("points." + (max_stage-1) + ".events.interact-by-hand.action_replant.value.model", oldSection.getString("return")); + } + + if (oldSection.contains("season")) { + List allSeason = new java.util.ArrayList<>(List.of("spring", "autumn", "summer", "winter")); + for (String allow : oldSection.getStringList("season")) { + allSeason.remove(allow.toLowerCase()); + } + newSection.set("requirements.plant.requirement_season.type", "season"); + newSection.set("requirements.plant.requirement_season.value", oldSection.getStringList("season")); + newSection.set("requirements.plant.requirement_season.message", "It's not a good season to plant " + crop); + + newSection.set("death-conditions.unsuitable_season.model", namespace + "crop_stage_death"); + newSection.set("death-conditions.unsuitable_season.conditions.condition_season.type", "unsuitable_season"); + newSection.set("death-conditions.unsuitable_season.conditions.condition_season.value", allSeason); + } + + if (oldSection.contains("quality-loots")) { + ConfigurationSection qualitySec = oldSection.getConfigurationSection("quality-loots"); + assert qualitySec != null; + String[] split = qualitySec.getString("amount").split("~"); + int min = Integer.parseInt(split[0]); + int max = Integer.parseInt(split[1]); + newSection.set("points." + (max_stage-1) + ".events.break.action_drop.type", "drop-items"); + newSection.set("points." + (max_stage-1) + ".events.break.action_drop.value.quality-crops.min", min); + newSection.set("points." + (max_stage-1) + ".events.break.action_drop.value.quality-crops.max", max); + newSection.set("points." + (max_stage-1) + ".events.break.action_drop.value.quality-crops.items.1", qualitySec.getString("quality.1")); + newSection.set("points." + (max_stage-1) + ".events.break.action_drop.value.quality-crops.items.2", qualitySec.getString("quality.2")); + newSection.set("points." + (max_stage-1) + ".events.break.action_drop.value.quality-crops.items.3", qualitySec.getString("quality.3")); + } + + if (oldSection.contains("other-loots")) { + ConfigurationSection lootSec = oldSection.getConfigurationSection("other-loots"); + assert lootSec != null; + for (String loot_key : lootSec.getKeys(false)) { + newSection.set("points." + (max_stage-1) + ".events.break.action_drop.value.other-items." + loot_key + ".item", lootSec.getString(loot_key + ".item")); + newSection.set("points." + (max_stage-1) + ".events.break.action_drop.value.other-items." + loot_key + ".min", lootSec.getInt(loot_key + ".min_amount")); + newSection.set("points." + (max_stage-1) + ".events.break.action_drop.value.other-items." + loot_key + ".max", lootSec.getInt(loot_key + ".max_amount")); + newSection.set("points." + (max_stage-1) + ".events.break.action_drop.value.other-items." + loot_key + ".chance", lootSec.getDouble(loot_key + ".chance")); + } + } + + if (oldSection.contains("harvest-actions.messages")) { + newSection.set("points." + (max_stage-1) + ".events.break.action_message.type", "message"); + newSection.set("points." + (max_stage-1) + ".events.break.action_message.value", oldSection.getStringList("harvest-actions.messages")); + newSection.set("points." + (max_stage-1) + ".events.break.action_message.chance", oldSection.getDouble("harvest-actions.messages-chance", 1)); + } + + if (oldSection.contains("harvest-actions.commands")) { + newSection.set("points." + (max_stage-1) + ".events.break.action_command.type", "command"); + newSection.set("points." + (max_stage-1) + ".events.break.action_command.value", oldSection.getStringList("harvest-actions.commands")); + newSection.set("points." + (max_stage-1) + ".events.break.action_command.chance", oldSection.getDouble("harvest-actions.commands-chance", 1)); + } + + if (oldSection.contains("harvest-actions.xp")) { + newSection.set("points." + (max_stage-1) + ".events.break.action_exp.type", "exp"); + newSection.set("points." + (max_stage-1) + ".events.break.action_exp.value", oldSection.getInt("harvest-actions.xp")); + newSection.set("points." + (max_stage-1) + ".events.break.action_exp.chance", oldSection.getDouble("harvest-actions.xp-chance", 1)); + } + + if (oldSection.contains("harvest-actions.skill-xp")) { + newSection.set("points." + (max_stage-1) + ".events.break.action_skill_xp.type", "skill-xp"); + newSection.set("points." + (max_stage-1) + ".events.break.action_skill_xp.value", oldSection.getInt("harvest-actions.skill-xp")); + newSection.set("points." + (max_stage-1) + ".events.break.action_skill_xp.chance", oldSection.getDouble("harvest-actions.skill-xp-chance", 1)); + } + + if (oldSection.contains("harvest-actions.job-xp")) { + newSection.set("points." + (max_stage-1) + ".events.break.action_job_xp.type", "job-xp"); + newSection.set("points." + (max_stage-1) + ".events.break.action_job_xp.value", oldSection.getInt("harvest-actions.job-xp")); + newSection.set("points." + (max_stage-1) + ".events.break.action_job_xp.chance", oldSection.getDouble("harvest-actions.job-xp-chance", 1)); + } + + newSection.set("grow-conditions.||.condition_1.type", "water_more_than"); + newSection.set("grow-conditions.||.condition_1.value", 0); + newSection.set("grow-conditions.||.condition_2.type", "random"); + newSection.set("grow-conditions.||.condition_2.value", 0.5); + + newSection.set("custom-bone-meal.default.item", "BONE_MEAL"); + newSection.set("custom-bone-meal.default.particle", "VILLAGER_HAPPY"); + newSection.set("custom-bone-meal.default.sound", "minecraft:item.bone_meal.use"); + newSection.set("custom-bone-meal.default.chance.2", 0.2); + newSection.set("custom-bone-meal.default.chance.1", 0.6); + + File output = new File(CustomCrops.getInstance().getDataFolder(), "converted" + File.separator + crop + ".yml"); + if (!output.getParentFile().exists()) output.getParentFile().mkdirs(); + try { + newConfig.save(output); + } catch (IOException ignored) { + } + } + + AdventureUtils.sendMessage(sender, "Converted! The result might not be 100% accurate."); + AdventureUtils.sendMessage(sender, "Files are stored into /CustomCrops/converted/ folder"); + AdventureUtils.sendMessage(sender, "Please double check before put into production environment"); + + return true; + } + + @Override + public List onTabComplete(CommandSender sender, List args) { + if (args.size() == 1) { + return List.of("tripwire", "item_frame"); + } + return null; + } +} 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 8e9e99b..71ecb5f 100644 --- a/src/main/java/net/momirealms/customcrops/command/subcmd/MigrateCommand.java +++ b/src/main/java/net/momirealms/customcrops/command/subcmd/MigrateCommand.java @@ -39,6 +39,7 @@ import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.util.Arrays; +import java.util.HashSet; import java.util.List; import java.util.Map; @@ -46,12 +47,23 @@ public class MigrateCommand extends AbstractSubCommand { public static final MigrateCommand INSTANCE = new MigrateCommand(); + private final HashSet confirm; + public MigrateCommand() { super("migrate"); + confirm = new HashSet<>(); } @Override public boolean onCommand(CommandSender sender, List args) { + + if (!confirm.contains(sender.getName())) { + confirm.add(sender.getName()); + AdventureUtils.sendMessage(sender, "[CustomCrops] Type the command again to confirm."); + return true; + } + + confirm.remove(sender.getName()); if (sender instanceof Player player) { AdventureUtils.playerMessage(player, "Migration started. See the console for more information."); } diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 616651b..1090481 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -21,10 +21,19 @@ worlds: - world schedule-system: - enable: true + # Water amount and fertilizer use would be reduced at 6am + # Sprinklers would work at 7am + # if disabled, you can do that manually with command /customcrops force [consume/sprinklerwork] + # 水分和肥料将在每天6点减少,洒水器将在7点工作 + # 如果禁用,你可以使用指令/customcrops force [consume/sprinklerwork]手动操作 + default-schedule: true # The average interval for a crop to gain one point (measured in seconds) # 平均每个农作物获得一生长点的时间间隔(秒) point-gain-interval: 1200 + # Save cache to file interval (seconds) + # set "-1" to disable + # 保存缓存的时间间隔 (秒) + cache-save-interval: 7200 # Thread pool settings # 线程池设置 thread-pool-settings: diff --git a/src/main/resources/messages/messages_spanish.yml b/src/main/resources/messages/messages_spanish.yml index e69de29..c8a56cf 100644 --- a/src/main/resources/messages/messages_spanish.yml +++ b/src/main/resources/messages/messages_spanish.yml @@ -0,0 +1,24 @@ +# https://docs.advntr.dev/minimessage/format.html +messages: + prefix: '[CustomCrops] ' + reload: '¡Recargado! Tomó {time}ms.' + invalid-args: 'Argumentos invalidos.' + no-console: 'Este comando solo puede ser ejecutado por un jugador' + not-online: 'El jugador {player} no esta conectado' + lack-args: 'Los argumentos son insuficientes' + not-none-args: 'Este comando no tiene argumentos' + before-plant: 'Este fertilizador debe ser usado antes de plantarlo' + unsuitable-pot: "No puedes plantar esta semilla en este pot" + reach-crop-limit: 'El numero de crops ha llegado al limite' + no-perm: "No tienes permiso para esto" + spring: 'Primavera' + summer: 'Verano' + autumn: 'Otoño' + winter: 'Invierno' + no-season: 'LAS TEMPORADAS ESTAN DESACTIVADAS EN ESTE MUNDO' + set-season: "Correctamente establecido {world}'s temporada a {season}." + set-date: "Correctamente establecido {world}'s fecha para {date}." + world-not-exist: 'El mundo {world} no existe.' + season-not-exist: 'Temporada {season} no existe.' + force-sprinkler-work: "Se forzo {world}'s sprinklers para trabajar" + force-consume: "Se forzo {world}'s pot para reducir la cantidad de consumo del agua y fertilizantes" \ No newline at end of file diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index aafc553..5871476 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -51,6 +51,7 @@ permissions : customcrops.setseason: true customcrops.force: true customcrops.migrate: true + customcrops.convert: true customcrops.reload: default: op customcrops.help: @@ -64,4 +65,6 @@ permissions : customcrops.force: default: op customcrops.migrate: + default: op + customcrops.convert: default: op \ No newline at end of file