diff --git a/src/main/java/net/momirealms/customcrops/CommandHandler.java b/src/main/java/net/momirealms/customcrops/CommandHandler.java index ad1ad2c..62ecd5e 100644 --- a/src/main/java/net/momirealms/customcrops/CommandHandler.java +++ b/src/main/java/net/momirealms/customcrops/CommandHandler.java @@ -10,7 +10,6 @@ import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.entity.Player; -import org.kingdoms.data.DataManager; import javax.annotation.ParametersAreNonnullByDefault; import java.util.Objects; diff --git a/src/main/java/net/momirealms/customcrops/Crops/CropGrow.java b/src/main/java/net/momirealms/customcrops/Crops/CropGrow.java new file mode 100644 index 0000000..88362ac --- /dev/null +++ b/src/main/java/net/momirealms/customcrops/Crops/CropGrow.java @@ -0,0 +1,108 @@ +package net.momirealms.customcrops.Crops; + +import dev.lone.itemsadder.api.CustomBlock; +import net.momirealms.customcrops.CustomCrops; +import net.momirealms.customcrops.DataManager.CropManager; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; + +import java.io.File; +import java.util.Objects; + +public class CropGrow { + public static void cropGrow(){ + FileConfiguration config = CustomCrops.instance.getConfig(); + File file = new File(CustomCrops.instance.getDataFolder(), "crop-data.yml"); + FileConfiguration data; + data = YamlConfiguration.loadConfiguration(file); + boolean enable_season = config.getBoolean("enable-season"); + boolean enable_greenhouse = config.getBoolean("config.enable-greenhouse"); + int range = config.getInt("config.greenhouse-range"); + String glass = config.getString("config.greenhouse-glass"); + config.getStringList("config.whitelist-worlds").forEach(worldName -> CropManager.getCrops(Objects.requireNonNull(Bukkit.getWorld(worldName))).forEach(seedLocation -> { + World world = Bukkit.getWorld(worldName); + Location potLocation = seedLocation.clone().subtract(0,1,0); + String[] seasons = Objects.requireNonNull(data.getString(worldName + "." + seedLocation.getBlockX() + "," + seedLocation.getBlockY() + "," + seedLocation.getBlockZ())).split(","); + if (CustomBlock.byAlreadyPlaced(world.getBlockAt(potLocation)) != null && CustomBlock.byAlreadyPlaced(world.getBlockAt(seedLocation)) != null){ + if (CustomBlock.byAlreadyPlaced((world.getBlockAt(potLocation))).getNamespacedID().equalsIgnoreCase(config.getString("config.watered-pot")) && CustomBlock.byAlreadyPlaced(world.getBlockAt(seedLocation)).getNamespacedID().contains("stage")){ + if (CustomBlock.byAlreadyPlaced(world.getBlockAt(seedLocation)).getNamespacedID().equalsIgnoreCase(config.getString("config.dead-crop"))){ + return; + } + String namespace = CustomBlock.byAlreadyPlaced(world.getBlockAt(seedLocation)).getNamespacedID().split(":")[0]; + String[] cropNameList = CustomBlock.byAlreadyPlaced(world.getBlockAt(seedLocation)).getNamespacedID().split(":")[1].split("_"); + Label_out: + if(enable_season){ + if(enable_greenhouse){ + for(int i = 1; i <= range; i++){ + Location tempLocation = seedLocation.clone().add(0,i,0); + if (CustomBlock.byAlreadyPlaced(world.getBlockAt(tempLocation)) != null){ + if(CustomBlock.byAlreadyPlaced(world.getBlockAt(tempLocation)).getNamespacedID().equalsIgnoreCase(glass)){ + break Label_out; + } + } + } + } + boolean wrongSeason = true; + for(String season : seasons){ + if(Objects.equals(season, config.getString("current-season"))){ + wrongSeason = false; + } + } + if(wrongSeason){ + Bukkit.getScheduler().callSyncMethod(CustomCrops.instance, () -> { + CustomBlock.remove(seedLocation); + CustomBlock.place(config.getString("config.dead-crop"),seedLocation); + return null; + }); + return; + } + } + int nextStage = Integer.parseInt(cropNameList[2]) + 1; + if (CustomBlock.getInstance( namespace +":"+cropNameList[0] + "_stage_" + nextStage) != null) { + Bukkit.getScheduler().callSyncMethod(CustomCrops.instance, () ->{ + CustomBlock.remove(potLocation); + CustomBlock.place(config.getString("config.pot"),potLocation); + if(Math.random()< config.getDouble("config.grow-success-chance")){ + CustomBlock.remove(seedLocation); + CustomBlock.place(namespace + ":" + cropNameList[0] + "_stage_" + nextStage,seedLocation); + } + return null; + }); + } + }else if(CustomBlock.byAlreadyPlaced((world.getBlockAt(potLocation))).getNamespacedID().equalsIgnoreCase(config.getString("config.pot")) && CustomBlock.byAlreadyPlaced(world.getBlockAt(seedLocation)).getNamespacedID().contains("stage")){ + if (CustomBlock.byAlreadyPlaced(world.getBlockAt(seedLocation)).getNamespacedID().equalsIgnoreCase(config.getString("config.dead-crop"))){ + return; + } + if(enable_season) { + if(enable_greenhouse){ + for(int i = 1; i <= range; i++){ + Location tempLocation = seedLocation.clone().add(0,i,0); + if (CustomBlock.byAlreadyPlaced(world.getBlockAt(tempLocation)) != null){ + if(CustomBlock.byAlreadyPlaced(world.getBlockAt(tempLocation)).getNamespacedID().equalsIgnoreCase(config.getString("config.greenhouse-glass"))){ + return; + } + } + } + } + boolean wrongSeason = true; + for (String season : seasons) { + if (Objects.equals(season, config.getString("current-season"))) { + wrongSeason = false; + } + } + if (wrongSeason) { + Bukkit.getScheduler().callSyncMethod(CustomCrops.instance, () -> { + CustomBlock.remove(seedLocation); + CustomBlock.place(config.getString("config.dead-crop"), seedLocation); + return null; + }); + } + } + } + } + })); + } +} diff --git a/src/main/java/net/momirealms/customcrops/Crops/SprinklerWork.java b/src/main/java/net/momirealms/customcrops/Crops/SprinklerWork.java new file mode 100644 index 0000000..196a0b5 --- /dev/null +++ b/src/main/java/net/momirealms/customcrops/Crops/SprinklerWork.java @@ -0,0 +1,55 @@ +package net.momirealms.customcrops.Crops; + +import com.comphenix.protocol.PacketType; +import com.comphenix.protocol.events.PacketContainer; +import dev.lone.itemsadder.api.CustomBlock; +import net.momirealms.customcrops.CustomCrops; +import net.momirealms.customcrops.DataManager.SprinklerManager; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; + +import java.io.File; +import java.util.Objects; + +public class SprinklerWork { + public static void sprinklerWork(){ + FileConfiguration config = CustomCrops.instance.getConfig(); + File file = new File(CustomCrops.instance.getDataFolder(), "sprinkler-data.yml"); + FileConfiguration data; + data = YamlConfiguration.loadConfiguration(file); + config.getStringList("config.whitelist-worlds").forEach(worldName -> SprinklerManager.getSprinklers(Objects.requireNonNull(Bukkit.getWorld(worldName))).forEach(location -> { + World world = Bukkit.getWorld(worldName); + String type = Objects.requireNonNull(data.getString(worldName + "." + location.getBlockX() + "," + location.getBlockY() + "," + location.getBlockZ())); + if(type.equals("s1")){ + for(int i = -1; i <= 1;i++){ + for (int j = -1; j <= 1; j++){ + Location tempLoc = location.clone().add(i,-1,j); + waterPot(tempLoc, world, config); + } + } + }else if(type.equals("s2")){ + for(int i = -2; i <= 2;i++){ + for (int j = -2; j <= 2; j++){ + Location tempLoc = location.clone().add(i,-1,j); + waterPot(tempLoc, world, config); + } + } + } + })); + } + private static void waterPot(Location tempLoc, World world, FileConfiguration config) { + if(CustomBlock.byAlreadyPlaced(world.getBlockAt(tempLoc)) != null){ + if(CustomBlock.byAlreadyPlaced(world.getBlockAt(tempLoc)).getNamespacedID().equalsIgnoreCase(config.getString("config.pot"))){ + PacketContainer fakeWater = new PacketContainer(PacketType.Play.Server.ENTITY_HEAD_ROTATION); + Bukkit.getScheduler().callSyncMethod(CustomCrops.instance,()->{ + CustomBlock.remove(tempLoc); + CustomBlock.place(config.getString("config.watered-pot"), tempLoc); + return null; + }); + } + } + } +} diff --git a/src/main/java/net/momirealms/customcrops/Crops/TimeCheck.java b/src/main/java/net/momirealms/customcrops/Crops/TimeCheck.java index 19529cd..7c45fce 100644 --- a/src/main/java/net/momirealms/customcrops/Crops/TimeCheck.java +++ b/src/main/java/net/momirealms/customcrops/Crops/TimeCheck.java @@ -1,166 +1,49 @@ package net.momirealms.customcrops.Crops; -import com.comphenix.protocol.PacketType; -import com.comphenix.protocol.events.PacketContainer; -import dev.lone.itemsadder.api.CustomBlock; import net.momirealms.customcrops.CustomCrops; import net.momirealms.customcrops.DataManager.CropManager; import net.momirealms.customcrops.DataManager.SprinklerManager; import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.World; import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.scheduler.BukkitRunnable; -import java.io.File; +import java.util.List; import java.util.Objects; public class TimeCheck extends BukkitRunnable { + FileConfiguration config = CustomCrops.instance.getConfig(); + List cropGrowTimeList = config.getLongList("config.grow-time"); + List sprinklerWorkTimeList = config.getLongList("config.sprinkler-time"); + @Override public void run() { - long time = Bukkit.getWorld("world").getTime(); - if(time == 23500){ - CropManager.cleanLoadedCache(); - } - if(time == 23700){ - CropManager.saveData(); - } - if(time == 23900){ - FileConfiguration config = CustomCrops.instance.getConfig(); - File file = new File(CustomCrops.instance.getDataFolder(), "crop-data.yml"); - FileConfiguration data; - data = YamlConfiguration.loadConfiguration(file); - boolean enable_season = config.getBoolean("enable-season"); - boolean enable_greenhouse = config.getBoolean("config.enable-greenhouse"); - int range = config.getInt("config.greenhouse-range"); - String glass = config.getString("config.greenhouse-glass"); - config.getStringList("config.whitelist-worlds").forEach(worldName -> CropManager.getCrops(Objects.requireNonNull(Bukkit.getWorld(worldName))).forEach(seedLocation -> { - World world = Bukkit.getWorld(worldName); - Location potLocation = seedLocation.clone().subtract(0,1,0); - String[] seasons = Objects.requireNonNull(data.getString(worldName + "." + seedLocation.getBlockX() + "," + seedLocation.getBlockY() + "," + seedLocation.getBlockZ())).split(","); - if (CustomBlock.byAlreadyPlaced(world.getBlockAt(potLocation)) != null && CustomBlock.byAlreadyPlaced(world.getBlockAt(seedLocation)) != null){ - if (CustomBlock.byAlreadyPlaced((world.getBlockAt(potLocation))).getNamespacedID().equalsIgnoreCase(config.getString("config.watered-pot")) && CustomBlock.byAlreadyPlaced(world.getBlockAt(seedLocation)).getNamespacedID().contains("stage")){ - if (CustomBlock.byAlreadyPlaced(world.getBlockAt(seedLocation)).getNamespacedID().equalsIgnoreCase(config.getString("config.dead-crop"))){ - return; - } - String namespace = CustomBlock.byAlreadyPlaced(world.getBlockAt(seedLocation)).getNamespacedID().split(":")[0]; - String[] cropNameList = CustomBlock.byAlreadyPlaced(world.getBlockAt(seedLocation)).getNamespacedID().split(":")[1].split("_"); - Label_out: - if(enable_season){ - if(enable_greenhouse){ - for(int i = 1; i <= range; i++){ - Location tempLocation = seedLocation.clone().add(0,i,0); - if (CustomBlock.byAlreadyPlaced(world.getBlockAt(tempLocation)) != null){ - if(CustomBlock.byAlreadyPlaced(world.getBlockAt(tempLocation)).getNamespacedID().equalsIgnoreCase(glass)){ - break Label_out; - } - } - } - } - boolean wrongSeason = true; - for(String season : seasons){ - if(Objects.equals(season, config.getString("current-season"))){ - wrongSeason = false; - } - } - if(wrongSeason){ - Bukkit.getScheduler().callSyncMethod(CustomCrops.instance, () -> { - CustomBlock.remove(seedLocation); - CustomBlock.place(config.getString("config.dead-crop"),seedLocation); - return null; - }); - return; - } - } - int nextStage = Integer.parseInt(cropNameList[2]) + 1; - if (CustomBlock.getInstance( namespace +":"+cropNameList[0] + "_stage_" + nextStage) != null) { - Bukkit.getScheduler().callSyncMethod(CustomCrops.instance, () ->{ - CustomBlock.remove(potLocation); - CustomBlock.place(config.getString("config.pot"),potLocation); - if(Math.random()< config.getDouble("config.grow-success-chance")){ - CustomBlock.remove(seedLocation); - CustomBlock.place(namespace + ":" + cropNameList[0] + "_stage_" + nextStage,seedLocation); - } - return null; - }); - } - }else if(CustomBlock.byAlreadyPlaced((world.getBlockAt(potLocation))).getNamespacedID().equalsIgnoreCase(config.getString("config.pot")) && CustomBlock.byAlreadyPlaced(world.getBlockAt(seedLocation)).getNamespacedID().contains("stage")){ - if (CustomBlock.byAlreadyPlaced(world.getBlockAt(seedLocation)).getNamespacedID().equalsIgnoreCase(config.getString("config.dead-crop"))){ - return; - } - if(enable_season) { - if(enable_greenhouse){ - for(int i = 1; i <= range; i++){ - Location tempLocation = seedLocation.clone().add(0,i,0); - if (CustomBlock.byAlreadyPlaced(world.getBlockAt(tempLocation)) != null){ - if(CustomBlock.byAlreadyPlaced(world.getBlockAt(tempLocation)).getNamespacedID().equalsIgnoreCase(config.getString("config.greenhouse-glass"))){ - return; - } - } - } - } - boolean wrongSeason = true; - for (String season : seasons) { - if (Objects.equals(season, config.getString("current-season"))) { - wrongSeason = false; - } - } - if (wrongSeason) { - Bukkit.getScheduler().callSyncMethod(CustomCrops.instance, () -> { - CustomBlock.remove(seedLocation); - CustomBlock.place(config.getString("config.dead-crop"), seedLocation); - return null; - }); - } - } - } - } - })); - } - if (time == 100){ - SprinklerManager.cleanCache(); - } - if (time == 300){ - SprinklerManager.saveData(); - } - if(time == 500){ - FileConfiguration config = CustomCrops.instance.getConfig(); - File file = new File(CustomCrops.instance.getDataFolder(), "sprinkler-data.yml"); - FileConfiguration data; - data = YamlConfiguration.loadConfiguration(file); - config.getStringList("config.whitelist-worlds").forEach(worldName -> SprinklerManager.getSprinklers(Objects.requireNonNull(Bukkit.getWorld(worldName))).forEach(location -> { - World world = Bukkit.getWorld(worldName); - String type = Objects.requireNonNull(data.getString(worldName + "." + location.getBlockX() + "," + location.getBlockY() + "," + location.getBlockZ())); - if(type.equals("s1")){ - for(int i = -1; i <= 1;i++){ - for (int j = -1; j <= 1; j++){ - Location tempLoc = location.clone().add(i,-1,j); - waterPot(tempLoc, world, config); - } - } - }else if(type.equals("s2")){ - for(int i = -2; i <= 2;i++){ - for (int j = -2; j <= 2; j++){ - Location tempLoc = location.clone().add(i,-1,j); - waterPot(tempLoc, world, config); - } - } - } - })); - } - } - private void waterPot(Location tempLoc, World world, FileConfiguration config) { - if(CustomBlock.byAlreadyPlaced(world.getBlockAt(tempLoc)) != null){ - if(CustomBlock.byAlreadyPlaced(world.getBlockAt(tempLoc)).getNamespacedID().equalsIgnoreCase(config.getString("config.pot"))){ - PacketContainer fakeWater = new PacketContainer(PacketType.Play.Server.ENTITY_HEAD_ROTATION); - Bukkit.getScheduler().callSyncMethod(CustomCrops.instance,()->{ - CustomBlock.remove(tempLoc); - CustomBlock.place(config.getString("config.watered-pot"), tempLoc); - return null; - }); + long time = Objects.requireNonNull(Bukkit.getWorld("world")).getTime(); + + cropGrowTimeList.forEach(cropGrowTime -> { + + if(time == cropGrowTime){ + CropManager.cleanLoadedCache(); } - } + if(time == (cropGrowTime + 50)){ + CropManager.saveData(); + } + if(time == (cropGrowTime + 100)){ + CropGrow.cropGrow(); + } + }); + + sprinklerWorkTimeList.forEach(sprinklerTime -> { + + if(time == sprinklerTime){ + SprinklerManager.cleanCache(); + } + if(time == (sprinklerTime + 50)){ + SprinklerManager.saveData(); + } + if(time == (sprinklerTime + 100)){ + SprinklerWork.sprinklerWork(); + } + }); } } diff --git a/src/main/java/net/momirealms/customcrops/CustomCrops.java b/src/main/java/net/momirealms/customcrops/CustomCrops.java index 7debad0..051ffbf 100644 --- a/src/main/java/net/momirealms/customcrops/CustomCrops.java +++ b/src/main/java/net/momirealms/customcrops/CustomCrops.java @@ -7,7 +7,6 @@ import com.comphenix.protocol.events.PacketAdapter; import com.comphenix.protocol.events.PacketContainer; import com.comphenix.protocol.events.PacketEvent; import com.comphenix.protocol.wrappers.WrappedChatComponent; -import net.kyori.adventure.platform.bukkit.BukkitAudiences; import net.momirealms.customcrops.Crops.CropTimer; import net.momirealms.customcrops.DataManager.BackUp; import net.momirealms.customcrops.DataManager.CropManager; @@ -20,7 +19,6 @@ import org.bukkit.Bukkit; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.plugin.java.JavaPlugin; -import org.checkerframework.checker.nullness.qual.NonNull; import java.io.File; import java.io.IOException; @@ -34,7 +32,6 @@ public final class CustomCrops extends JavaPlugin { public static CropTimer timer; public static CropManager cropManager; public static SprinklerManager sprinklerManager; - private BukkitAudiences adventure; @Override public void onEnable() { @@ -57,6 +54,7 @@ public final class CustomCrops extends JavaPlugin { List components = packet.getChatComponents().getValues(); for (WrappedChatComponent component : components) { if(component.toString().contains("Ender Chest")){ + //component.setJson("{\"text\":\"收纳袋\"}"); component.setJson("{\"translate\":\"container.enderchest\"}"); packet.getChatComponents().write(components.indexOf(component), component); } @@ -96,10 +94,11 @@ public final class CustomCrops extends JavaPlugin { //检测papi依赖 if(Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null){ new Placeholders(this).register(); - MessageManager.consoleMessage("[CustomCorps] 检测到PlaceHolderAPI 已启用季节变量!",Bukkit.getConsoleSender()); + MessageManager.consoleMessage("&#ccfbff-#ef96c5&[CustomCrops] 检测到PlaceHolderAPI 已启用季节变量!",Bukkit.getConsoleSender()); } //启动成功 - MessageManager.consoleMessage("[CustomCorps] 自定义农作物插件已启用!作者:小默米 QQ:3266959688",Bukkit.getConsoleSender()); + MessageManager.consoleMessage("&#ccfbff-#ef96c5&[CustomCrops] 自定义农作物插件已启用!作者:小默米 QQ:3266959688",Bukkit.getConsoleSender()); + //this.getLogger().info("自定义农作物插件已启用!作者:小默米 QQ:3266959688"); } @Override @@ -113,23 +112,12 @@ public final class CustomCrops extends JavaPlugin { CropManager.saveData(); SprinklerManager.saveData(); - //关闭adventure - if(this.adventure != null) { - this.adventure.close(); - this.adventure = null; - } //备份 BackUp.backUpData(); - MessageManager.consoleMessage("[CustomCorps] 自定义农作物插件已卸载!作者:小默米 QQ:3266959688",Bukkit.getConsoleSender()); + MessageManager.consoleMessage(("&#ccfbff-#ef96c5&[CustomCrops] 自定义农作物插件已卸载!作者:小默米 QQ:3266959688"),Bukkit.getConsoleSender()); } - public @NonNull BukkitAudiences adventure() { - if(this.adventure == null) { - throw new IllegalStateException("Tried to access Adventure when the plugin was disabled!"); - } - return this.adventure; - } //定时任务 public static void startTimer() { diff --git a/src/main/java/net/momirealms/customcrops/DataManager/BackUp.java b/src/main/java/net/momirealms/customcrops/DataManager/BackUp.java index 3b07564..c1c5d35 100644 --- a/src/main/java/net/momirealms/customcrops/DataManager/BackUp.java +++ b/src/main/java/net/momirealms/customcrops/DataManager/BackUp.java @@ -25,7 +25,6 @@ public class BackUp { BackUp.backUp(sprinkler_data,sprinklerBackUp); } catch (IOException e) { e.printStackTrace(); - CustomCrops.instance.getLogger().warning("备份发生错误"); } } diff --git a/src/main/java/net/momirealms/customcrops/DataManager/CropManager.java b/src/main/java/net/momirealms/customcrops/DataManager/CropManager.java index a9a44d3..99efa5d 100644 --- a/src/main/java/net/momirealms/customcrops/DataManager/CropManager.java +++ b/src/main/java/net/momirealms/customcrops/DataManager/CropManager.java @@ -25,7 +25,7 @@ public class CropManager { CropManager.instances = new HashMap(); if(data.getConfigurationSection(world) != null){ for (String coordinate : data.getConfigurationSection(world).getKeys(false)) { - Location tempLocation = new Location(Bukkit.getWorld(world), Integer.parseInt(coordinate.split(",")[0]), Integer.parseInt(coordinate.split(",")[1]), Integer.parseInt(coordinate.split(",")[2])); + Location tempLocation = new Location(Bukkit.getWorld(world), (double)Integer.parseInt(coordinate.split(",")[0]), (double)Integer.parseInt(coordinate.split(",")[1]), (double)Integer.parseInt(coordinate.split(",")[2])); String season = data.getString(world + "." + coordinate); CropManager.instances.put(tempLocation, season); } @@ -75,19 +75,22 @@ public class CropManager { } else { CropManager.instances = new HashMap(); - Bukkit.getConsoleSender().sendMessage("错误类型1:请联系开发者并提供报错信息"); + Bukkit.getConsoleSender().sendMessage("错误:空数据"); } try { data.save(file); } catch (IOException e) { e.printStackTrace(); + CustomCrops.instance.getLogger().warning("农作物数据保存出错"); } } - public static void putInstance(Location location, String season) { CropManager.instances.put(location, season); } + public HashMap getMap() { + return CropManager.instances; + } //清理无效的农作物 public static void cleanLoadedCache() { @@ -114,6 +117,7 @@ public class CropManager { data.save(file); }catch (IOException e){ e.printStackTrace(); + CustomCrops.instance.getLogger().warning("农作物缓存清理保存出错!"); } } } diff --git a/src/main/java/net/momirealms/customcrops/DataManager/SprinklerManager.java b/src/main/java/net/momirealms/customcrops/DataManager/SprinklerManager.java index 30836a8..e7679f1 100644 --- a/src/main/java/net/momirealms/customcrops/DataManager/SprinklerManager.java +++ b/src/main/java/net/momirealms/customcrops/DataManager/SprinklerManager.java @@ -77,13 +77,14 @@ public class SprinklerManager { } else { SprinklerManager.instances = new HashMap(); - Bukkit.getConsoleSender().sendMessage("错误:请联系开发者并提供报错信息"); + Bukkit.getConsoleSender().sendMessage("错误:空数据"); } try { data.save(file); } catch (IOException e) { e.printStackTrace(); + CustomCrops.instance.getLogger().warning("洒水器数据保存出错"); } } public static void putInstance(Location location, String type) { @@ -111,6 +112,7 @@ public class SprinklerManager { data.save(file); }catch (IOException e){ e.printStackTrace(); + CustomCrops.instance.getLogger().warning("洒水器缓存清理保存出错!"); } return null; }); diff --git a/src/main/java/net/momirealms/customcrops/Integrations/KingdomsXIntegrations.java b/src/main/java/net/momirealms/customcrops/Integrations/KingdomsXIntegrations.java index 685ba9d..1b28b70 100644 --- a/src/main/java/net/momirealms/customcrops/Integrations/KingdomsXIntegrations.java +++ b/src/main/java/net/momirealms/customcrops/Integrations/KingdomsXIntegrations.java @@ -11,9 +11,6 @@ public class KingdomsXIntegrations { KingdomPlayer kp = KingdomPlayer.getKingdomPlayer(player); Land land = Land.getLand(location); if (land == null) return false; - if (player.isOp()) { - return false; - } if (land.isClaimed()) { Kingdom cropKingdom = land.getKingdom(); if (kp.getKingdom() != null) { diff --git a/src/main/java/net/momirealms/customcrops/Integrations/ResidenceIntegrations.java b/src/main/java/net/momirealms/customcrops/Integrations/ResidenceIntegrations.java index 65ddde8..489d819 100644 --- a/src/main/java/net/momirealms/customcrops/Integrations/ResidenceIntegrations.java +++ b/src/main/java/net/momirealms/customcrops/Integrations/ResidenceIntegrations.java @@ -1,5 +1,6 @@ package net.momirealms.customcrops.Integrations; +import com.bekvon.bukkit.residence.containers.Flags; import com.bekvon.bukkit.residence.protection.ClaimedResidence; import com.bekvon.bukkit.residence.protection.FlagPermissions; import com.bekvon.bukkit.residence.protection.ResidencePermissions; @@ -13,7 +14,8 @@ public class ResidenceIntegrations { if(res!=null){ ResidencePermissions perms = res.getPermissions(); String playerName = player.getName(); - boolean hasPermission = perms.playerHas(playerName, "build", true); + boolean hasPermission = perms.playerHas(player, Flags.build, true); + ///perms.playerHas(playerName, "build", true); return !hasPermission; } return false; @@ -24,7 +26,8 @@ public class ResidenceIntegrations { if(res!=null){ ResidencePermissions perms = res.getPermissions(); String playerName = player.getName(); - boolean hasPermission = perms.playerHas(playerName, "harvest", true); + boolean hasPermission = perms.playerHas(player, Flags.harvest, true); + //boolean hasPermission = perms.playerHas(playerName, "harvest", true); return !hasPermission; } return false; diff --git a/src/main/java/net/momirealms/customcrops/Integrations/WorldGuardIntegrations.java b/src/main/java/net/momirealms/customcrops/Integrations/WorldGuardIntegrations.java index 663fb45..e6e4fcb 100644 --- a/src/main/java/net/momirealms/customcrops/Integrations/WorldGuardIntegrations.java +++ b/src/main/java/net/momirealms/customcrops/Integrations/WorldGuardIntegrations.java @@ -17,7 +17,10 @@ public class WorldGuardIntegrations { RegionContainer container = WorldGuard.getInstance().getPlatform().getRegionContainer(); RegionQuery query = container.createQuery(); - return !query.testState(BukkitAdapter.adapt(loc), localPlayer, Flags.BUILD); + if (!query.testState(BukkitAdapter.adapt(loc), localPlayer, Flags.BUILD)) { + return true; + } + return false; } public static boolean checkWGHarvest(Location loc,Player player){ @@ -25,6 +28,9 @@ public class WorldGuardIntegrations { RegionContainer container = WorldGuard.getInstance().getPlatform().getRegionContainer(); RegionQuery query = container.createQuery(); - return !query.testState(BukkitAdapter.adapt(loc), localPlayer, Flags.BLOCK_BREAK); + if (!query.testState(BukkitAdapter.adapt(loc), localPlayer, Flags.BLOCK_BREAK)) { + return true; + } + return false; } } diff --git a/src/main/java/net/momirealms/customcrops/Libs/minedown/MineDown.java b/src/main/java/net/momirealms/customcrops/Libs/minedown/MineDown.java new file mode 100644 index 0000000..1e0847a --- /dev/null +++ b/src/main/java/net/momirealms/customcrops/Libs/minedown/MineDown.java @@ -0,0 +1,499 @@ +package net.momirealms.customcrops.Libs.minedown; + +/* + * Copyright (c) 2017 Max Lee (https://github.com/Phoenix616) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +import net.md_5.bungee.api.ChatColor; +import net.md_5.bungee.api.chat.BaseComponent; +import net.md_5.bungee.api.chat.ClickEvent; +import net.md_5.bungee.api.chat.HoverEvent; + +import java.util.Map; + +/** + *

MineDown

+ * A MarkDown inspired markup for Minecraft chat components + *

+ * This lets you convert string messages into chat components by using a custom mark up syntax + * which is loosely based on MarkDown while still supporting legacy formatting codes. + * + * + * + * + * + * + * + * + * + * + * + * + *
Inline Formatting
Color legacy &6Text {@link ChatColor} codes
Color &gold&Text {@link ChatColor} codes
RGB Hex Color &ff00ff&Text Full hexadecimal format
RGB Hex Color &f0f&Text Short format (equivalent to long one)
Bold **Text**
Italic ##Text##
Underlined __Text__
Strikethrough ~~Text~~
Obfuscated ??Text??
+ * + *

Events

+ * You can define click and hover events with the commonly used MarkDown link syntax. + *

+ * + * + * + * + * + * + * + *
Simple Syntax
General syntax [Text](text-color text-formatting... link hover text)
Simple Link [Text](https://example.com)
Simple Command [Text](/command to run)
Link + Hover [Text](https://example.com Hover Text)
Text formatting + Link + Hover [Text](blue underline https://example.com Hover Text)
+ *

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Advanced Syntax
General syntax [Text](action=value) {@link ClickEvent.Action}, {@link HoverEvent.Action}
Link [Text](open_url=https://example.com)
Color [Text](color=red)
RGB Hex Color [Text](color=#ff00ff) Full hexadecimal format
RGB Hex Color [Text](color=#f0f) Short format (equivalent to long one)
Formatting [Text](format=underline,bold)
Font [Text](format=underline,bold)
Run Command [Text](run_command=/command string)
Suggest Command [Text](suggest_command=/command)
Simple Hover [Text](hover=Hover Text)
Hover Text [Text](show_text=Hover Text)
Hover Entity Info [Text](show_entity=uuid:pig Name)
Hover Item Info [Text](show_item=stone*2 nbt...)
+ *

+ * All advanced settings can be chained/included in a event definition. + * You can't however add multiple different colors or click and hover actions! + */ +public class MineDown { + public static final String FONT_PREFIX = "font="; + public static final String COLOR_PREFIX = "color="; + public static final String FORMAT_PREFIX = "format="; + public static final String HOVER_PREFIX = "hover="; + public static final String INSERTION_PREFIX = "insert="; + + private String message; + private final Replacer replacer = new Replacer(); + private final MineDownParser parser = new MineDownParser(); + private BaseComponent[] baseComponents = null; + private boolean replaceFirst = Boolean.getBoolean("de.themoep.minedown.replacefirst"); + + /** + * Create a new MineDown builder with a certain message + * @param message The message to parse + */ + public MineDown(String message) { + this.message = message; + } + + /** + * Parse a MineDown string to components + * @param message The message to translate + * @param replacements Optional placeholder replacements + * @return The parsed components + */ + public static BaseComponent[] parse(String message, String... replacements) { + return new MineDown(message).replace(replacements).toComponent(); + } + + /** + * Convert components to a MineDown string + * @param components The components to convert + * @return The components represented as a MineDown string + */ + public static String stringify(BaseComponent[] components) { + return new MineDownStringifier().stringify(components); + } + + /** + * Parse and convert the message to the component + * @return The parsed component message + */ + public BaseComponent[] toComponent() { + if (baseComponents() == null) { + if (replaceFirst()) { + Replacer componentReplacer = new Replacer(); + for (Map.Entry entry : replacer().componentReplacements().entrySet()) { + componentReplacer.replace(entry.getKey(), stringify(entry.getValue())); + } + baseComponents = parser().parse(componentReplacer.replaceIn(replacer().replaceIn(message()))).create(); + } else { + baseComponents = replacer().replaceIn(parser().parse(message()).create()); + } + } + return baseComponents(); + } + + /** + * Remove a cached component and re-parse the next time {@link #toComponent} is called + */ + private void reset() { + baseComponents = null; + } + + /** + * Set whether or not replacements should be replaced before or after the components are created. + * When replacing first it will not replace any placeholders with component replacement values! + * Default is after. (replaceFirst = false) + * @param replaceFirst Whether or not to replace first or parse first + * @return The MineDown instance + */ + public MineDown replaceFirst(boolean replaceFirst) { + reset(); + this.replaceFirst = replaceFirst; + return this; + } + + /** + * Get whether or not replacements should be replaced before or after the components are created. + * When replacing first it will not replace any placeholders with component replacement values! + * Default is after. (replaceFirst = false) + * @return Whether or not to replace first or parse first + */ + public boolean replaceFirst() { + return replaceFirst; + } + + /** + * Add an array with placeholders and values that should get replaced in the message + * @param replacements The replacements, nth element is the placeholder, n+1th the value + * @return The MineDown instance + */ + public MineDown replace(String... replacements) { + reset(); + replacer().replace(replacements); + return this; + } + + /** + * Add a map with placeholders and values that should get replaced in the message + * @param replacements The replacements mapped placeholder to value + * @return The MineDown instance + */ + public MineDown replace(Map replacements) { + reset(); + replacer().replace(replacements); + return this; + } + + /** + * Add a placeholder to component mapping that should get replaced in the message + * @param placeholder The placeholder to replace + * @param replacement The replacement components + * @return The Replacer instance + */ + public MineDown replace(String placeholder, BaseComponent... replacement) { + reset(); + replacer().replace(placeholder,replacement); + return this; + } + + /** + * Set the placeholder indicator for both prefix and suffix + * @param placeholderIndicator The character to use as a placeholder indicator + * @return The MineDown instance + */ + public MineDown placeholderIndicator(String placeholderIndicator) { + placeholderPrefix(placeholderIndicator); + placeholderSuffix(placeholderIndicator); + return this; + } + + /** + * Set the placeholder indicator's prefix character + * @param placeholderPrefix The character to use as the placeholder indicator's prefix + * @return The MineDown instance + */ + public MineDown placeholderPrefix(String placeholderPrefix) { + reset(); + replacer().placeholderPrefix(placeholderPrefix); + return this; + } + + /** + * Get the placeholder indicator's prefix character + * @return The placeholder indicator's prefix character + */ + public String placeholderPrefix() { + return replacer().placeholderPrefix(); + } + + /** + * Set the placeholder indicator's suffix character + * @param placeholderSuffix The character to use as the placeholder indicator's suffix + * @return The MineDown instance + */ + public MineDown placeholderSuffix(String placeholderSuffix) { + reset(); + replacer().placeholderSuffix(placeholderSuffix); + return this; + } + + /** + * Get the placeholder indicator's suffix character + * @return The placeholder indicator's suffix character + */ + public String placeholderSuffix() { + return replacer().placeholderSuffix(); + } + + /** + * Set whether or not the case of the placeholder should be ignored when replacing + * @param ignorePlaceholderCase Whether or not to ignore the case of the placeholders + * @return The MineDown instance + */ + public MineDown ignorePlaceholderCase(boolean ignorePlaceholderCase) { + reset(); + replacer().ignorePlaceholderCase(ignorePlaceholderCase); + return this; + } + + /** + * Get whether or not the case of the placeholder should be ignored when replacing + * @return Whether or not to ignore the case of the placeholders + */ + public boolean ignorePlaceholderCase() { + return replacer().ignorePlaceholderCase(); + } + + /** + * Enable or disable the translation of legacy color codes + * @param translateLegacyColors Whether or not to translate legacy color codes (Default: true) + * @return The MineDown instance + * @deprecated Use {@link #enable(MineDownParser.Option)} and {@link #disable(MineDownParser.Option)} + */ + @Deprecated + public MineDown translateLegacyColors(boolean translateLegacyColors) { + reset(); + parser().translateLegacyColors(translateLegacyColors); + return this; + } + + /** + * Detect urls in strings and add events to them? (Default: true) + * @param enabled Whether or not to detect URLs and add events to them + * @return The MineDown instance + */ + public MineDown urlDetection(boolean enabled) { + reset(); + parser().urlDetection(enabled); + return this; + } + + /** + * Automatically add http to values of open_url when there doesn't exist any? (Default: true) + * @param enabled Whether or not to automatically add http when missing + * @return The MineDown instance + */ + public MineDown autoAddUrlPrefix(boolean enabled) { + reset(); + parser().autoAddUrlPrefix(enabled); + return this; + } + + /** + * The text to display when hovering over an URL + * @param text The text to display when hovering over an URL + * @return The MineDown instance + */ + public MineDown urlHoverText(String text) { + reset(); + parser().urlHoverText(text); + return this; + } + + /** + * Set the max width the hover text should have. + * Minecraft itself will wrap after 60 characters. + * Won't apply if the text already includes new lines. + * @param hoverTextWidth The url hover text length + * @return The MineDown instance + */ + public MineDown hoverTextWidth(int hoverTextWidth) { + reset(); + parser().hoverTextWidth(hoverTextWidth); + return this; + } + + /** + * Enable an option. Unfilter it if you filtered it before. + * @param option The option to enable + * @return The MineDown instance + */ + public MineDown enable(MineDownParser.Option option) { + reset(); + parser().enable(option); + return this; + } + + /** + * Disable an option. Disabling an option will stop the parser from replacing + * this option's chars in the string. Use {@link #filter(MineDownParser.Option)} to completely + * remove the characters used by this option from the message instead. + * @param option The option to disable + * @return The MineDown instance + */ + public MineDown disable(MineDownParser.Option option) { + reset(); + parser().disable(option); + return this; + } + + /** + * Filter an option. This completely removes the characters of this option from + * the string ignoring whether the option is enabled or not. + * @param option The option to add to the filter + * @return The MineDown instance + */ + public MineDown filter(MineDownParser.Option option) { + reset(); + parser().filter(option); + return this; + } + + /** + * Unfilter an option. Does not enable it! + * @param option The option to remove from the filter + * @return The MineDown instance + */ + public MineDown unfilter(MineDownParser.Option option) { + reset(); + parser().unfilter(option); + return this; + } + + /** + * Set a special character to replace color codes by if translating legacy colors is enabled. + * @param colorChar The character to use as a special color code. (Default: ampersand &) + * @return The MineDown instance + */ + public MineDown colorChar(char colorChar) { + reset(); + parser().colorChar(colorChar); + return this; + } + + /** + * Get the set message that is to be parsed + * @return The to be parsed message + */ + public String message() { + return this.message; + } + + /** + * Set the message that is to be parsed + * @param message The message to be parsed + * @return The MineDown instance + */ + public MineDown message(String message) { + this.message = message; + reset(); + return this; + } + + /** + * Get the replacer instance that is currently used + * @return The currently used replacer instance + */ + public Replacer replacer() { + return this.replacer; + } + + /** + * Get the parser instance that is currently used + * @return The currently used parser instance + */ + public MineDownParser parser() { + return this.parser; + } + + protected BaseComponent[] baseComponents() { + return this.baseComponents; + } + + /** + * Copy all MineDown settings to a new instance + * @return The new MineDown instance with all settings copied + */ + public MineDown copy() { + return new MineDown(message()).copy(this); + } + + /** + * Copy all MineDown settings from another one + * @param from The MineDown to copy from + * @return This MineDown instance + */ + public MineDown copy(MineDown from) { + replacer().copy(from.replacer()); + parser().copy(from.parser()); + return this; + } + + /** + * Get the string that represents the format in MineDown + * @param format The format + * @return The MineDown string or an empty one if it's not a format + */ + public static String getFormatString(ChatColor format) { + if (format == ChatColor.BOLD) { + return "**"; + } else if (format == ChatColor.ITALIC) { + return "##"; + } else if (format == ChatColor.UNDERLINE) { + return "__"; + } else if (format == ChatColor.STRIKETHROUGH) { + return "~~"; + } else if (format == ChatColor.MAGIC) { + return "??"; + } + return ""; + } + + /** + * Get the ChatColor format from a MineDown string + * @param c The character + * @return The ChatColor of that format or null it none was found + */ + public static ChatColor getFormatFromChar(char c) { + switch (c) { + case '~': + return ChatColor.STRIKETHROUGH; + case '_': + return ChatColor.UNDERLINE; + case '*': + return ChatColor.BOLD; + case '#': + return ChatColor.ITALIC; + case '?': + return ChatColor.MAGIC; + } + return null; + } + + /** + * Escape all MineDown formatting in a string. This will escape backslashes too! + * @param string The string to escape in + * @return The string with formatting escaped + */ + public static String escape(String string) { + return new MineDown(string).parser().escape(string); + } +} diff --git a/src/main/java/net/momirealms/customcrops/Libs/minedown/MineDownParser.java b/src/main/java/net/momirealms/customcrops/Libs/minedown/MineDownParser.java new file mode 100644 index 0000000..5751122 --- /dev/null +++ b/src/main/java/net/momirealms/customcrops/Libs/minedown/MineDownParser.java @@ -0,0 +1,1241 @@ +package net.momirealms.customcrops.Libs.minedown; + +/* + * Copyright (c) 2017 Max Lee (https://github.com/Phoenix616) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +import net.md_5.bungee.api.ChatColor; +import net.md_5.bungee.api.chat.BaseComponent; +import net.md_5.bungee.api.chat.ClickEvent; +import net.md_5.bungee.api.chat.ComponentBuilder; +import net.md_5.bungee.api.chat.HoverEvent; +import net.md_5.bungee.api.chat.ItemTag; +import net.md_5.bungee.api.chat.TextComponent; +import net.md_5.bungee.api.chat.hover.content.Entity; +import net.md_5.bungee.api.chat.hover.content.Item; +import net.md_5.bungee.api.chat.hover.content.Text; + +import java.awt.Color; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Collections; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.PrimitiveIterator; +import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +import static net.momirealms.customcrops.Libs.minedown.MineDown.COLOR_PREFIX; +import static net.momirealms.customcrops.Libs.minedown.MineDown.FONT_PREFIX; +import static net.momirealms.customcrops.Libs.minedown.MineDown.FORMAT_PREFIX; +import static net.momirealms.customcrops.Libs.minedown.MineDown.HOVER_PREFIX; +import static net.momirealms.customcrops.Libs.minedown.MineDown.INSERTION_PREFIX; + +public class MineDownParser { + private static final String RAINBOW = "rainbow"; + + private static final boolean HAS_APPEND_SUPPORT = Util.hasMethod(ComponentBuilder.class, "append", BaseComponent[].class); + private static final boolean HAS_RGB_SUPPORT = Util.hasMethod(ChatColor.class, "of", String.class); + private static final boolean HAS_FONT_SUPPORT = Util.hasMethod(ComponentBuilder.class, "font", String.class); + private static final boolean HAS_INSERTION_SUPPORT = Util.hasMethod(ComponentBuilder.class, "insertion", String.class); + private static final boolean HAS_HOVER_CONTENT_SUPPORT = Util.hasMethod(HoverEvent.class, "getContents"); + + /** + * The character to use as a special color code. (Default: ampersand &) + */ + private char colorChar = '&'; + + /** + * All enabled options + */ + private Set