diff --git a/src/main/java/net/momirealms/customcrops/CommandHandler.java b/src/main/java/net/momirealms/customcrops/CommandHandler.java index 9ab25db..37b11cd 100644 --- a/src/main/java/net/momirealms/customcrops/CommandHandler.java +++ b/src/main/java/net/momirealms/customcrops/CommandHandler.java @@ -1,9 +1,9 @@ package net.momirealms.customcrops; -import net.momirealms.customcrops.DataManager.BackUp; -import net.momirealms.customcrops.DataManager.CropManager; -import net.momirealms.customcrops.DataManager.NextSeason; -import net.momirealms.customcrops.DataManager.SprinklerManager; +import net.momirealms.customcrops.datamanager.BackUp; +import net.momirealms.customcrops.datamanager.CropManager; +import net.momirealms.customcrops.datamanager.NextSeason; +import net.momirealms.customcrops.datamanager.SprinklerManager; import org.bukkit.Bukkit; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; diff --git a/src/main/java/net/momirealms/customcrops/Crops/CropTimer.java b/src/main/java/net/momirealms/customcrops/Crops/CropTimer.java index 1aa50c6..045980d 100644 --- a/src/main/java/net/momirealms/customcrops/Crops/CropTimer.java +++ b/src/main/java/net/momirealms/customcrops/Crops/CropTimer.java @@ -1,4 +1,4 @@ -package net.momirealms.customcrops.Crops; +package net.momirealms.customcrops.crops; import net.momirealms.customcrops.CustomCrops; import org.bukkit.Bukkit; diff --git a/src/main/java/net/momirealms/customcrops/Crops/TimeCheck.java b/src/main/java/net/momirealms/customcrops/Crops/TimeCheck.java index da3748d..3c2fe49 100644 --- a/src/main/java/net/momirealms/customcrops/Crops/TimeCheck.java +++ b/src/main/java/net/momirealms/customcrops/Crops/TimeCheck.java @@ -1,32 +1,33 @@ -package net.momirealms.customcrops.Crops; +package net.momirealms.customcrops.crops; import net.momirealms.customcrops.ConfigManager; import net.momirealms.customcrops.CustomCrops; -import net.momirealms.customcrops.DataManager.CropManager; -import net.momirealms.customcrops.DataManager.SprinklerManager; +import net.momirealms.customcrops.datamanager.CropManager; +import net.momirealms.customcrops.datamanager.SprinklerManager; import org.bukkit.Bukkit; import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scheduler.BukkitScheduler; -import java.util.Objects; - public class TimeCheck extends BukkitRunnable { BukkitScheduler bukkitScheduler = Bukkit.getScheduler(); @Override public void run() { - long time = Objects.requireNonNull(Bukkit.getWorld("world")).getTime(); - ConfigManager.Config.cropGrowTimeList.forEach(cropGrowTime -> { - if(time == cropGrowTime){ - bukkitScheduler.runTaskAsynchronously(CustomCrops.instance, CropManager::CropGrow); - } - }); - ConfigManager.Config.sprinklerWorkTimeList.forEach(sprinklerTime -> { - if(time == sprinklerTime){ - bukkitScheduler.runTaskAsynchronously(CustomCrops.instance, SprinklerManager::SprinklerWork); - } + ConfigManager.Config.worlds.forEach(world ->{ + long time = Bukkit.getWorld(world).getTime(); + + ConfigManager.Config.cropGrowTimeList.forEach(cropGrowTime -> { + if(time == cropGrowTime){ + bukkitScheduler.runTaskAsynchronously(CustomCrops.instance, CropManager::CropGrow); + } + }); + ConfigManager.Config.sprinklerWorkTimeList.forEach(sprinklerTime -> { + if(time == sprinklerTime){ + bukkitScheduler.runTaskAsynchronously(CustomCrops.instance, SprinklerManager::SprinklerWork); + } + }); }); } } \ No newline at end of file diff --git a/src/main/java/net/momirealms/customcrops/CustomCrops.java b/src/main/java/net/momirealms/customcrops/CustomCrops.java index 5236d76..014dcdf 100644 --- a/src/main/java/net/momirealms/customcrops/CustomCrops.java +++ b/src/main/java/net/momirealms/customcrops/CustomCrops.java @@ -1,10 +1,10 @@ package net.momirealms.customcrops; import com.comphenix.protocol.ProtocolManager; -import net.momirealms.customcrops.Crops.CropTimer; -import net.momirealms.customcrops.DataManager.BackUp; -import net.momirealms.customcrops.DataManager.CropManager; -import net.momirealms.customcrops.DataManager.SprinklerManager; +import net.momirealms.customcrops.crops.CropTimer; +import net.momirealms.customcrops.datamanager.BackUp; +import net.momirealms.customcrops.datamanager.CropManager; +import net.momirealms.customcrops.datamanager.SprinklerManager; import net.momirealms.customcrops.listener.BreakCustomBlock; import net.momirealms.customcrops.listener.BreakFurniture; import net.momirealms.customcrops.listener.RightClickBlock; diff --git a/src/main/java/net/momirealms/customcrops/DataManager/BackUp.java b/src/main/java/net/momirealms/customcrops/DataManager/BackUp.java index 3ed8120..e056d87 100644 --- a/src/main/java/net/momirealms/customcrops/DataManager/BackUp.java +++ b/src/main/java/net/momirealms/customcrops/DataManager/BackUp.java @@ -1,4 +1,4 @@ -package net.momirealms.customcrops.DataManager; +package net.momirealms.customcrops.datamanager; import net.momirealms.customcrops.CustomCrops; diff --git a/src/main/java/net/momirealms/customcrops/DataManager/CropManager.java b/src/main/java/net/momirealms/customcrops/DataManager/CropManager.java index 96eff6d..c024c9f 100644 --- a/src/main/java/net/momirealms/customcrops/DataManager/CropManager.java +++ b/src/main/java/net/momirealms/customcrops/DataManager/CropManager.java @@ -1,4 +1,4 @@ -package net.momirealms.customcrops.DataManager; +package net.momirealms.customcrops.datamanager; import dev.lone.itemsadder.api.CustomBlock; import net.momirealms.customcrops.ConfigManager; @@ -151,7 +151,7 @@ public class CropManager { String[] string_list = StringUtils.split(key,","); if (world.isChunkLoaded(Integer.parseInt(string_list[0])/16, Integer.parseInt(string_list[2])/16)){ Location tempLoc = new Location(world,Double.parseDouble(string_list[0]),Double.parseDouble(string_list[1]),Double.parseDouble(string_list[2])); - if(world.getBlockAt(tempLoc).getType() != Material.TRIPWIRE){ + if(tempLoc.getBlock().getType() != Material.TRIPWIRE){ CropManager.instances.remove(tempLoc); data.set(worldName+"."+string_list[0]+","+string_list[1]+","+string_list[2], null); }else { @@ -183,8 +183,8 @@ public class CropManager { locations.forEach(seedLocation -> { Location potLocation = seedLocation.clone().subtract(0,1,0); - Block seedBlock = world.getBlockAt(seedLocation); - Block potBlock = world.getBlockAt(potLocation); + Block seedBlock = seedLocation.getBlock(); + Block potBlock = potLocation.getBlock(); String[] seasons = StringUtils.split(data.getString(worldName + "." + seedLocation.getBlockX() + "," + seedLocation.getBlockY() + "," + seedLocation.getBlockZ()),","); @@ -203,8 +203,8 @@ public class CropManager { if(ConfigManager.Config.greenhouse){ for(int i = 1; i <= ConfigManager.Config.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(ConfigManager.Config.glass)){ + if (CustomBlock.byAlreadyPlaced(tempLocation.getBlock()) != null){ + if(CustomBlock.byAlreadyPlaced(tempLocation.getBlock()).getNamespacedID().equalsIgnoreCase(ConfigManager.Config.glass)){ break Label_out; } } @@ -259,8 +259,8 @@ public class CropManager { if(ConfigManager.Config.greenhouse){ for(int i = 1; i <= ConfigManager.Config.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(ConfigManager.Config.glass)){ + if (CustomBlock.byAlreadyPlaced(tempLocation.getBlock()) != null){ + if(CustomBlock.byAlreadyPlaced(tempLocation.getBlock()).getNamespacedID().equalsIgnoreCase(ConfigManager.Config.glass)){ return; } } diff --git a/src/main/java/net/momirealms/customcrops/DataManager/MaxCropsPerChunk.java b/src/main/java/net/momirealms/customcrops/DataManager/MaxCropsPerChunk.java index 493b88d..07a51dd 100644 --- a/src/main/java/net/momirealms/customcrops/DataManager/MaxCropsPerChunk.java +++ b/src/main/java/net/momirealms/customcrops/DataManager/MaxCropsPerChunk.java @@ -1,4 +1,4 @@ -package net.momirealms.customcrops.DataManager; +package net.momirealms.customcrops.datamanager; import dev.lone.itemsadder.api.CustomBlock; import net.momirealms.customcrops.ConfigManager; @@ -26,7 +26,7 @@ public class MaxCropsPerChunk { Location square = chunkLocation.clone().add(i, 0.0, j); for (int k = minY; k <= maxY; ++k) { square.add(0.0, 1.0, 0.0); - Block b = location.getWorld().getBlockAt(square); + Block b = square.getBlock(); if(CustomBlock.byAlreadyPlaced(b)!= null){ if (CustomBlock.byAlreadyPlaced(b).getNamespacedID().contains("stage")) { if (n++ > maxAmount) { diff --git a/src/main/java/net/momirealms/customcrops/DataManager/MaxSprinklersPerChunk.java b/src/main/java/net/momirealms/customcrops/DataManager/MaxSprinklersPerChunk.java index 7928604..f31110e 100644 --- a/src/main/java/net/momirealms/customcrops/DataManager/MaxSprinklersPerChunk.java +++ b/src/main/java/net/momirealms/customcrops/DataManager/MaxSprinklersPerChunk.java @@ -1,4 +1,4 @@ -package net.momirealms.customcrops.DataManager; +package net.momirealms.customcrops.datamanager; import net.momirealms.customcrops.ConfigManager; import net.momirealms.customcrops.IAFurniture; diff --git a/src/main/java/net/momirealms/customcrops/DataManager/NextSeason.java b/src/main/java/net/momirealms/customcrops/DataManager/NextSeason.java index b31da9f..b1e139f 100644 --- a/src/main/java/net/momirealms/customcrops/DataManager/NextSeason.java +++ b/src/main/java/net/momirealms/customcrops/DataManager/NextSeason.java @@ -1,4 +1,4 @@ -package net.momirealms.customcrops.DataManager; +package net.momirealms.customcrops.datamanager; import net.momirealms.customcrops.ConfigManager; import net.momirealms.customcrops.CustomCrops; diff --git a/src/main/java/net/momirealms/customcrops/DataManager/SprinklerManager.java b/src/main/java/net/momirealms/customcrops/DataManager/SprinklerManager.java index 08805d5..e709fe2 100644 --- a/src/main/java/net/momirealms/customcrops/DataManager/SprinklerManager.java +++ b/src/main/java/net/momirealms/customcrops/DataManager/SprinklerManager.java @@ -1,4 +1,4 @@ -package net.momirealms.customcrops.DataManager; +package net.momirealms.customcrops.datamanager; import dev.lone.itemsadder.api.CustomBlock; import net.momirealms.customcrops.ConfigManager; @@ -8,7 +8,6 @@ import net.momirealms.customcrops.MessageManager; import org.apache.commons.lang.StringUtils; import org.bukkit.Bukkit; import org.bukkit.Location; -import org.bukkit.Material; import org.bukkit.World; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.YamlConfiguration; @@ -211,8 +210,8 @@ public class SprinklerManager { }); } private static void waterPot(Location tempLoc, World world) { - if(CustomBlock.byAlreadyPlaced(world.getBlockAt(tempLoc)) != null){ - if(CustomBlock.byAlreadyPlaced(world.getBlockAt(tempLoc)).getNamespacedID().equalsIgnoreCase(ConfigManager.Config.pot)){ + if(CustomBlock.byAlreadyPlaced(tempLoc.getBlock()) != null){ + if(CustomBlock.byAlreadyPlaced(tempLoc.getBlock()).getNamespacedID().equalsIgnoreCase(ConfigManager.Config.pot)){ Bukkit.getScheduler().callSyncMethod(CustomCrops.instance,()->{ CustomBlock.remove(tempLoc); CustomBlock.place((ConfigManager.Config.watered_pot), tempLoc); diff --git a/src/main/java/net/momirealms/customcrops/Integrations/IntegrationCheck.java b/src/main/java/net/momirealms/customcrops/Integrations/IntegrationCheck.java index 4697ef3..eca0e63 100644 --- a/src/main/java/net/momirealms/customcrops/Integrations/IntegrationCheck.java +++ b/src/main/java/net/momirealms/customcrops/Integrations/IntegrationCheck.java @@ -1,4 +1,4 @@ -package net.momirealms.customcrops.Integrations; +package net.momirealms.customcrops.integrations; import net.momirealms.customcrops.ConfigManager; import org.bukkit.Location; diff --git a/src/main/java/net/momirealms/customcrops/Integrations/KingdomsXIntegrations.java b/src/main/java/net/momirealms/customcrops/Integrations/KingdomsXIntegrations.java index 1b28b70..8d77dd3 100644 --- a/src/main/java/net/momirealms/customcrops/Integrations/KingdomsXIntegrations.java +++ b/src/main/java/net/momirealms/customcrops/Integrations/KingdomsXIntegrations.java @@ -1,4 +1,4 @@ -package net.momirealms.customcrops.Integrations; +package net.momirealms.customcrops.integrations; import org.bukkit.Location; import org.bukkit.entity.Player; diff --git a/src/main/java/net/momirealms/customcrops/Integrations/ResidenceIntegrations.java b/src/main/java/net/momirealms/customcrops/Integrations/ResidenceIntegrations.java index 0638847..358ccd6 100644 --- a/src/main/java/net/momirealms/customcrops/Integrations/ResidenceIntegrations.java +++ b/src/main/java/net/momirealms/customcrops/Integrations/ResidenceIntegrations.java @@ -1,4 +1,4 @@ -package net.momirealms.customcrops.Integrations; +package net.momirealms.customcrops.integrations; import com.bekvon.bukkit.residence.containers.Flags; import com.bekvon.bukkit.residence.protection.ClaimedResidence; diff --git a/src/main/java/net/momirealms/customcrops/Integrations/WorldGuardIntegrations.java b/src/main/java/net/momirealms/customcrops/Integrations/WorldGuardIntegrations.java index 663fb45..6b0b958 100644 --- a/src/main/java/net/momirealms/customcrops/Integrations/WorldGuardIntegrations.java +++ b/src/main/java/net/momirealms/customcrops/Integrations/WorldGuardIntegrations.java @@ -1,4 +1,4 @@ -package net.momirealms.customcrops.Integrations; +package net.momirealms.customcrops.integrations; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldguard.LocalPlayer; 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