Compare commits
	
		
			19 Commits
		
	
	
		
			0.3.0-ALPH
			...
			0.6.0-ALPH
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| b1aefdd9d9 | |||
| c44ff5c890 | |||
| c6d3a771c3 | |||
| 3e31c8c648 | |||
| 9c6921b4cd | |||
| 3b5218cb98 | |||
| a1c9624fe1 | |||
| a7d1da7f8a | |||
| c2ffe5e903 | |||
| 3d83458b9c | |||
| abb080b065 | |||
| 9bb234169d | |||
| 664115b2b4 | |||
| 4602ca71db | |||
| 30bca7b8f1 | |||
| 81e62eb664 | |||
| 5cbde82fff | |||
| eb0e06f193 | |||
| 483ffaec2b | 
							
								
								
									
										21
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								README.md
									
									
									
									
									
								
							@@ -3,6 +3,9 @@
 | 
				
			|||||||
The paid-signs plugin is a plugin that lets you add costs for creating plugin signs. This allows restricting usage of
 | 
					The paid-signs plugin is a plugin that lets you add costs for creating plugin signs. This allows restricting usage of
 | 
				
			||||||
signs such as CraftBook's gate/lift and other signs while still allowing every player to use the signs.
 | 
					signs such as CraftBook's gate/lift and other signs while still allowing every player to use the signs.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Note: OP players, and players with the '*' permission will have the `paidsigns.paymentexempt` permission and will not
 | 
				
			||||||
 | 
					see any payment messages. For testing, you'll need to un-set the `paidsigns.paymentexempt` permission.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Limitations
 | 
					## Limitations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
As this plugin only listens to sign change events, there are some limitations:
 | 
					As this plugin only listens to sign change events, there are some limitations:
 | 
				
			||||||
@@ -13,10 +16,11 @@ As this plugin only listens to sign change events, there are some limitations:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
## Commands
 | 
					## Commands
 | 
				
			||||||
 | 
					
 | 
				
			||||||
* /addpaidsign <name> <cost> \[permission] \[ignore case] \[ignore color]
 | 
					* /addpaidsign <name> <cost> \[permission] \[ignore case] \[ignore color] \[match any condition]
 | 
				
			||||||
* /addpaidsigncondition <name (of a paid sign)> <line number> <string to match> \[executeRegEx] \[ignoreCase]
 | 
					* /addpaidsigncondition <name (of a paid sign)> <line number> <string to match> \[executeRegEx] \[ignoreCase]
 | 
				
			||||||
  \[ignoreColor]
 | 
					  \[ignoreColor]
 | 
				
			||||||
* /listpaidsigns \[name (of a paid sign)] \[line number]
 | 
					* /listpaidsigns \[name (of a paid sign)] \[line number]
 | 
				
			||||||
 | 
					* /editpaidsign <sign name> <property>/<line number> \[new value]/<property> \[new value]
 | 
				
			||||||
* /removepaidsigncondition <name (of a paid sign)> <line number>
 | 
					* /removepaidsigncondition <name (of a paid sign)> <line number>
 | 
				
			||||||
* /removepaidsign <name (of a paid sign)>
 | 
					* /removepaidsign <name (of a paid sign)>
 | 
				
			||||||
* /reload
 | 
					* /reload
 | 
				
			||||||
@@ -35,6 +39,8 @@ This command adds a new paid sign that does nothing until a condition is added.
 | 
				
			|||||||
  default uses the config file value).
 | 
					  default uses the config file value).
 | 
				
			||||||
* ignore color - Whether any condition of the paid sign should ignore color by default, when matching against text (
 | 
					* ignore color - Whether any condition of the paid sign should ignore color by default, when matching against text (
 | 
				
			||||||
  default uses the config file value).
 | 
					  default uses the config file value).
 | 
				
			||||||
 | 
					* match any condition - Whether to trigger a paid sign match if a single one of the sign's conditions is true. This is
 | 
				
			||||||
 | 
					  mainly useful if several lines may contain the match string, or if trying to match a word.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### /addpaidsigncondition
 | 
					### /addpaidsigncondition
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -57,6 +63,14 @@ This lists registered paid signs and paid sign conditions. No arguments will pri
 | 
				
			|||||||
* name - The name of the paid sign to see information about
 | 
					* name - The name of the paid sign to see information about
 | 
				
			||||||
* line number - The line number of the condition to see information about
 | 
					* line number - The line number of the condition to see information about
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### /editpaidsign
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* name - The name of the paid sign to edit
 | 
				
			||||||
 | 
					* property/line number - The property to edit for the sign, or the line of the condition to edit
 | 
				
			||||||
 | 
					* new value/property - The new property value if a property was specified in the second argument, or a condition
 | 
				
			||||||
 | 
					  property if a line number was specified in the second argument
 | 
				
			||||||
 | 
					* new value - The new property value of the condition property specified in the third argument
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### /removepaidsigncondition
 | 
					### /removepaidsigncondition
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Removes a paid sign condition from a sign
 | 
					Removes a paid sign condition from a sign
 | 
				
			||||||
@@ -79,12 +93,15 @@ Removes a registered paid sign
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
## Configuration options
 | 
					## Configuration options
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* language - The language to use for all messages displayed to players
 | 
				
			||||||
* ignoreCase - Whether to ignore the case (lowercase/uppercase) of the paid sign text. The option can be set on a
 | 
					* ignoreCase - Whether to ignore the case (lowercase/uppercase) of the paid sign text. The option can be set on a
 | 
				
			||||||
  per-sign basis, but this value is used if not specified. The correct value depends on whether the plugin signs it
 | 
					  per-sign basis, but this value is used if not specified. The correct value depends on whether the plugin signs it
 | 
				
			||||||
  should match are case-sensitive or not.
 | 
					  should match are case-sensitive or not.
 | 
				
			||||||
* ignoreColor - Whether to ignore any color or formatting applied to the text when trying to match a paid sign's text.
 | 
					* ignoreColor - Whether to ignore any color or formatting applied to the text when trying to match a paid sign's text.
 | 
				
			||||||
  The option can be set on a per-sign basis, but this value is used if not specified. The correct value depends on
 | 
					  The option can be set on a per-sign basis, but this value is used if not specified. The correct value depends on
 | 
				
			||||||
  whether the plugin signs it should match allow coloring or not.
 | 
					  whether the plugin signs it should match allow coloring or not.
 | 
				
			||||||
* enableRefunds - Whether to enable refunds to the sign creator when a sign detected as a paid sign is broken (payment
 | 
					* refundsEnabled - Whether to enable refunds to the sign creator when a sign detected as a paid sign is broken (payment
 | 
				
			||||||
  will always go to the original creator)
 | 
					  will always go to the original creator)
 | 
				
			||||||
* refundPercentage - The percentage of the paid sign cost to refund (0-100)
 | 
					* refundPercentage - The percentage of the paid sign cost to refund (0-100)
 | 
				
			||||||
 | 
					* refundAlways - Whether to refund when signs that players have paid for are broken by anything. This includes tnt,
 | 
				
			||||||
 | 
					  creepers, pistons and similar
 | 
				
			||||||
							
								
								
									
										8
									
								
								pom.xml
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								pom.xml
									
									
									
									
									
								
							@@ -6,7 +6,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    <groupId>net.knarcraft</groupId>
 | 
					    <groupId>net.knarcraft</groupId>
 | 
				
			||||||
    <artifactId>paidsigns</artifactId>
 | 
					    <artifactId>paidsigns</artifactId>
 | 
				
			||||||
    <version>0.3.0-ALPHA</version>
 | 
					    <version>0.6.0-ALPHA</version>
 | 
				
			||||||
    <packaging>jar</packaging>
 | 
					    <packaging>jar</packaging>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <name>Paid Signs</name>
 | 
					    <name>Paid Signs</name>
 | 
				
			||||||
@@ -25,8 +25,8 @@
 | 
				
			|||||||
                <artifactId>maven-compiler-plugin</artifactId>
 | 
					                <artifactId>maven-compiler-plugin</artifactId>
 | 
				
			||||||
                <version>3.8.1</version>
 | 
					                <version>3.8.1</version>
 | 
				
			||||||
                <configuration>
 | 
					                <configuration>
 | 
				
			||||||
                    <source>16</source>
 | 
					                    <source>${java.version}</source>
 | 
				
			||||||
                    <target>16</target>
 | 
					                    <target>${java.version}</target>
 | 
				
			||||||
                </configuration>
 | 
					                </configuration>
 | 
				
			||||||
            </plugin>
 | 
					            </plugin>
 | 
				
			||||||
            <plugin>
 | 
					            <plugin>
 | 
				
			||||||
@@ -85,7 +85,7 @@
 | 
				
			|||||||
        <dependency>
 | 
					        <dependency>
 | 
				
			||||||
            <groupId>org.jetbrains</groupId>
 | 
					            <groupId>org.jetbrains</groupId>
 | 
				
			||||||
            <artifactId>annotations</artifactId>
 | 
					            <artifactId>annotations</artifactId>
 | 
				
			||||||
            <version>22.0.0</version>
 | 
					            <version>23.0.0</version>
 | 
				
			||||||
            <scope>compile</scope>
 | 
					            <scope>compile</scope>
 | 
				
			||||||
        </dependency>
 | 
					        </dependency>
 | 
				
			||||||
    </dependencies>
 | 
					    </dependencies>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,13 +4,16 @@ import net.knarcraft.paidsigns.command.AddCommand;
 | 
				
			|||||||
import net.knarcraft.paidsigns.command.AddConditionCommand;
 | 
					import net.knarcraft.paidsigns.command.AddConditionCommand;
 | 
				
			||||||
import net.knarcraft.paidsigns.command.AddConditionTabCompleter;
 | 
					import net.knarcraft.paidsigns.command.AddConditionTabCompleter;
 | 
				
			||||||
import net.knarcraft.paidsigns.command.AddTabCompleter;
 | 
					import net.knarcraft.paidsigns.command.AddTabCompleter;
 | 
				
			||||||
 | 
					import net.knarcraft.paidsigns.command.EditCommand;
 | 
				
			||||||
 | 
					import net.knarcraft.paidsigns.command.EditTabCompleter;
 | 
				
			||||||
import net.knarcraft.paidsigns.command.ListCommand;
 | 
					import net.knarcraft.paidsigns.command.ListCommand;
 | 
				
			||||||
import net.knarcraft.paidsigns.command.ListTabCompleter;
 | 
					import net.knarcraft.paidsigns.command.ListTabCompleter;
 | 
				
			||||||
import net.knarcraft.paidsigns.command.ReloadTabCommand;
 | 
					import net.knarcraft.paidsigns.command.ReloadTabCommand;
 | 
				
			||||||
import net.knarcraft.paidsigns.command.RemoveConditionCommand;
 | 
					import net.knarcraft.paidsigns.command.RemoveConditionCommand;
 | 
				
			||||||
import net.knarcraft.paidsigns.command.RemoveConditionTabCompleter;
 | 
					import net.knarcraft.paidsigns.command.RemoveConditionTabCompleter;
 | 
				
			||||||
import net.knarcraft.paidsigns.command.RemoveTabCommand;
 | 
					import net.knarcraft.paidsigns.command.RemoveTabCommand;
 | 
				
			||||||
import net.knarcraft.paidsigns.listener.BlockBreakListener;
 | 
					import net.knarcraft.paidsigns.formatting.Translator;
 | 
				
			||||||
 | 
					import net.knarcraft.paidsigns.listener.SignBreakListener;
 | 
				
			||||||
import net.knarcraft.paidsigns.listener.SignListener;
 | 
					import net.knarcraft.paidsigns.listener.SignListener;
 | 
				
			||||||
import net.knarcraft.paidsigns.manager.EconomyManager;
 | 
					import net.knarcraft.paidsigns.manager.EconomyManager;
 | 
				
			||||||
import net.knarcraft.paidsigns.manager.PaidSignManager;
 | 
					import net.knarcraft.paidsigns.manager.PaidSignManager;
 | 
				
			||||||
@@ -33,10 +36,12 @@ public final class PaidSigns extends JavaPlugin {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    private static PaidSigns paidSigns;
 | 
					    private static PaidSigns paidSigns;
 | 
				
			||||||
    private PaidSignManager signManager;
 | 
					    private PaidSignManager signManager;
 | 
				
			||||||
 | 
					    private String language;
 | 
				
			||||||
    private boolean ignoreCase;
 | 
					    private boolean ignoreCase;
 | 
				
			||||||
    private boolean ignoreColor;
 | 
					    private boolean ignoreColor;
 | 
				
			||||||
    private boolean enableRefunds;
 | 
					    private boolean refundsEnabled;
 | 
				
			||||||
    private int refundPercentage;
 | 
					    private short refundPercentage;
 | 
				
			||||||
 | 
					    private boolean refundAlways;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Instantiates a new paid signs object
 | 
					     * Instantiates a new paid signs object
 | 
				
			||||||
@@ -58,13 +63,14 @@ public final class PaidSigns extends JavaPlugin {
 | 
				
			|||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public void onEnable() {
 | 
					    public void onEnable() {
 | 
				
			||||||
        setupVault();
 | 
					        setupVault();
 | 
				
			||||||
 | 
					        loadConfig();
 | 
				
			||||||
 | 
					        Translator.loadLanguages(language);
 | 
				
			||||||
        signManager = new PaidSignManager(PaidSignManager.loadSigns());
 | 
					        signManager = new PaidSignManager(PaidSignManager.loadSigns());
 | 
				
			||||||
        TrackedSignManager.loadTrackedSigns();
 | 
					        TrackedSignManager.loadTrackedSigns();
 | 
				
			||||||
        loadConfig();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        PluginManager pluginManager = getServer().getPluginManager();
 | 
					        PluginManager pluginManager = getServer().getPluginManager();
 | 
				
			||||||
        pluginManager.registerEvents(new SignListener(), this);
 | 
					        pluginManager.registerEvents(new SignListener(), this);
 | 
				
			||||||
        pluginManager.registerEvents(new BlockBreakListener(), this);
 | 
					        pluginManager.registerEvents(new SignBreakListener(), this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        registerCommands();
 | 
					        registerCommands();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -79,6 +85,7 @@ public final class PaidSigns extends JavaPlugin {
 | 
				
			|||||||
    public void reload() {
 | 
					    public void reload() {
 | 
				
			||||||
        this.reloadConfig();
 | 
					        this.reloadConfig();
 | 
				
			||||||
        loadConfig();
 | 
					        loadConfig();
 | 
				
			||||||
 | 
					        Translator.loadLanguages(language);
 | 
				
			||||||
        signManager = new PaidSignManager(PaidSignManager.loadSigns());
 | 
					        signManager = new PaidSignManager(PaidSignManager.loadSigns());
 | 
				
			||||||
        TrackedSignManager.loadTrackedSigns();
 | 
					        TrackedSignManager.loadTrackedSigns();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -116,7 +123,7 @@ public final class PaidSigns extends JavaPlugin {
 | 
				
			|||||||
     * @return <p>Whether refunds are currently enabled</p>
 | 
					     * @return <p>Whether refunds are currently enabled</p>
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public boolean areRefundsEnabled() {
 | 
					    public boolean areRefundsEnabled() {
 | 
				
			||||||
        return this.enableRefunds;
 | 
					        return this.refundsEnabled;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@@ -124,7 +131,7 @@ public final class PaidSigns extends JavaPlugin {
 | 
				
			|||||||
     *
 | 
					     *
 | 
				
			||||||
     * @return <p>The percentage of the cost to refund</p>
 | 
					     * @return <p>The percentage of the cost to refund</p>
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public int getRefundPercentage() {
 | 
					    public short getRefundPercentage() {
 | 
				
			||||||
        if (this.refundPercentage < 0) {
 | 
					        if (this.refundPercentage < 0) {
 | 
				
			||||||
            return 0;
 | 
					            return 0;
 | 
				
			||||||
        } else if (refundPercentage > 100) {
 | 
					        } else if (refundPercentage > 100) {
 | 
				
			||||||
@@ -133,6 +140,15 @@ public final class PaidSigns extends JavaPlugin {
 | 
				
			|||||||
        return this.refundPercentage;
 | 
					        return this.refundPercentage;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Gets whether refunds should always happen, even if signs are not broken by players
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return <p>True if refunds should always happen</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public boolean refundAlways() {
 | 
				
			||||||
 | 
					        return this.refundAlways;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Registers the commands used by this plugin
 | 
					     * Registers the commands used by this plugin
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
@@ -140,7 +156,9 @@ public final class PaidSigns extends JavaPlugin {
 | 
				
			|||||||
        registerCommand("addPaidSign", new AddCommand(), new AddTabCompleter());
 | 
					        registerCommand("addPaidSign", new AddCommand(), new AddTabCompleter());
 | 
				
			||||||
        registerCommand("listPaidSigns", new ListCommand(), new ListTabCompleter());
 | 
					        registerCommand("listPaidSigns", new ListCommand(), new ListTabCompleter());
 | 
				
			||||||
        registerCommand("addPaidSignCondition", new AddConditionCommand(), new AddConditionTabCompleter());
 | 
					        registerCommand("addPaidSignCondition", new AddConditionCommand(), new AddConditionTabCompleter());
 | 
				
			||||||
        registerCommand("removePaidSignCondition", new RemoveConditionCommand(), new RemoveConditionTabCompleter());
 | 
					        registerCommand("removePaidSignCondition", new RemoveConditionCommand(),
 | 
				
			||||||
 | 
					                new RemoveConditionTabCompleter());
 | 
				
			||||||
 | 
					        registerCommand("editPaidSign", new EditCommand(), new EditTabCompleter());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        TabExecutor removeTabExecutor = new RemoveTabCommand();
 | 
					        TabExecutor removeTabExecutor = new RemoveTabCommand();
 | 
				
			||||||
        registerCommand("removePaidSign", removeTabExecutor, removeTabExecutor);
 | 
					        registerCommand("removePaidSign", removeTabExecutor, removeTabExecutor);
 | 
				
			||||||
@@ -170,10 +188,13 @@ public final class PaidSigns extends JavaPlugin {
 | 
				
			|||||||
        FileConfiguration config = this.getConfig();
 | 
					        FileConfiguration config = this.getConfig();
 | 
				
			||||||
        config.options().copyDefaults(true);
 | 
					        config.options().copyDefaults(true);
 | 
				
			||||||
        this.saveDefaultConfig();
 | 
					        this.saveDefaultConfig();
 | 
				
			||||||
 | 
					        this.saveConfig();
 | 
				
			||||||
 | 
					        language = config.getString("language", "en");
 | 
				
			||||||
        ignoreCase = config.getBoolean("ignoreCase", true);
 | 
					        ignoreCase = config.getBoolean("ignoreCase", true);
 | 
				
			||||||
        ignoreColor = config.getBoolean("ignoreColor", false);
 | 
					        ignoreColor = config.getBoolean("ignoreColor", false);
 | 
				
			||||||
        enableRefunds = config.getBoolean("enableRefunds", true);
 | 
					        refundsEnabled = config.getBoolean("refundsEnabled", true);
 | 
				
			||||||
        refundPercentage = config.getInt("refundPercentage", 100);
 | 
					        refundPercentage = (short) config.getInt("refundPercentage", 100);
 | 
				
			||||||
 | 
					        refundAlways = config.getBoolean("refundAlways", false);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@@ -185,7 +206,7 @@ public final class PaidSigns extends JavaPlugin {
 | 
				
			|||||||
        if (economyProvider != null) {
 | 
					        if (economyProvider != null) {
 | 
				
			||||||
            EconomyManager.initialize(economyProvider.getProvider());
 | 
					            EconomyManager.initialize(economyProvider.getProvider());
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            throw new IllegalStateException("[PaidSigns] Error: Vault could not be loaded");
 | 
					            throw new IllegalStateException("Error: Vault could not be loaded");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,6 +2,8 @@ package net.knarcraft.paidsigns.command;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import net.knarcraft.paidsigns.PaidSigns;
 | 
					import net.knarcraft.paidsigns.PaidSigns;
 | 
				
			||||||
import net.knarcraft.paidsigns.container.PaidSign;
 | 
					import net.knarcraft.paidsigns.container.PaidSign;
 | 
				
			||||||
 | 
					import net.knarcraft.paidsigns.formatting.StringFormatter;
 | 
				
			||||||
 | 
					import net.knarcraft.paidsigns.formatting.TranslatableMessage;
 | 
				
			||||||
import net.knarcraft.paidsigns.manager.PaidSignManager;
 | 
					import net.knarcraft.paidsigns.manager.PaidSignManager;
 | 
				
			||||||
import net.knarcraft.paidsigns.property.OptionState;
 | 
					import net.knarcraft.paidsigns.property.OptionState;
 | 
				
			||||||
import org.bukkit.command.Command;
 | 
					import org.bukkit.command.Command;
 | 
				
			||||||
@@ -9,9 +11,6 @@ import org.bukkit.command.CommandSender;
 | 
				
			|||||||
import org.jetbrains.annotations.NotNull;
 | 
					import org.jetbrains.annotations.NotNull;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.io.IOException;
 | 
					import java.io.IOException;
 | 
				
			||||||
import java.util.Arrays;
 | 
					 | 
				
			||||||
import java.util.logging.Level;
 | 
					 | 
				
			||||||
import java.util.logging.Logger;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * A representation of the command for adding a new paid sign
 | 
					 * A representation of the command for adding a new paid sign
 | 
				
			||||||
@@ -31,7 +30,7 @@ public class AddCommand extends TokenizedCommand {
 | 
				
			|||||||
        try {
 | 
					        try {
 | 
				
			||||||
            cost = Double.parseDouble(arguments.get(1));
 | 
					            cost = Double.parseDouble(arguments.get(1));
 | 
				
			||||||
        } catch (NumberFormatException exception) {
 | 
					        } catch (NumberFormatException exception) {
 | 
				
			||||||
            sender.sendMessage("You provided an invalid number");
 | 
					            sender.sendMessage(StringFormatter.getTranslatedErrorMessage(TranslatableMessage.ERROR_INVALID_NUMBER));
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        String permission = "";
 | 
					        String permission = "";
 | 
				
			||||||
@@ -46,8 +45,12 @@ public class AddCommand extends TokenizedCommand {
 | 
				
			|||||||
        if (argumentSize > 4) {
 | 
					        if (argumentSize > 4) {
 | 
				
			||||||
            ignoreColor = OptionState.fromString(arguments.get(4));
 | 
					            ignoreColor = OptionState.fromString(arguments.get(4));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        boolean matchAnyCondition = false;
 | 
				
			||||||
 | 
					        if (argumentSize > 5) {
 | 
				
			||||||
 | 
					            matchAnyCondition = Boolean.parseBoolean(arguments.get(5));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return createPaidSign(sender, signName, cost, permission, ignoreCase, ignoreColor);
 | 
					        return createPaidSign(sender, signName, cost, permission, ignoreCase, ignoreColor, matchAnyCondition);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@@ -59,29 +62,27 @@ public class AddCommand extends TokenizedCommand {
 | 
				
			|||||||
     * @param permission        <p>The permission required for creating the sign represented by the paid sign</p>
 | 
					     * @param permission        <p>The permission required for creating the sign represented by the paid sign</p>
 | 
				
			||||||
     * @param ignoreCase        <p>Whether to ignore case for the paid sign's conditions</p>
 | 
					     * @param ignoreCase        <p>Whether to ignore case for the paid sign's conditions</p>
 | 
				
			||||||
     * @param ignoreColor       <p>Whether to ignore color for the paid sign's conditions</p>
 | 
					     * @param ignoreColor       <p>Whether to ignore color for the paid sign's conditions</p>
 | 
				
			||||||
 | 
					     * @param matchAnyCondition <p>Whether to treat any matching condition as a sign match</p>
 | 
				
			||||||
     * @return <p>True if the paid sign was successfully created and registered</p>
 | 
					     * @return <p>True if the paid sign was successfully created and registered</p>
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    private boolean createPaidSign(CommandSender sender, String signName, double cost, String permission,
 | 
					    private boolean createPaidSign(CommandSender sender, String signName, double cost, String permission,
 | 
				
			||||||
                                   OptionState ignoreCase, OptionState ignoreColor) {
 | 
					                                   OptionState ignoreCase, OptionState ignoreColor, boolean matchAnyCondition) {
 | 
				
			||||||
        PaidSignManager manager = PaidSigns.getInstance().getSignManager();
 | 
					        PaidSignManager manager = PaidSigns.getInstance().getSignManager();
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            PaidSign sign = new PaidSign(signName, cost, permission, ignoreCase, ignoreColor);
 | 
					            PaidSign sign = new PaidSign(signName, cost, permission, ignoreCase, ignoreColor, matchAnyCondition);
 | 
				
			||||||
            if (manager.getPaidSign(signName) != null) {
 | 
					            if (manager.getPaidSign(signName) != null) {
 | 
				
			||||||
                sender.sendMessage("A paid sign with the same name already exists");
 | 
					                sender.sendMessage(StringFormatter.getTranslatedErrorMessage(TranslatableMessage.ERROR_NAME_DUPLICATE));
 | 
				
			||||||
                return false;
 | 
					                return false;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            manager.addPaidSign(sign);
 | 
					            manager.addPaidSign(sign);
 | 
				
			||||||
            sender.sendMessage("Successfully added new paid sign");
 | 
					            sender.sendMessage(StringFormatter.getTranslatedInfoMessage(TranslatableMessage.SUCCESS_ADDED_PAID_SIGN));
 | 
				
			||||||
            return true;
 | 
					            return true;
 | 
				
			||||||
        } catch (IOException e) {
 | 
					        } catch (IOException e) {
 | 
				
			||||||
            Logger logger = PaidSigns.getInstance().getLogger();
 | 
					            sender.sendMessage(StringFormatter.getTranslatedErrorMessage(TranslatableMessage.ERROR_EXCEPTION_OCCURRED));
 | 
				
			||||||
            logger.log(Level.SEVERE, "Exception encountered while trying to write " +
 | 
					 | 
				
			||||||
                    "to the data file");
 | 
					 | 
				
			||||||
            logger.log(Level.SEVERE, Arrays.toString(e.getStackTrace()));
 | 
					 | 
				
			||||||
            sender.sendMessage("An exception occurred. Please notify the server administrator or check the server log.");
 | 
					 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        } catch (IllegalArgumentException e) {
 | 
					        } catch (IllegalArgumentException e) {
 | 
				
			||||||
            sender.sendMessage("Invalid input: " + e.getMessage());
 | 
					            sender.sendMessage(StringFormatter.replacePlaceholder(StringFormatter.getTranslatedErrorMessage(
 | 
				
			||||||
 | 
					                    TranslatableMessage.ERROR_INVALID_INPUT), "{input}", e.getMessage()));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,6 +2,8 @@ package net.knarcraft.paidsigns.command;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import net.knarcraft.paidsigns.PaidSigns;
 | 
					import net.knarcraft.paidsigns.PaidSigns;
 | 
				
			||||||
import net.knarcraft.paidsigns.container.PaidSign;
 | 
					import net.knarcraft.paidsigns.container.PaidSign;
 | 
				
			||||||
 | 
					import net.knarcraft.paidsigns.formatting.StringFormatter;
 | 
				
			||||||
 | 
					import net.knarcraft.paidsigns.formatting.TranslatableMessage;
 | 
				
			||||||
import net.knarcraft.paidsigns.manager.PaidSignManager;
 | 
					import net.knarcraft.paidsigns.manager.PaidSignManager;
 | 
				
			||||||
import net.knarcraft.paidsigns.property.OptionState;
 | 
					import net.knarcraft.paidsigns.property.OptionState;
 | 
				
			||||||
import org.bukkit.command.Command;
 | 
					import org.bukkit.command.Command;
 | 
				
			||||||
@@ -9,9 +11,6 @@ import org.bukkit.command.CommandSender;
 | 
				
			|||||||
import org.jetbrains.annotations.NotNull;
 | 
					import org.jetbrains.annotations.NotNull;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.io.IOException;
 | 
					import java.io.IOException;
 | 
				
			||||||
import java.util.Arrays;
 | 
					 | 
				
			||||||
import java.util.logging.Level;
 | 
					 | 
				
			||||||
import java.util.logging.Logger;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * A representation of the command for adding a new match condition for a sign
 | 
					 * A representation of the command for adding a new match condition for a sign
 | 
				
			||||||
@@ -19,7 +18,8 @@ import java.util.logging.Logger;
 | 
				
			|||||||
public class AddConditionCommand extends TokenizedCommand {
 | 
					public class AddConditionCommand extends TokenizedCommand {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
 | 
					    public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label,
 | 
				
			||||||
 | 
					                             @NotNull String[] args) {
 | 
				
			||||||
        super.onCommand(sender, command, label, args);
 | 
					        super.onCommand(sender, command, label, args);
 | 
				
			||||||
        if (argumentSize < 3) {
 | 
					        if (argumentSize < 3) {
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
@@ -29,14 +29,21 @@ public class AddConditionCommand extends TokenizedCommand {
 | 
				
			|||||||
        short lineNumber;
 | 
					        short lineNumber;
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            lineNumber = (short) (Short.parseShort(arguments.get(1)) - 1);
 | 
					            lineNumber = (short) (Short.parseShort(arguments.get(1)) - 1);
 | 
				
			||||||
 | 
					            if (lineNumber < 0 || lineNumber > 3) {
 | 
				
			||||||
 | 
					                sender.sendMessage(StringFormatter.getTranslatedErrorMessage(TranslatableMessage.ERROR_INVALID_NUMBER));
 | 
				
			||||||
 | 
					                return false;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        } catch (NumberFormatException exception) {
 | 
					        } catch (NumberFormatException exception) {
 | 
				
			||||||
            sender.sendMessage("Invalid line number given");
 | 
					            sender.sendMessage(StringFormatter.getTranslatedErrorMessage(TranslatableMessage.ERROR_INVALID_NUMBER));
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        String stringToMatch = arguments.get(2);
 | 
					        String stringToMatch = arguments.get(2);
 | 
				
			||||||
        boolean executeRegEx = false;
 | 
					        boolean executeRegEx = false;
 | 
				
			||||||
        if (argumentSize > 3) {
 | 
					        if (argumentSize > 3) {
 | 
				
			||||||
            executeRegEx = Boolean.parseBoolean(arguments.get(3));
 | 
					            executeRegEx = Boolean.parseBoolean(arguments.get(3));
 | 
				
			||||||
 | 
					            if (executeRegEx && isRegExInvalid(sender, stringToMatch)) {
 | 
				
			||||||
 | 
					                return false;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        OptionState ignoreCase = OptionState.DEFAULT;
 | 
					        OptionState ignoreCase = OptionState.DEFAULT;
 | 
				
			||||||
        if (argumentSize > 4) {
 | 
					        if (argumentSize > 4) {
 | 
				
			||||||
@@ -46,23 +53,38 @@ public class AddConditionCommand extends TokenizedCommand {
 | 
				
			|||||||
        if (argumentSize > 5) {
 | 
					        if (argumentSize > 5) {
 | 
				
			||||||
            ignoreColor = OptionState.getFromBoolean(Boolean.parseBoolean(arguments.get(5)));
 | 
					            ignoreColor = OptionState.getFromBoolean(Boolean.parseBoolean(arguments.get(5)));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        return addCondition(name, lineNumber, stringToMatch, executeRegEx, ignoreCase, ignoreColor, sender);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Uses the given input to add a paid sign condition
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param name          <p>The name of the paid sign to add the condition to</p>
 | 
				
			||||||
 | 
					     * @param lineNumber    <p>The sign line the condition should check</p>
 | 
				
			||||||
 | 
					     * @param stringToMatch <p>The string to look for on created signs</p>
 | 
				
			||||||
 | 
					     * @param executeRegEx  <p>Whether to treat the match string as a regular expression</p>
 | 
				
			||||||
 | 
					     * @param ignoreCase    <p>Whether to ignore case when matching</p>
 | 
				
			||||||
 | 
					     * @param ignoreColor   <p>Whether to ignore color when matching</p>
 | 
				
			||||||
 | 
					     * @param sender        <p>The command sender to notify when finished</p>
 | 
				
			||||||
 | 
					     * @return <p>True if the condition was successfully added</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private boolean addCondition(String name, short lineNumber, String stringToMatch, boolean executeRegEx,
 | 
				
			||||||
 | 
					                                 OptionState ignoreCase, OptionState ignoreColor, CommandSender sender) {
 | 
				
			||||||
        PaidSignManager signManager = PaidSigns.getInstance().getSignManager();
 | 
					        PaidSignManager signManager = PaidSigns.getInstance().getSignManager();
 | 
				
			||||||
        PaidSign sign = signManager.getPaidSign(name);
 | 
					        PaidSign sign = signManager.getPaidSign(name);
 | 
				
			||||||
        if (sign == null) {
 | 
					        if (sign == null) {
 | 
				
			||||||
            sender.sendMessage("No such paid sign exists");
 | 
					            sender.sendMessage(StringFormatter.getTranslatedErrorMessage(TranslatableMessage.ERROR_PAID_SIGN_NOT_FOUND));
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        sign.addCondition(lineNumber, stringToMatch, executeRegEx, ignoreCase, ignoreColor);
 | 
					        sign.addCondition(lineNumber, stringToMatch, executeRegEx, ignoreCase, ignoreColor);
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            signManager.saveSigns();
 | 
					            signManager.saveSigns();
 | 
				
			||||||
        } catch (IOException e) {
 | 
					        } catch (IOException e) {
 | 
				
			||||||
            Logger logger = PaidSigns.getInstance().getLogger();
 | 
					            sender.sendMessage(StringFormatter.getTranslatedErrorMessage(TranslatableMessage.ERROR_EXCEPTION_OCCURRED));
 | 
				
			||||||
            logger.log(Level.SEVERE, "Exception encountered while trying to write to the data file");
 | 
					 | 
				
			||||||
            logger.log(Level.SEVERE, Arrays.toString(e.getStackTrace()));
 | 
					 | 
				
			||||||
            sender.sendMessage("An exception occurred. Please notify the server administrator or check the server log.");
 | 
					 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        sender.sendMessage("Condition added");
 | 
					        sender.sendMessage(StringFormatter.getTranslatedInfoMessage(
 | 
				
			||||||
 | 
					                TranslatableMessage.SUCCESS_ADDED_PAID_SIGN_CONDITION));
 | 
				
			||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,18 +1,13 @@
 | 
				
			|||||||
package net.knarcraft.paidsigns.command;
 | 
					package net.knarcraft.paidsigns.command;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import net.knarcraft.paidsigns.utility.TabCompleteHelper;
 | 
					import net.knarcraft.paidsigns.utility.TabCompleteHelper;
 | 
				
			||||||
import org.bukkit.Bukkit;
 | 
					 | 
				
			||||||
import org.bukkit.command.Command;
 | 
					import org.bukkit.command.Command;
 | 
				
			||||||
import org.bukkit.command.CommandSender;
 | 
					import org.bukkit.command.CommandSender;
 | 
				
			||||||
import org.bukkit.permissions.Permission;
 | 
					 | 
				
			||||||
import org.jetbrains.annotations.NotNull;
 | 
					import org.jetbrains.annotations.NotNull;
 | 
				
			||||||
import org.jetbrains.annotations.Nullable;
 | 
					import org.jetbrains.annotations.Nullable;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.util.ArrayList;
 | 
					import java.util.ArrayList;
 | 
				
			||||||
import java.util.HashMap;
 | 
					 | 
				
			||||||
import java.util.List;
 | 
					import java.util.List;
 | 
				
			||||||
import java.util.Map;
 | 
					 | 
				
			||||||
import java.util.StringJoiner;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * The tab completer for the add paid sign command
 | 
					 * The tab completer for the add paid sign command
 | 
				
			||||||
@@ -21,9 +16,8 @@ public class AddTabCompleter extends TokenizedTabCompleter {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    private static List<String> names;
 | 
					    private static List<String> names;
 | 
				
			||||||
    private static List<String> costs;
 | 
					    private static List<String> costs;
 | 
				
			||||||
    private static List<String> plugins;
 | 
					 | 
				
			||||||
    private static Map<String, List<String>> permissions;
 | 
					 | 
				
			||||||
    private static List<String> options;
 | 
					    private static List<String> options;
 | 
				
			||||||
 | 
					    private static List<String> booleans;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Nullable
 | 
					    @Nullable
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
@@ -32,7 +26,6 @@ public class AddTabCompleter extends TokenizedTabCompleter {
 | 
				
			|||||||
        super.onTabComplete(sender, command, alias, args);
 | 
					        super.onTabComplete(sender, command, alias, args);
 | 
				
			||||||
        if (names == null) {
 | 
					        if (names == null) {
 | 
				
			||||||
            initializeValues();
 | 
					            initializeValues();
 | 
				
			||||||
            loadAvailablePermissions();
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (argumentSize == 1) {
 | 
					        if (argumentSize == 1) {
 | 
				
			||||||
@@ -40,90 +33,17 @@ public class AddTabCompleter extends TokenizedTabCompleter {
 | 
				
			|||||||
        } else if (argumentSize == 2) {
 | 
					        } else if (argumentSize == 2) {
 | 
				
			||||||
            return TabCompleteHelper.filterMatchingStartsWith(costs, arguments.get(1));
 | 
					            return TabCompleteHelper.filterMatchingStartsWith(costs, arguments.get(1));
 | 
				
			||||||
        } else if (argumentSize == 3) {
 | 
					        } else if (argumentSize == 3) {
 | 
				
			||||||
            return tabCompletePermission(arguments.get(arguments.size() - 1));
 | 
					            return TabCompleteHelper.tabCompletePermission(arguments.get(arguments.size() - 1));
 | 
				
			||||||
        } else if (argumentSize == 4) {
 | 
					        } else if (argumentSize == 4) {
 | 
				
			||||||
            return TabCompleteHelper.filterMatchingStartsWith(options, arguments.get(3));
 | 
					            return TabCompleteHelper.filterMatchingStartsWith(options, arguments.get(3));
 | 
				
			||||||
        } else if (argumentSize == 5) {
 | 
					        } else if (argumentSize == 5) {
 | 
				
			||||||
            return TabCompleteHelper.filterMatchingStartsWith(options, arguments.get(4));
 | 
					            return TabCompleteHelper.filterMatchingStartsWith(options, arguments.get(4));
 | 
				
			||||||
 | 
					        } else if (argumentSize == 6) {
 | 
				
			||||||
 | 
					            return TabCompleteHelper.filterMatchingStartsWith(booleans, arguments.get(5));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return new ArrayList<>();
 | 
					        return new ArrayList<>();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Gets the tab complete value for the permission typed
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @param typedNode <p>The full permission node typed by the player</p>
 | 
					 | 
				
			||||||
     * @return <p>All known valid auto-complete options</p>
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    private List<String> tabCompletePermission(String typedNode) {
 | 
					 | 
				
			||||||
        List<String> output;
 | 
					 | 
				
			||||||
        if (typedNode.contains(".")) {
 | 
					 | 
				
			||||||
            List<String> matchingPermissions = permissions.get(typedNode.substring(0, typedNode.lastIndexOf(".")));
 | 
					 | 
				
			||||||
            if (matchingPermissions == null) {
 | 
					 | 
				
			||||||
                output = new ArrayList<>();
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                //Filter by the typed text
 | 
					 | 
				
			||||||
                output = filterMatching(matchingPermissions, typedNode);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            output = plugins;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        //Add previous permissions in the comma-separated lists as a prefix
 | 
					 | 
				
			||||||
        return output;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Find completable strings which match the text typed by the command's sender
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @param values    <p>The values to filter</p>
 | 
					 | 
				
			||||||
     * @param typedText <p>The text the player has started typing</p>
 | 
					 | 
				
			||||||
     * @return <p>The given string values which start with the player's typed text</p>
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    private List<String> filterMatching(List<String> values, String typedText) {
 | 
					 | 
				
			||||||
        List<String> configValues = new ArrayList<>();
 | 
					 | 
				
			||||||
        for (String value : values) {
 | 
					 | 
				
			||||||
            if (value.toLowerCase().startsWith(typedText.toLowerCase())) {
 | 
					 | 
				
			||||||
                configValues.add(value);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        return configValues;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Loads all permissions available from bukkit plugins
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    private static void loadAvailablePermissions() {
 | 
					 | 
				
			||||||
        plugins = new ArrayList<>();
 | 
					 | 
				
			||||||
        permissions = new HashMap<>();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for (Permission permission : Bukkit.getPluginManager().getPermissions()) {
 | 
					 | 
				
			||||||
            loadPermission(permission.getName());
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Loads a given permission into the proper lists and maps
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @param permissionName <p>The permission to load</p>
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    private static void loadPermission(String permissionName) {
 | 
					 | 
				
			||||||
        String[] permissionParts = permissionName.split("\\.");
 | 
					 | 
				
			||||||
        if (permissionParts.length == 1 && !plugins.contains(permissionParts[0])) {
 | 
					 | 
				
			||||||
            plugins.add(permissionParts[0]);
 | 
					 | 
				
			||||||
        } else if (permissionParts.length > 1) {
 | 
					 | 
				
			||||||
            StringJoiner pathJoiner = new StringJoiner(".");
 | 
					 | 
				
			||||||
            for (int j = 0; j < permissionParts.length - 1; j++) {
 | 
					 | 
				
			||||||
                pathJoiner.add(permissionParts[j]);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            String path = pathJoiner.toString();
 | 
					 | 
				
			||||||
            List<String> permissionList = permissions.computeIfAbsent(path, k -> new ArrayList<>());
 | 
					 | 
				
			||||||
            permissionList.add(permissionName);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            loadPermission(path);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Initializes the values available for tab completion
 | 
					     * Initializes the values available for tab completion
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
@@ -131,6 +51,7 @@ public class AddTabCompleter extends TokenizedTabCompleter {
 | 
				
			|||||||
        names = TabCompleteHelper.getExamplePaidSignNames();
 | 
					        names = TabCompleteHelper.getExamplePaidSignNames();
 | 
				
			||||||
        costs = TabCompleteHelper.getCosts();
 | 
					        costs = TabCompleteHelper.getCosts();
 | 
				
			||||||
        options = TabCompleteHelper.getOptionStates();
 | 
					        options = TabCompleteHelper.getOptionStates();
 | 
				
			||||||
 | 
					        booleans = TabCompleteHelper.getBooleans();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										186
									
								
								src/main/java/net/knarcraft/paidsigns/command/EditCommand.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										186
									
								
								src/main/java/net/knarcraft/paidsigns/command/EditCommand.java
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,186 @@
 | 
				
			|||||||
 | 
					package net.knarcraft.paidsigns.command;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import net.knarcraft.paidsigns.PaidSigns;
 | 
				
			||||||
 | 
					import net.knarcraft.paidsigns.container.PaidSign;
 | 
				
			||||||
 | 
					import net.knarcraft.paidsigns.container.PaidSignCondition;
 | 
				
			||||||
 | 
					import net.knarcraft.paidsigns.formatting.StringFormatter;
 | 
				
			||||||
 | 
					import net.knarcraft.paidsigns.formatting.TranslatableMessage;
 | 
				
			||||||
 | 
					import net.knarcraft.paidsigns.manager.PaidSignManager;
 | 
				
			||||||
 | 
					import net.knarcraft.paidsigns.property.OptionState;
 | 
				
			||||||
 | 
					import net.knarcraft.paidsigns.property.PaidSignConditionProperty;
 | 
				
			||||||
 | 
					import net.knarcraft.paidsigns.property.PaidSignProperty;
 | 
				
			||||||
 | 
					import org.bukkit.command.Command;
 | 
				
			||||||
 | 
					import org.bukkit.command.CommandSender;
 | 
				
			||||||
 | 
					import org.jetbrains.annotations.NotNull;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.io.IOException;
 | 
				
			||||||
 | 
					import java.util.Map;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * A representation of the command for editing a new paid sign
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					public class EditCommand extends TokenizedCommand {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label,
 | 
				
			||||||
 | 
					                             @NotNull String[] args) {
 | 
				
			||||||
 | 
					        super.onCommand(sender, command, label, args);
 | 
				
			||||||
 | 
					        if (argumentSize < 3) {
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        PaidSign sign = PaidSigns.getInstance().getSignManager().getPaidSign(arguments.get(0));
 | 
				
			||||||
 | 
					        if (sign == null) {
 | 
				
			||||||
 | 
					            sender.sendMessage(StringFormatter.getTranslatedErrorMessage(TranslatableMessage.ERROR_PAID_SIGN_NOT_FOUND));
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            try {
 | 
				
			||||||
 | 
					                //First, assume a condition is changed
 | 
				
			||||||
 | 
					                return parseGivenConditionLine(sign, sender);
 | 
				
			||||||
 | 
					            } catch (NumberFormatException exception) {
 | 
				
			||||||
 | 
					                //Fall back to assume a sign is changed
 | 
				
			||||||
 | 
					                return parseGivenProperty(sign, sender);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } catch (IOException e) {
 | 
				
			||||||
 | 
					            sender.sendMessage(StringFormatter.getTranslatedErrorMessage(TranslatableMessage.ERROR_EXCEPTION_OCCURRED));
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Parses the given condition line and the rest of the input
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param sign   <p>The paid sign the user is trying to edit</p>
 | 
				
			||||||
 | 
					     * @param sender <p>The command sender to notify of any errors</p>
 | 
				
			||||||
 | 
					     * @return <p>True if the command was executed successfully</p>
 | 
				
			||||||
 | 
					     * @throws NumberFormatException <p>If the given argument is not a number</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private boolean parseGivenConditionLine(@NotNull PaidSign sign,
 | 
				
			||||||
 | 
					                                            @NotNull CommandSender sender) throws NumberFormatException {
 | 
				
			||||||
 | 
					        short signLine = (short) (Short.parseShort(arguments.get(1)) - 1);
 | 
				
			||||||
 | 
					        if (signLine < 0 || signLine > 3 || sign.getConditions().get(signLine) == null) {
 | 
				
			||||||
 | 
					            sender.sendMessage(StringFormatter.getTranslatedErrorMessage(TranslatableMessage.ERROR_NO_SUCH_CONDITION));
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (argumentSize < 4) {
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        PaidSignConditionProperty conditionProperty = PaidSignConditionProperty.getFromString(arguments.get(2));
 | 
				
			||||||
 | 
					        if (conditionProperty == null) {
 | 
				
			||||||
 | 
					            sender.sendMessage(StringFormatter.getTranslatedErrorMessage(
 | 
				
			||||||
 | 
					                    TranslatableMessage.ERROR_PROPERTY_NOT_RECOGNIZED));
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        String value = arguments.get(3);
 | 
				
			||||||
 | 
					        return updateConditionProperty(sender, sign, signLine, conditionProperty, value);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Parses the given paid sign property and the rest of the input
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param sign   <p>The paid sign the user is trying to edit</p>
 | 
				
			||||||
 | 
					     * @param sender <p>The command sender to notify of any errors</p>
 | 
				
			||||||
 | 
					     * @return <p>True if the command was executed successfully</p>
 | 
				
			||||||
 | 
					     * @throws IOException <p>If unable to remove or save the sign</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private boolean parseGivenProperty(@NotNull PaidSign sign,
 | 
				
			||||||
 | 
					                                       @NotNull CommandSender sender) throws IOException {
 | 
				
			||||||
 | 
					        PaidSignProperty property = PaidSignProperty.getFromString(arguments.get(1));
 | 
				
			||||||
 | 
					        if (property == null) {
 | 
				
			||||||
 | 
					            sender.sendMessage(StringFormatter.getTranslatedErrorMessage(
 | 
				
			||||||
 | 
					                    TranslatableMessage.ERROR_PROPERTY_NOT_RECOGNIZED));
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        String value = arguments.get(2);
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            updateProperty(sender, sign, property, value);
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        } catch (NumberFormatException exception) {
 | 
				
			||||||
 | 
					            sender.sendMessage(StringFormatter.getTranslatedErrorMessage(TranslatableMessage.ERROR_INVALID_NUMBER));
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Updates a property for a paid sign
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param sender   <p>The command sender to notify of any errors or success</p>
 | 
				
			||||||
 | 
					     * @param sign     <p>The sign to be updated</p>
 | 
				
			||||||
 | 
					     * @param property <p>The property to update</p>
 | 
				
			||||||
 | 
					     * @param newValue <p>The new value of the property</p>
 | 
				
			||||||
 | 
					     * @throws IOException <p>If unable to remove or save the sign</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private void updateProperty(CommandSender sender, PaidSign sign, PaidSignProperty property,
 | 
				
			||||||
 | 
					                                String newValue) throws IOException {
 | 
				
			||||||
 | 
					        String signName = property == PaidSignProperty.NAME ? newValue : sign.getName();
 | 
				
			||||||
 | 
					        OptionState ignoreCase = property == PaidSignProperty.IGNORE_CASE ? OptionState.fromString(newValue) :
 | 
				
			||||||
 | 
					                OptionState.getFromBoolean(sign.getIgnoreCase());
 | 
				
			||||||
 | 
					        OptionState ignoreColor = property == PaidSignProperty.IGNORE_COLOR ? OptionState.fromString(newValue) :
 | 
				
			||||||
 | 
					                OptionState.getFromBoolean(sign.getIgnoreColor());
 | 
				
			||||||
 | 
					        boolean matchAnyCondition = property == PaidSignProperty.MATCH_ANY_CONDITION ? Boolean.parseBoolean(newValue) :
 | 
				
			||||||
 | 
					                sign.matchAnyCondition();
 | 
				
			||||||
 | 
					        double cost = property == PaidSignProperty.COST ? Double.parseDouble(newValue) : sign.getCost();
 | 
				
			||||||
 | 
					        String permission = property == PaidSignProperty.PERMISSION ? newValue : sign.getPermission();
 | 
				
			||||||
 | 
					        Map<Short, PaidSignCondition> conditions = sign.getConditions();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        PaidSignManager manager = PaidSigns.getInstance().getSignManager();
 | 
				
			||||||
 | 
					        PaidSign updatedSign = new PaidSign(signName, cost, permission, ignoreCase, ignoreColor, matchAnyCondition);
 | 
				
			||||||
 | 
					        for (short line : conditions.keySet()) {
 | 
				
			||||||
 | 
					            PaidSignCondition condition = conditions.get(line);
 | 
				
			||||||
 | 
					            updatedSign.addCondition(line, condition.getStringToMatch(), condition.executeRegex(),
 | 
				
			||||||
 | 
					                    OptionState.getFromBoolean(condition.ignoreCase()),
 | 
				
			||||||
 | 
					                    OptionState.getFromBoolean(condition.ignoreColor()));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        manager.removePaidSign(sign.getName());
 | 
				
			||||||
 | 
					        manager.addPaidSign(updatedSign);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        sender.sendMessage(StringFormatter.getTranslatedInfoMessage(TranslatableMessage.SUCCESS_UPDATED_PAID_SIGN));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Updates a property of a condition of a paid sign
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param sender         <p>The command sender to notify of any errors or success</p>
 | 
				
			||||||
 | 
					     * @param sign           <p>The sign the condition belongs to</p>
 | 
				
			||||||
 | 
					     * @param conditionIndex <p>The line index that identifies the sign condition</p>
 | 
				
			||||||
 | 
					     * @param property       <p>The condition property to update</p>
 | 
				
			||||||
 | 
					     * @param newValue       <p>The new value of the property</p>
 | 
				
			||||||
 | 
					     * @return <p>True if the property was successfully changed</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private boolean updateConditionProperty(CommandSender sender, PaidSign sign, short conditionIndex,
 | 
				
			||||||
 | 
					                                            PaidSignConditionProperty property, String newValue) {
 | 
				
			||||||
 | 
					        PaidSignCondition condition = sign.getConditions().get(conditionIndex);
 | 
				
			||||||
 | 
					        String stringToMatch = property == PaidSignConditionProperty.STRING_TO_MATCH ? newValue :
 | 
				
			||||||
 | 
					                condition.getStringToMatch();
 | 
				
			||||||
 | 
					        boolean executeRegEx = property == PaidSignConditionProperty.EXECUTE_REG_EX ? Boolean.parseBoolean(newValue) :
 | 
				
			||||||
 | 
					                condition.executeRegex();
 | 
				
			||||||
 | 
					        boolean ignoreCase = property == PaidSignConditionProperty.IGNORE_CASE ? OptionState.getBooleanValue(
 | 
				
			||||||
 | 
					                OptionState.fromString(newValue), sign.getIgnoreCase()) : condition.ignoreCase();
 | 
				
			||||||
 | 
					        boolean ignoreColor = property == PaidSignConditionProperty.IGNORE_COLOR ? OptionState.getBooleanValue(
 | 
				
			||||||
 | 
					                OptionState.fromString(newValue), sign.getIgnoreColor()) : condition.ignoreColor();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //Make sure to test the regular expression in case anything changed
 | 
				
			||||||
 | 
					        if (executeRegEx && isRegExInvalid(sender, stringToMatch)) {
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        sign.addCondition(conditionIndex, stringToMatch, executeRegEx, OptionState.getFromBoolean(ignoreCase),
 | 
				
			||||||
 | 
					                OptionState.getFromBoolean(ignoreColor));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            PaidSigns.getInstance().getSignManager().saveSigns();
 | 
				
			||||||
 | 
					        } catch (IOException e) {
 | 
				
			||||||
 | 
					            sender.sendMessage(StringFormatter.getTranslatedErrorMessage(TranslatableMessage.ERROR_EXCEPTION_OCCURRED));
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        sender.sendMessage(StringFormatter.getTranslatedInfoMessage(
 | 
				
			||||||
 | 
					                TranslatableMessage.SUCCESS_UPDATED_PAID_SIGN_CONDITION));
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -0,0 +1,176 @@
 | 
				
			|||||||
 | 
					package net.knarcraft.paidsigns.command;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import net.knarcraft.paidsigns.PaidSigns;
 | 
				
			||||||
 | 
					import net.knarcraft.paidsigns.container.PaidSign;
 | 
				
			||||||
 | 
					import net.knarcraft.paidsigns.property.PaidSignConditionProperty;
 | 
				
			||||||
 | 
					import net.knarcraft.paidsigns.property.PaidSignProperty;
 | 
				
			||||||
 | 
					import net.knarcraft.paidsigns.utility.TabCompleteHelper;
 | 
				
			||||||
 | 
					import org.bukkit.command.Command;
 | 
				
			||||||
 | 
					import org.bukkit.command.CommandSender;
 | 
				
			||||||
 | 
					import org.jetbrains.annotations.NotNull;
 | 
				
			||||||
 | 
					import org.jetbrains.annotations.Nullable;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.util.ArrayList;
 | 
				
			||||||
 | 
					import java.util.HashMap;
 | 
				
			||||||
 | 
					import java.util.List;
 | 
				
			||||||
 | 
					import java.util.Map;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * The tab completer for the edit paid sign command
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					public class EditTabCompleter extends TokenizedTabCompleter {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private static Map<PaidSignProperty, List<String>> propertyExampleValues;
 | 
				
			||||||
 | 
					    private static Map<PaidSignConditionProperty, List<String>> conditionPropertyExampleValues;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Nullable
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label,
 | 
				
			||||||
 | 
					                                      @NotNull String[] args) {
 | 
				
			||||||
 | 
					        super.onTabComplete(sender, command, label, args);
 | 
				
			||||||
 | 
					        if (propertyExampleValues == null) {
 | 
				
			||||||
 | 
					            initializePropertyExampleValues();
 | 
				
			||||||
 | 
					            initializeConditionPropertyExampleValues();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (argumentSize == 1) {
 | 
				
			||||||
 | 
					            return TabCompleteHelper.filterMatchingStartsWith(TabCompleteHelper.getPaidSignNames(), arguments.get(0));
 | 
				
			||||||
 | 
					        } else if (argumentSize >= 2) {
 | 
				
			||||||
 | 
					            PaidSign sign = PaidSigns.getInstance().getSignManager().getPaidSign(arguments.get(0));
 | 
				
			||||||
 | 
					            if (sign != null) {
 | 
				
			||||||
 | 
					                return tabCompleteForSign(sign);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return new ArrayList<>();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Returns tab completions for the given, non-null sign
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param sign <p>The sign to tab complete for</p>
 | 
				
			||||||
 | 
					     * @return <p>The tab complete options to give to users</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private List<String> tabCompleteForSign(@NotNull PaidSign sign) {
 | 
				
			||||||
 | 
					        if (argumentSize == 2) {
 | 
				
			||||||
 | 
					            List<String> conditions = getAvailableSignConditions(sign);
 | 
				
			||||||
 | 
					            conditions.addAll(getPaidSignProperties());
 | 
				
			||||||
 | 
					            return TabCompleteHelper.filterMatchingStartsWith(conditions, arguments.get(1));
 | 
				
			||||||
 | 
					        } else if (argumentSize >= 3) {
 | 
				
			||||||
 | 
					            try {
 | 
				
			||||||
 | 
					                return tabCompleteSignLine(sign);
 | 
				
			||||||
 | 
					            } catch (NumberFormatException exception) {
 | 
				
			||||||
 | 
					                if (argumentSize == 3) {
 | 
				
			||||||
 | 
					                    return tabCompleteProperty();
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return new ArrayList<>();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Returns tab completions for the selected sign line
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param sign <p>The paid sign the line belongs to</p>
 | 
				
			||||||
 | 
					     * @return <p>The tab complete options to give to users</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private List<String> tabCompleteSignLine(@NotNull PaidSign sign) {
 | 
				
			||||||
 | 
					        short signLine = (short) (Short.parseShort(arguments.get(1)) - 1);
 | 
				
			||||||
 | 
					        //Refuse to autocomplete if invalid input is given
 | 
				
			||||||
 | 
					        if (signLine < 0 || signLine > 3 || sign.getConditions().get(signLine) == null) {
 | 
				
			||||||
 | 
					            return new ArrayList<>();
 | 
				
			||||||
 | 
					        } else if (argumentSize == 3) {
 | 
				
			||||||
 | 
					            return TabCompleteHelper.filterMatchingStartsWith(getPaidSignConditionProperties(), arguments.get(2));
 | 
				
			||||||
 | 
					        } else if (argumentSize == 4) {
 | 
				
			||||||
 | 
					            PaidSignConditionProperty property = PaidSignConditionProperty.getFromString(arguments.get(2));
 | 
				
			||||||
 | 
					            if (property != null) {
 | 
				
			||||||
 | 
					                return TabCompleteHelper.filterMatchingStartsWith(conditionPropertyExampleValues.get(property),
 | 
				
			||||||
 | 
					                        arguments.get(3));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return new ArrayList<>();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Returns tab completions for the selected property
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return <p>The tab complete options to give to users</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private List<String> tabCompleteProperty() {
 | 
				
			||||||
 | 
					        PaidSignProperty paidSignProperty = PaidSignProperty.getFromString(arguments.get(1));
 | 
				
			||||||
 | 
					        if (paidSignProperty != null) {
 | 
				
			||||||
 | 
					            if (paidSignProperty == PaidSignProperty.PERMISSION) {
 | 
				
			||||||
 | 
					                return TabCompleteHelper.tabCompletePermission(arguments.get(2));
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                return TabCompleteHelper.filterMatchingStartsWith(propertyExampleValues.get(paidSignProperty),
 | 
				
			||||||
 | 
					                        arguments.get(2));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            return new ArrayList<>();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Gets all paid sign condition properties
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return <p>All paid sign condition properties</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private List<String> getPaidSignConditionProperties() {
 | 
				
			||||||
 | 
					        List<String> properties = new ArrayList<>();
 | 
				
			||||||
 | 
					        for (PaidSignConditionProperty property : PaidSignConditionProperty.values()) {
 | 
				
			||||||
 | 
					            properties.add(property.getStringRepresentation());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return properties;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Gets all paid sign properties
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return <p>All paid sign properties</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private List<String> getPaidSignProperties() {
 | 
				
			||||||
 | 
					        List<String> properties = new ArrayList<>();
 | 
				
			||||||
 | 
					        for (PaidSignProperty property : PaidSignProperty.values()) {
 | 
				
			||||||
 | 
					            properties.add(property.getStringRepresentation());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return properties;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Gets all sign conditions available for the given sign
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param sign <p>The sign to get available sign conditions for</p>
 | 
				
			||||||
 | 
					     * @return <p>The available sign conditions</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private List<String> getAvailableSignConditions(PaidSign sign) {
 | 
				
			||||||
 | 
					        List<String> availableConditions = new ArrayList<>();
 | 
				
			||||||
 | 
					        for (Short signLine : sign.getConditions().keySet()) {
 | 
				
			||||||
 | 
					            availableConditions.add(String.valueOf(signLine + 1));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return availableConditions;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Initializes the map for paid sign property example tab completions
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private void initializePropertyExampleValues() {
 | 
				
			||||||
 | 
					        propertyExampleValues = new HashMap<>();
 | 
				
			||||||
 | 
					        propertyExampleValues.put(PaidSignProperty.COST, TabCompleteHelper.getCosts());
 | 
				
			||||||
 | 
					        propertyExampleValues.put(PaidSignProperty.NAME, TabCompleteHelper.getPaidSignNames());
 | 
				
			||||||
 | 
					        propertyExampleValues.put(PaidSignProperty.IGNORE_CASE, TabCompleteHelper.getOptionStates());
 | 
				
			||||||
 | 
					        propertyExampleValues.put(PaidSignProperty.IGNORE_COLOR, TabCompleteHelper.getOptionStates());
 | 
				
			||||||
 | 
					        propertyExampleValues.put(PaidSignProperty.MATCH_ANY_CONDITION, TabCompleteHelper.getBooleans());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Initializes the map for paid sign condition property example tab completions
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private void initializeConditionPropertyExampleValues() {
 | 
				
			||||||
 | 
					        conditionPropertyExampleValues = new HashMap<>();
 | 
				
			||||||
 | 
					        conditionPropertyExampleValues.put(PaidSignConditionProperty.STRING_TO_MATCH,
 | 
				
			||||||
 | 
					                TabCompleteHelper.getExampleConditionStrings());
 | 
				
			||||||
 | 
					        conditionPropertyExampleValues.put(PaidSignConditionProperty.IGNORE_COLOR, TabCompleteHelper.getOptionStates());
 | 
				
			||||||
 | 
					        conditionPropertyExampleValues.put(PaidSignConditionProperty.IGNORE_CASE, TabCompleteHelper.getOptionStates());
 | 
				
			||||||
 | 
					        conditionPropertyExampleValues.put(PaidSignConditionProperty.EXECUTE_REG_EX, TabCompleteHelper.getBooleans());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -3,12 +3,20 @@ package net.knarcraft.paidsigns.command;
 | 
				
			|||||||
import net.knarcraft.paidsigns.PaidSigns;
 | 
					import net.knarcraft.paidsigns.PaidSigns;
 | 
				
			||||||
import net.knarcraft.paidsigns.container.PaidSign;
 | 
					import net.knarcraft.paidsigns.container.PaidSign;
 | 
				
			||||||
import net.knarcraft.paidsigns.container.PaidSignCondition;
 | 
					import net.knarcraft.paidsigns.container.PaidSignCondition;
 | 
				
			||||||
 | 
					import net.knarcraft.paidsigns.formatting.StringFormatter;
 | 
				
			||||||
 | 
					import net.knarcraft.paidsigns.formatting.TranslatableMessage;
 | 
				
			||||||
 | 
					import net.knarcraft.paidsigns.formatting.Translator;
 | 
				
			||||||
import org.bukkit.command.Command;
 | 
					import org.bukkit.command.Command;
 | 
				
			||||||
import org.bukkit.command.CommandSender;
 | 
					import org.bukkit.command.CommandSender;
 | 
				
			||||||
import org.jetbrains.annotations.NotNull;
 | 
					import org.jetbrains.annotations.NotNull;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.util.Map;
 | 
					import java.util.Map;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import static net.knarcraft.paidsigns.formatting.StringFormatter.getTranslatedErrorMessage;
 | 
				
			||||||
 | 
					import static net.knarcraft.paidsigns.formatting.StringFormatter.replacePlaceholder;
 | 
				
			||||||
 | 
					import static net.knarcraft.paidsigns.formatting.StringFormatter.replacePlaceholders;
 | 
				
			||||||
 | 
					import static net.knarcraft.paidsigns.formatting.StringFormatter.translateBoolean;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * A representation of the command for listing information about paid signs
 | 
					 * A representation of the command for listing information about paid signs
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@@ -19,10 +27,7 @@ public class ListCommand extends TokenizedCommand {
 | 
				
			|||||||
                             @NotNull String[] args) {
 | 
					                             @NotNull String[] args) {
 | 
				
			||||||
        super.onCommand(sender, command, label, args);
 | 
					        super.onCommand(sender, command, label, args);
 | 
				
			||||||
        if (argumentSize < 1) {
 | 
					        if (argumentSize < 1) {
 | 
				
			||||||
            sender.sendMessage("Paid signs:");
 | 
					            displaySigns(sender);
 | 
				
			||||||
            for (String signName : PaidSigns.getInstance().getSignManager().getAllPaidSigns().keySet()) {
 | 
					 | 
				
			||||||
                sender.sendMessage(" | " + signName);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            return true;
 | 
					            return true;
 | 
				
			||||||
        } else if (argumentSize < 3) {
 | 
					        } else if (argumentSize < 3) {
 | 
				
			||||||
            return parsePaidSignSelection(sender);
 | 
					            return parsePaidSignSelection(sender);
 | 
				
			||||||
@@ -30,6 +35,21 @@ public class ListCommand extends TokenizedCommand {
 | 
				
			|||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Displays all available signs
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param sender <p>The command sender to display the signs to</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private void displaySigns(CommandSender sender) {
 | 
				
			||||||
 | 
					        StringBuilder signs = new StringBuilder();
 | 
				
			||||||
 | 
					        for (String signName : PaidSigns.getInstance().getSignManager().getAllPaidSigns().keySet()) {
 | 
				
			||||||
 | 
					            signs.append(StringFormatter.replacePlaceholder(Translator.getTranslatedMessage(
 | 
				
			||||||
 | 
					                    TranslatableMessage.PAID_SIGNS_INFO_FORMAT), "{name}", signName));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        sender.sendMessage(StringFormatter.replacePlaceholder(Translator.getTranslatedMessage(
 | 
				
			||||||
 | 
					                TranslatableMessage.PAID_SIGNS_INFO), "{signs}", signs.toString()));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Parses the given input and displays the wanted paid-sign information
 | 
					     * Parses the given input and displays the wanted paid-sign information
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
@@ -39,25 +59,30 @@ public class ListCommand extends TokenizedCommand {
 | 
				
			|||||||
    private boolean parsePaidSignSelection(CommandSender sender) {
 | 
					    private boolean parsePaidSignSelection(CommandSender sender) {
 | 
				
			||||||
        PaidSign paidSign = PaidSigns.getInstance().getSignManager().getPaidSign(arguments.get(0));
 | 
					        PaidSign paidSign = PaidSigns.getInstance().getSignManager().getPaidSign(arguments.get(0));
 | 
				
			||||||
        if (paidSign == null) {
 | 
					        if (paidSign == null) {
 | 
				
			||||||
            sender.sendMessage("No such paid sign");
 | 
					            sender.sendMessage(getTranslatedErrorMessage(TranslatableMessage.ERROR_PAID_SIGN_NOT_FOUND));
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (argumentSize < 2) {
 | 
					        if (argumentSize < 2) {
 | 
				
			||||||
            displayPaidSign(sender, paidSign);
 | 
					            displayPaidSign(sender, paidSign);
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            short signLine;
 | 
					            short lineNumber;
 | 
				
			||||||
            try {
 | 
					            try {
 | 
				
			||||||
                signLine = (short) (Short.parseShort(arguments.get(1)) - 1);
 | 
					                lineNumber = (short) (Short.parseShort(arguments.get(1)) - 1);
 | 
				
			||||||
 | 
					                if (lineNumber < 0 || lineNumber > 3) {
 | 
				
			||||||
 | 
					                    sender.sendMessage(StringFormatter.getTranslatedErrorMessage(TranslatableMessage.ERROR_INVALID_NUMBER));
 | 
				
			||||||
 | 
					                    return false;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
            } catch (NumberFormatException exception) {
 | 
					            } catch (NumberFormatException exception) {
 | 
				
			||||||
                sender.sendMessage("Invalid number given");
 | 
					                sender.sendMessage(getTranslatedErrorMessage(TranslatableMessage.ERROR_INVALID_NUMBER));
 | 
				
			||||||
                return false;
 | 
					                return false;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            if (!paidSign.getConditions().containsKey(signLine)) {
 | 
					            if (!paidSign.getConditions().containsKey(lineNumber)) {
 | 
				
			||||||
                sender.sendMessage("The paid sign you specified has no condition for line " + signLine);
 | 
					                sender.sendMessage(replacePlaceholder(getTranslatedErrorMessage(
 | 
				
			||||||
 | 
					                        TranslatableMessage.ERROR_NO_SUCH_CONDITION), "{line}", String.valueOf(lineNumber)));
 | 
				
			||||||
                return false;
 | 
					                return false;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            PaidSignCondition condition = paidSign.getConditions().get(signLine);
 | 
					            PaidSignCondition condition = paidSign.getConditions().get(lineNumber);
 | 
				
			||||||
            displayPaidSignCondition(sender, paidSign.getName(), signLine, condition);
 | 
					            displayPaidSignCondition(sender, paidSign.getName(), lineNumber, condition);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -72,13 +97,11 @@ public class ListCommand extends TokenizedCommand {
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    private void displayPaidSignCondition(CommandSender sender, String signName, short signLine,
 | 
					    private void displayPaidSignCondition(CommandSender sender, String signName, short signLine,
 | 
				
			||||||
                                          PaidSignCondition condition) {
 | 
					                                          PaidSignCondition condition) {
 | 
				
			||||||
        sender.sendMessage("Paid sign condition info: ");
 | 
					        sender.sendMessage(StringFormatter.replacePlaceholders(Translator.getTranslatedMessage(
 | 
				
			||||||
        sender.sendMessage("Paid sign name: " + signName);
 | 
					                TranslatableMessage.PAID_SIGN_CONDITION_INFO), new String[]{"{name}", "{line}", "{match}", "{regex}",
 | 
				
			||||||
        sender.sendMessage("Condition line: " + signLine);
 | 
					                "{case}", "{color}"}, new String[]{signName, String.valueOf(signLine + 1), condition.getStringToMatch(),
 | 
				
			||||||
        sender.sendMessage("Condition match string: " + condition.getStringToMatch());
 | 
					                translateBoolean(condition.executeRegex()), translateBoolean(condition.ignoreCase()),
 | 
				
			||||||
        sender.sendMessage("Execute RegEx: " + condition.executeRegex());
 | 
					                translateBoolean(condition.ignoreColor())}));
 | 
				
			||||||
        sender.sendMessage("Ignore case: " + condition.ignoreCase());
 | 
					 | 
				
			||||||
        sender.sendMessage("Ignore color: " + condition.ignoreColor());
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@@ -88,17 +111,20 @@ public class ListCommand extends TokenizedCommand {
 | 
				
			|||||||
     * @param paidSign <p>The paid sign to display information about</p>
 | 
					     * @param paidSign <p>The paid sign to display information about</p>
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    private void displayPaidSign(CommandSender sender, PaidSign paidSign) {
 | 
					    private void displayPaidSign(CommandSender sender, PaidSign paidSign) {
 | 
				
			||||||
        sender.sendMessage("Paid sign info:");
 | 
					        Map<Short, PaidSignCondition> signConditions = paidSign.getConditions();
 | 
				
			||||||
        sender.sendMessage("Name: " + paidSign.getName());
 | 
					        StringBuilder conditions = new StringBuilder();
 | 
				
			||||||
        sender.sendMessage("Cost: " + paidSign.getCost());
 | 
					        for (short lineIndex : signConditions.keySet()) {
 | 
				
			||||||
        sender.sendMessage("Permission: " + paidSign.getPermission());
 | 
					            String format = Translator.getTranslatedMessage(TranslatableMessage.PAID_SIGN_INFO_CONDITION_FORMAT);
 | 
				
			||||||
        sender.sendMessage("Ignore case: " + paidSign.getIgnoreCase());
 | 
					            conditions.append(StringFormatter.replacePlaceholders(format, new String[]{"{line}", "{condition}"},
 | 
				
			||||||
        sender.sendMessage("Ignore color: " + paidSign.getIgnoreColor());
 | 
					                    new String[]{String.valueOf((lineIndex + 1)), signConditions.get(lineIndex).getStringToMatch()}));
 | 
				
			||||||
        sender.sendMessage("Sign conditions: ");
 | 
					 | 
				
			||||||
        Map<Short, PaidSignCondition> conditions = paidSign.getConditions();
 | 
					 | 
				
			||||||
        for (short lineIndex : conditions.keySet()) {
 | 
					 | 
				
			||||||
            sender.sendMessage(" | " + (lineIndex + 1) + ". " + conditions.get(lineIndex).getStringToMatch());
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        sender.sendMessage(replacePlaceholders(Translator.getTranslatedMessage(
 | 
				
			||||||
 | 
					                TranslatableMessage.PAID_SIGN_INFO), new String[]{"{name}", "{cost}", "{permission}", "{case}",
 | 
				
			||||||
 | 
					                "{color}", "{any}", "{conditions}"}, new String[]{paidSign.getName(), String.valueOf(paidSign.getCost()),
 | 
				
			||||||
 | 
					                paidSign.getPermission(), translateBoolean(paidSign.getIgnoreCase()),
 | 
				
			||||||
 | 
					                translateBoolean(paidSign.getIgnoreColor()), translateBoolean(paidSign.matchAnyCondition()),
 | 
				
			||||||
 | 
					                conditions.toString()}));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,8 @@
 | 
				
			|||||||
package net.knarcraft.paidsigns.command;
 | 
					package net.knarcraft.paidsigns.command;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import net.knarcraft.paidsigns.PaidSigns;
 | 
					import net.knarcraft.paidsigns.PaidSigns;
 | 
				
			||||||
 | 
					import net.knarcraft.paidsigns.formatting.StringFormatter;
 | 
				
			||||||
 | 
					import net.knarcraft.paidsigns.formatting.TranslatableMessage;
 | 
				
			||||||
import org.bukkit.command.Command;
 | 
					import org.bukkit.command.Command;
 | 
				
			||||||
import org.bukkit.command.CommandSender;
 | 
					import org.bukkit.command.CommandSender;
 | 
				
			||||||
import org.bukkit.command.TabExecutor;
 | 
					import org.bukkit.command.TabExecutor;
 | 
				
			||||||
@@ -18,7 +20,7 @@ public class ReloadTabCommand implements TabExecutor {
 | 
				
			|||||||
    public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label,
 | 
					    public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label,
 | 
				
			||||||
                             @NotNull String[] args) {
 | 
					                             @NotNull String[] args) {
 | 
				
			||||||
        PaidSigns.getInstance().reload();
 | 
					        PaidSigns.getInstance().reload();
 | 
				
			||||||
        sender.sendMessage("PaidSigns reloaded");
 | 
					        sender.sendMessage(StringFormatter.getTranslatedInfoMessage(TranslatableMessage.SUCCESS_RELOADED));
 | 
				
			||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,15 +2,14 @@ package net.knarcraft.paidsigns.command;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import net.knarcraft.paidsigns.PaidSigns;
 | 
					import net.knarcraft.paidsigns.PaidSigns;
 | 
				
			||||||
import net.knarcraft.paidsigns.container.PaidSign;
 | 
					import net.knarcraft.paidsigns.container.PaidSign;
 | 
				
			||||||
 | 
					import net.knarcraft.paidsigns.formatting.StringFormatter;
 | 
				
			||||||
 | 
					import net.knarcraft.paidsigns.formatting.TranslatableMessage;
 | 
				
			||||||
import net.knarcraft.paidsigns.manager.PaidSignManager;
 | 
					import net.knarcraft.paidsigns.manager.PaidSignManager;
 | 
				
			||||||
import org.bukkit.command.Command;
 | 
					import org.bukkit.command.Command;
 | 
				
			||||||
import org.bukkit.command.CommandSender;
 | 
					import org.bukkit.command.CommandSender;
 | 
				
			||||||
import org.jetbrains.annotations.NotNull;
 | 
					import org.jetbrains.annotations.NotNull;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.io.IOException;
 | 
					import java.io.IOException;
 | 
				
			||||||
import java.util.Arrays;
 | 
					 | 
				
			||||||
import java.util.logging.Level;
 | 
					 | 
				
			||||||
import java.util.logging.Logger;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * A representation of the command for removing a condition from a sign
 | 
					 * A representation of the command for removing a condition from a sign
 | 
				
			||||||
@@ -25,36 +24,38 @@ public class RemoveConditionCommand extends TokenizedCommand {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        String name = arguments.get(0);
 | 
					        String name = arguments.get(0);
 | 
				
			||||||
        short line;
 | 
					        short lineNumber;
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            line = (short) (Short.parseShort(arguments.get(1)) - 1);
 | 
					            lineNumber = (short) (Short.parseShort(arguments.get(1)) - 1);
 | 
				
			||||||
 | 
					            if (lineNumber < 0 || lineNumber > 3) {
 | 
				
			||||||
 | 
					                sender.sendMessage(StringFormatter.getTranslatedErrorMessage(TranslatableMessage.ERROR_INVALID_NUMBER));
 | 
				
			||||||
 | 
					                return false;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        } catch (NumberFormatException exception) {
 | 
					        } catch (NumberFormatException exception) {
 | 
				
			||||||
            sender.sendMessage("Invalid line number given");
 | 
					            sender.sendMessage(StringFormatter.getTranslatedErrorMessage(TranslatableMessage.ERROR_INVALID_NUMBER));
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        PaidSignManager signManager = PaidSigns.getInstance().getSignManager();
 | 
					        PaidSignManager signManager = PaidSigns.getInstance().getSignManager();
 | 
				
			||||||
        PaidSign sign = signManager.getPaidSign(name);
 | 
					        PaidSign sign = signManager.getPaidSign(name);
 | 
				
			||||||
        if (sign == null) {
 | 
					        if (sign == null) {
 | 
				
			||||||
            sender.sendMessage("Invalid sign name given");
 | 
					            sender.sendMessage(StringFormatter.getTranslatedErrorMessage(TranslatableMessage.ERROR_PAID_SIGN_NOT_FOUND));
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!sign.getConditions().containsKey(line)) {
 | 
					        if (!sign.getConditions().containsKey(lineNumber)) {
 | 
				
			||||||
            sender.sendMessage("No condition registered for line " + (line + 1));
 | 
					            sender.sendMessage(StringFormatter.replacePlaceholder(StringFormatter.getTranslatedErrorMessage(
 | 
				
			||||||
 | 
					                    TranslatableMessage.ERROR_NO_SUCH_CONDITION), "{line}", String.valueOf((lineNumber + 1))));
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        sign.removeCondition(line);
 | 
					        sign.removeCondition(lineNumber);
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            signManager.saveSigns();
 | 
					            signManager.saveSigns();
 | 
				
			||||||
        } catch (IOException e) {
 | 
					        } catch (IOException e) {
 | 
				
			||||||
            Logger logger = PaidSigns.getInstance().getLogger();
 | 
					            sender.sendMessage(StringFormatter.getTranslatedErrorMessage(TranslatableMessage.ERROR_EXCEPTION_OCCURRED));
 | 
				
			||||||
            logger.log(Level.SEVERE, "Exception encountered while trying to write to the data file");
 | 
					 | 
				
			||||||
            logger.log(Level.SEVERE, Arrays.toString(e.getStackTrace()));
 | 
					 | 
				
			||||||
            sender.sendMessage("An exception occurred. Please notify the server administrator or check the server log.");
 | 
					 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        sender.sendMessage("Condition removed");
 | 
					        sender.sendMessage(StringFormatter.getTranslatedInfoMessage(TranslatableMessage.SUCCESS_REMOVED_CONDITION));
 | 
				
			||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,9 @@
 | 
				
			|||||||
package net.knarcraft.paidsigns.command;
 | 
					package net.knarcraft.paidsigns.command;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import net.knarcraft.paidsigns.PaidSigns;
 | 
					import net.knarcraft.paidsigns.PaidSigns;
 | 
				
			||||||
import net.knarcraft.paidsigns.container.PaidSign;
 | 
					import net.knarcraft.paidsigns.formatting.StringFormatter;
 | 
				
			||||||
 | 
					import net.knarcraft.paidsigns.formatting.TranslatableMessage;
 | 
				
			||||||
 | 
					import net.knarcraft.paidsigns.utility.TabCompleteHelper;
 | 
				
			||||||
import net.knarcraft.paidsigns.utility.Tokenizer;
 | 
					import net.knarcraft.paidsigns.utility.Tokenizer;
 | 
				
			||||||
import org.bukkit.command.Command;
 | 
					import org.bukkit.command.Command;
 | 
				
			||||||
import org.bukkit.command.CommandSender;
 | 
					import org.bukkit.command.CommandSender;
 | 
				
			||||||
@@ -11,11 +13,7 @@ import org.jetbrains.annotations.Nullable;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import java.io.IOException;
 | 
					import java.io.IOException;
 | 
				
			||||||
import java.util.ArrayList;
 | 
					import java.util.ArrayList;
 | 
				
			||||||
import java.util.Arrays;
 | 
					 | 
				
			||||||
import java.util.List;
 | 
					import java.util.List;
 | 
				
			||||||
import java.util.Map;
 | 
					 | 
				
			||||||
import java.util.logging.Level;
 | 
					 | 
				
			||||||
import java.util.logging.Logger;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * A representation of the command for removing a paid sign
 | 
					 * A representation of the command for removing a paid sign
 | 
				
			||||||
@@ -33,17 +31,15 @@ public class RemoveTabCommand implements TabExecutor {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            if (PaidSigns.getInstance().getSignManager().removePaidSign(name)) {
 | 
					            if (PaidSigns.getInstance().getSignManager().removePaidSign(name)) {
 | 
				
			||||||
                sender.sendMessage("Successfully removed paid sign");
 | 
					                sender.sendMessage(StringFormatter.getTranslatedInfoMessage(
 | 
				
			||||||
 | 
					                        TranslatableMessage.SUCCESS_REMOVED_PAID_SIGN));
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                sender.sendMessage("No matching paid sign was found");
 | 
					                sender.sendMessage(StringFormatter.getTranslatedErrorMessage(
 | 
				
			||||||
 | 
					                        TranslatableMessage.ERROR_PAID_SIGN_NOT_FOUND));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            return true;
 | 
					            return true;
 | 
				
			||||||
        } catch (IOException e) {
 | 
					        } catch (IOException e) {
 | 
				
			||||||
            Logger logger = PaidSigns.getInstance().getLogger();
 | 
					            sender.sendMessage(StringFormatter.getTranslatedErrorMessage(TranslatableMessage.ERROR_EXCEPTION_OCCURRED));
 | 
				
			||||||
            logger.log(Level.SEVERE, "Exception encountered while trying to write " +
 | 
					 | 
				
			||||||
                    "to the data file");
 | 
					 | 
				
			||||||
            logger.log(Level.SEVERE, Arrays.toString(e.getStackTrace()));
 | 
					 | 
				
			||||||
            sender.sendMessage("An exception occurred. Please notify the server administrator or check the server log.");
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -56,12 +52,7 @@ public class RemoveTabCommand implements TabExecutor {
 | 
				
			|||||||
        int argumentSize = args[args.length - 1].isEmpty() ? arguments.size() : arguments.size() - 1;
 | 
					        int argumentSize = args[args.length - 1].isEmpty() ? arguments.size() : arguments.size() - 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (argumentSize < 1) {
 | 
					        if (argumentSize < 1) {
 | 
				
			||||||
            Map<String, PaidSign> allPaidSigns = PaidSigns.getInstance().getSignManager().getAllPaidSigns();
 | 
					            return TabCompleteHelper.getPaidSignNames();
 | 
				
			||||||
            List<String> signNames = new ArrayList<>();
 | 
					 | 
				
			||||||
            for (String name : allPaidSigns.keySet()) {
 | 
					 | 
				
			||||||
                signNames.add("\"" + name + "\"");
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            return signNames;
 | 
					 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            return new ArrayList<>();
 | 
					            return new ArrayList<>();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,7 @@
 | 
				
			|||||||
package net.knarcraft.paidsigns.command;
 | 
					package net.knarcraft.paidsigns.command;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import net.knarcraft.paidsigns.formatting.StringFormatter;
 | 
				
			||||||
 | 
					import net.knarcraft.paidsigns.formatting.TranslatableMessage;
 | 
				
			||||||
import net.knarcraft.paidsigns.utility.Tokenizer;
 | 
					import net.knarcraft.paidsigns.utility.Tokenizer;
 | 
				
			||||||
import org.bukkit.command.Command;
 | 
					import org.bukkit.command.Command;
 | 
				
			||||||
import org.bukkit.command.CommandExecutor;
 | 
					import org.bukkit.command.CommandExecutor;
 | 
				
			||||||
@@ -7,6 +9,8 @@ import org.bukkit.command.CommandSender;
 | 
				
			|||||||
import org.jetbrains.annotations.NotNull;
 | 
					import org.jetbrains.annotations.NotNull;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.util.List;
 | 
					import java.util.List;
 | 
				
			||||||
 | 
					import java.util.regex.Pattern;
 | 
				
			||||||
 | 
					import java.util.regex.PatternSyntaxException;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * A command executor with tokenized arguments
 | 
					 * A command executor with tokenized arguments
 | 
				
			||||||
@@ -23,4 +27,22 @@ public class TokenizedCommand implements CommandExecutor {
 | 
				
			|||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Tests whether the given regular expression is valid
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param sender            <p>The command sender to notify if the regular expression is invalid</p>
 | 
				
			||||||
 | 
					     * @param regularExpression <p>The regular expression to test</p>
 | 
				
			||||||
 | 
					     * @return <p>True if the regular expression is invalid</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    protected boolean isRegExInvalid(CommandSender sender, String regularExpression) {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            Pattern.compile(regularExpression);
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					        } catch (PatternSyntaxException exception) {
 | 
				
			||||||
 | 
					            sender.sendMessage(StringFormatter.getTranslatedErrorMessage(
 | 
				
			||||||
 | 
					                    TranslatableMessage.ERROR_INVALID_REGULAR_EXPRESSION));
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,6 +16,7 @@ public class PaidSign {
 | 
				
			|||||||
    private final String permission;
 | 
					    private final String permission;
 | 
				
			||||||
    private final OptionState ignoreCase;
 | 
					    private final OptionState ignoreCase;
 | 
				
			||||||
    private final OptionState ignoreColor;
 | 
					    private final OptionState ignoreColor;
 | 
				
			||||||
 | 
					    private final boolean matchAnyCondition;
 | 
				
			||||||
    private final Map<Short, PaidSignCondition> conditions = new HashMap<>();
 | 
					    private final Map<Short, PaidSignCondition> conditions = new HashMap<>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@@ -26,8 +27,10 @@ public class PaidSign {
 | 
				
			|||||||
     * @param permission        <p>The permission required to create the sign this paid sign matches</p>
 | 
					     * @param permission        <p>The permission required to create the sign this paid sign matches</p>
 | 
				
			||||||
     * @param ignoreCase        <p>Whether to ignore case when looking for this permission sign</p>
 | 
					     * @param ignoreCase        <p>Whether to ignore case when looking for this permission sign</p>
 | 
				
			||||||
     * @param ignoreColor       <p>Whether to ignore color when looking for this permission sign</p>
 | 
					     * @param ignoreColor       <p>Whether to ignore color when looking for this permission sign</p>
 | 
				
			||||||
 | 
					     * @param matchAnyCondition <p>Whether to treat a match for any condition as a sign match</p>
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public PaidSign(String name, double cost, String permission, OptionState ignoreCase, OptionState ignoreColor) {
 | 
					    public PaidSign(String name, double cost, String permission, OptionState ignoreCase, OptionState ignoreColor,
 | 
				
			||||||
 | 
					                    boolean matchAnyCondition) {
 | 
				
			||||||
        if (name == null || name.trim().isBlank()) {
 | 
					        if (name == null || name.trim().isBlank()) {
 | 
				
			||||||
            throw new IllegalArgumentException("Name cannot be empty");
 | 
					            throw new IllegalArgumentException("Name cannot be empty");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -42,6 +45,7 @@ public class PaidSign {
 | 
				
			|||||||
        this.permission = permission;
 | 
					        this.permission = permission;
 | 
				
			||||||
        this.ignoreCase = ignoreCase;
 | 
					        this.ignoreCase = ignoreCase;
 | 
				
			||||||
        this.ignoreColor = ignoreColor;
 | 
					        this.ignoreColor = ignoreColor;
 | 
				
			||||||
 | 
					        this.matchAnyCondition = matchAnyCondition;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@@ -98,6 +102,15 @@ public class PaidSign {
 | 
				
			|||||||
        return OptionState.getBooleanValue(this.ignoreColor, PaidSigns.getInstance().ignoreColor());
 | 
					        return OptionState.getBooleanValue(this.ignoreColor, PaidSigns.getInstance().ignoreColor());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Gets whether to treat a match for any condition as a sign match
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return <p>Whether to treat a match for any condition as a sign match</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public boolean matchAnyCondition() {
 | 
				
			||||||
 | 
					        return this.matchAnyCondition;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Checks whether this paid sign matches the given set of sign lines
 | 
					     * Checks whether this paid sign matches the given set of sign lines
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
@@ -109,11 +122,18 @@ public class PaidSign {
 | 
				
			|||||||
        if (this.conditions.isEmpty()) {
 | 
					        if (this.conditions.isEmpty()) {
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        boolean success = true;
 | 
					        boolean matchAny = matchAnyCondition();
 | 
				
			||||||
 | 
					        boolean success = !matchAny;
 | 
				
			||||||
        for (short i = 0; i < 4; i++) {
 | 
					        for (short i = 0; i < 4; i++) {
 | 
				
			||||||
            PaidSignCondition condition = this.conditions.get(i);
 | 
					            PaidSignCondition condition = this.conditions.get(i);
 | 
				
			||||||
            if (condition != null) {
 | 
					            if (condition != null) {
 | 
				
			||||||
                success = success && condition.test(lines[i]);
 | 
					                boolean conditionMatches = condition.test(lines[i]);
 | 
				
			||||||
 | 
					                if (matchAny) {
 | 
				
			||||||
 | 
					                    success |= conditionMatches;
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    success &= conditionMatches;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return success;
 | 
					        return success;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,125 @@
 | 
				
			|||||||
 | 
					package net.knarcraft.paidsigns.formatting;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import net.md_5.bungee.api.ChatColor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.util.regex.Matcher;
 | 
				
			||||||
 | 
					import java.util.regex.Pattern;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * A formatter for formatting displayed messages
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					public final class StringFormatter {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private StringFormatter() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Translates the given boolean value
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param booleanValue <p>The boolean value to translate</p>
 | 
				
			||||||
 | 
					     * @return <p>The translation of the boolean value</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public static String translateBoolean(boolean booleanValue) {
 | 
				
			||||||
 | 
					        if (booleanValue) {
 | 
				
			||||||
 | 
					            return Translator.getTranslatedMessage(TranslatableMessage.BOOLEAN_TRUE);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            return Translator.getTranslatedMessage(TranslatableMessage.BOOLEAN_FALSE);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Replaces a placeholder in a string
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param input       <p>The input string to replace in</p>
 | 
				
			||||||
 | 
					     * @param placeholder <p>The placeholder to replace</p>
 | 
				
			||||||
 | 
					     * @param replacement <p>The replacement value</p>
 | 
				
			||||||
 | 
					     * @return <p>The input string with the placeholder replaced</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public static String replacePlaceholder(String input, String placeholder, String replacement) {
 | 
				
			||||||
 | 
					        return input.replace(placeholder, replacement);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Replaces placeholders in a string
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param input        <p>The input string to replace in</p>
 | 
				
			||||||
 | 
					     * @param placeholders <p>The placeholders to replace</p>
 | 
				
			||||||
 | 
					     * @param replacements <p>The replacement values</p>
 | 
				
			||||||
 | 
					     * @return <p>The input string with placeholders replaced</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public static String replacePlaceholders(String input, String[] placeholders, String[] replacements) {
 | 
				
			||||||
 | 
					        for (int i = 0; i < Math.min(placeholders.length, replacements.length); i++) {
 | 
				
			||||||
 | 
					            input = replacePlaceholder(input, placeholders[i], replacements[i]);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return input;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Gets a translated and formatted info message
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param translatableMessage <p>The translatable message to translate and format</p>
 | 
				
			||||||
 | 
					     * @return <p>The translated and formatted message</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public static String getTranslatedInfoMessage(TranslatableMessage translatableMessage) {
 | 
				
			||||||
 | 
					        return formatInfoMessage(Translator.getTranslatedMessage(translatableMessage));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Gets a translated and formatted error message
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param translatableMessage <p>The translatable message to translate and format</p>
 | 
				
			||||||
 | 
					     * @return <p>The translated and formatted message</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public static String getTranslatedErrorMessage(TranslatableMessage translatableMessage) {
 | 
				
			||||||
 | 
					        return formatErrorMessage(Translator.getTranslatedMessage(translatableMessage));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Formats an information message by adding the prefix and text color
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param message <p>The message to format</p>
 | 
				
			||||||
 | 
					     * @return <p>The formatted message</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public static String formatInfoMessage(String message) {
 | 
				
			||||||
 | 
					        return ChatColor.DARK_GREEN + formatMessage(message);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Formats an error message by adding the prefix and text color
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param message <p>The message to format</p>
 | 
				
			||||||
 | 
					     * @return <p>The formatted message</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public static String formatErrorMessage(String message) {
 | 
				
			||||||
 | 
					        return ChatColor.DARK_RED + formatMessage(message);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Translates all found color codes to formatting in a string
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param message <p>The string to search for color codes</p>
 | 
				
			||||||
 | 
					     * @return <p>The message with color codes translated</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public static String translateAllColorCodes(String message) {
 | 
				
			||||||
 | 
					        message = ChatColor.translateAlternateColorCodes('&', message);
 | 
				
			||||||
 | 
					        Pattern pattern = Pattern.compile("(#[a-fA-F0-9]{6})");
 | 
				
			||||||
 | 
					        Matcher matcher = pattern.matcher(message);
 | 
				
			||||||
 | 
					        while (matcher.find()) {
 | 
				
			||||||
 | 
					            message = message.replace(matcher.group(), "" + ChatColor.of(matcher.group()));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return message;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Formats a message by adding the prefix and text color
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param message <p>The message to format</p>
 | 
				
			||||||
 | 
					     * @return <p>The formatted message</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private static String formatMessage(String message) {
 | 
				
			||||||
 | 
					        return Translator.getTranslatedMessage(TranslatableMessage.PREFIX) + " " +
 | 
				
			||||||
 | 
					                ChatColor.RESET + message;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,138 @@
 | 
				
			|||||||
 | 
					package net.knarcraft.paidsigns.formatting;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * An enum representing all translatable messages
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					public enum TranslatableMessage {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * The prefix to display in messages
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    PREFIX,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * The message to display when a paid sign is successfully added
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    SUCCESS_ADDED_PAID_SIGN,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * The message to display when a paid sign condition is successfully added
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    SUCCESS_ADDED_PAID_SIGN_CONDITION,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * The message to display when a paid sign is successfully updated
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    SUCCESS_UPDATED_PAID_SIGN,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * The message to display when a paid sign condition is successfully updated
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    SUCCESS_UPDATED_PAID_SIGN_CONDITION,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * The message to display when a paid sign has been successfully removed
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    SUCCESS_REMOVED_PAID_SIGN,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * The message to display when a paid sign condition has been successfully removed
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    SUCCESS_REMOVED_CONDITION,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * The message to display after the plugin has been reloaded
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    SUCCESS_RELOADED,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * The message to display when a player has been charged for creating a paid sign
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    SUCCESS_PAID_FOR_SIGN,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * The message to display when a player has been refunded for breaking a sign
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    SUCCESS_REFUNDED,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * The info text used to display all paid signs
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    PAID_SIGNS_INFO,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * The format used for displaying a paid sign's name
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    PAID_SIGNS_INFO_FORMAT,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * The info text used to display information about a paid sign
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    PAID_SIGN_INFO,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * The info text used to display information about a paid sign condition
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    PAID_SIGN_CONDITION_INFO,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * The format used for displaying one of a paid sign's conditions
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    PAID_SIGN_INFO_CONDITION_FORMAT,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * The message to display for a true boolean value
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    BOOLEAN_TRUE,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * The message to display for a false boolean value
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    BOOLEAN_FALSE,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * The error to display when a command argument contains an invalid number
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    ERROR_INVALID_NUMBER,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * The error to display if a paid sign name duplicate is encountered
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    ERROR_NAME_DUPLICATE,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * The error to display if a severe exception occurs
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    ERROR_EXCEPTION_OCCURRED,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * The error to display if some input is invalid
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    ERROR_INVALID_INPUT,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * The error to display if a specified paid sign is not found
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    ERROR_PAID_SIGN_NOT_FOUND,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * The error to display if a paid sign condition is specified, but does not exist
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    ERROR_NO_SUCH_CONDITION,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * The error to display if a player cannot pay for a sign matching a paid sign
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    ERROR_CANNOT_AFFORD,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * The error to display if an invalid regular expression is provided
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    ERROR_INVALID_REGULAR_EXPRESSION,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * The error to display if an invalid property is given to the edit command
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    ERROR_PROPERTY_NOT_RECOGNIZED,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										118
									
								
								src/main/java/net/knarcraft/paidsigns/formatting/Translator.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										118
									
								
								src/main/java/net/knarcraft/paidsigns/formatting/Translator.java
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,118 @@
 | 
				
			|||||||
 | 
					package net.knarcraft.paidsigns.formatting;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import net.knarcraft.paidsigns.PaidSigns;
 | 
				
			||||||
 | 
					import net.knarcraft.paidsigns.utility.FileHelper;
 | 
				
			||||||
 | 
					import org.bukkit.configuration.file.YamlConfiguration;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.io.BufferedReader;
 | 
				
			||||||
 | 
					import java.io.File;
 | 
				
			||||||
 | 
					import java.io.FileInputStream;
 | 
				
			||||||
 | 
					import java.io.FileNotFoundException;
 | 
				
			||||||
 | 
					import java.io.InputStreamReader;
 | 
				
			||||||
 | 
					import java.util.HashMap;
 | 
				
			||||||
 | 
					import java.util.Map;
 | 
				
			||||||
 | 
					import java.util.logging.Level;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * A tool to get strings translated to the correct language
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					public final class Translator {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private static Map<TranslatableMessage, String> translatedMessages;
 | 
				
			||||||
 | 
					    private static Map<TranslatableMessage, String> backupTranslatedMessages;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private Translator() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Loads the languages used by this translator
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public static void loadLanguages(String selectedLanguage) {
 | 
				
			||||||
 | 
					        backupTranslatedMessages = loadTranslatedMessages("en");
 | 
				
			||||||
 | 
					        translatedMessages = loadCustomTranslatedMessages(selectedLanguage);
 | 
				
			||||||
 | 
					        if (translatedMessages == null) {
 | 
				
			||||||
 | 
					            translatedMessages = loadTranslatedMessages(selectedLanguage);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Gets a translated version of the given translatable message
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param translatableMessage <p>The message to translate</p>
 | 
				
			||||||
 | 
					     * @return <p>The translated message</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public static String getTranslatedMessage(TranslatableMessage translatableMessage) {
 | 
				
			||||||
 | 
					        if (translatedMessages == null) {
 | 
				
			||||||
 | 
					            return "Translated strings not loaded";
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        String translatedMessage;
 | 
				
			||||||
 | 
					        if (translatedMessages.containsKey(translatableMessage)) {
 | 
				
			||||||
 | 
					            translatedMessage = translatedMessages.get(translatableMessage);
 | 
				
			||||||
 | 
					        } else if (backupTranslatedMessages.containsKey(translatableMessage)) {
 | 
				
			||||||
 | 
					            translatedMessage = backupTranslatedMessages.get(translatableMessage);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            translatedMessage = translatableMessage.toString();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return StringFormatter.translateAllColorCodes(translatedMessage);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Loads all translated messages for the given language
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param language <p>The language chosen by the user</p>
 | 
				
			||||||
 | 
					     * @return <p>A mapping of all strings for the given language</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public static Map<TranslatableMessage, String> loadTranslatedMessages(String language) {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            BufferedReader reader = FileHelper.getBufferedReaderForInternalFile("/strings.yml");
 | 
				
			||||||
 | 
					            return loadTranslatableMessages(language, reader);
 | 
				
			||||||
 | 
					        } catch (FileNotFoundException e) {
 | 
				
			||||||
 | 
					            PaidSigns.getInstance().getLogger().log(Level.SEVERE, "Unable to load translated messages");
 | 
				
			||||||
 | 
					            return null;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Tries to load translated messages from a custom strings.yml file
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param language <p>The selected language</p>
 | 
				
			||||||
 | 
					     * @return <p>The loaded translated strings, or null if no custom language file exists</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public static Map<TranslatableMessage, String> loadCustomTranslatedMessages(String language) {
 | 
				
			||||||
 | 
					        File strings = new File(PaidSigns.getInstance().getDataFolder(), "strings.yml");
 | 
				
			||||||
 | 
					        if (!strings.exists()) {
 | 
				
			||||||
 | 
					            PaidSigns.getInstance().getLogger().log(Level.FINEST, "Strings file not found");
 | 
				
			||||||
 | 
					            return null;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            PaidSigns.getInstance().getLogger().log(Level.WARNING, "Loading custom strings...");
 | 
				
			||||||
 | 
					            return loadTranslatableMessages(language, new BufferedReader(new InputStreamReader(new FileInputStream(strings))));
 | 
				
			||||||
 | 
					        } catch (FileNotFoundException e) {
 | 
				
			||||||
 | 
					            PaidSigns.getInstance().getLogger().log(Level.WARNING, "Unable to load custom messages");
 | 
				
			||||||
 | 
					            return null;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Loads translatable messages from the given reader
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param language <p>The selected language</p>
 | 
				
			||||||
 | 
					     * @param reader   <p>The buffered reader to read from</p>
 | 
				
			||||||
 | 
					     * @return <p>The loaded translated strings</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private static Map<TranslatableMessage, String> loadTranslatableMessages(String language, BufferedReader reader) {
 | 
				
			||||||
 | 
					        Map<TranslatableMessage, String> translatedMessages = new HashMap<>();
 | 
				
			||||||
 | 
					        YamlConfiguration configuration = YamlConfiguration.loadConfiguration(reader);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (TranslatableMessage message : TranslatableMessage.values()) {
 | 
				
			||||||
 | 
					            String translated = configuration.getString(language + "." + message.toString());
 | 
				
			||||||
 | 
					            if (translated != null) {
 | 
				
			||||||
 | 
					                translatedMessages.put(message, translated);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return translatedMessages;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,35 +0,0 @@
 | 
				
			|||||||
package net.knarcraft.paidsigns.listener;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import net.knarcraft.paidsigns.PaidSigns;
 | 
					 | 
				
			||||||
import net.knarcraft.paidsigns.manager.TrackedSignManager;
 | 
					 | 
				
			||||||
import org.bukkit.block.Sign;
 | 
					 | 
				
			||||||
import org.bukkit.event.EventHandler;
 | 
					 | 
				
			||||||
import org.bukkit.event.EventPriority;
 | 
					 | 
				
			||||||
import org.bukkit.event.Listener;
 | 
					 | 
				
			||||||
import org.bukkit.event.block.BlockBreakEvent;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import java.io.IOException;
 | 
					 | 
				
			||||||
import java.util.Arrays;
 | 
					 | 
				
			||||||
import java.util.logging.Level;
 | 
					 | 
				
			||||||
import java.util.logging.Logger;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * A listener that listens for any tracked signs being broken
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
public class BlockBreakListener implements Listener {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @EventHandler(priority = EventPriority.MONITOR)
 | 
					 | 
				
			||||||
    public void onBlockBreak(BlockBreakEvent event) {
 | 
					 | 
				
			||||||
        if (event.getBlock().getState() instanceof Sign) {
 | 
					 | 
				
			||||||
            try {
 | 
					 | 
				
			||||||
                TrackedSignManager.removeTrackedSign(event.getBlock().getLocation());
 | 
					 | 
				
			||||||
            } catch (IOException e) {
 | 
					 | 
				
			||||||
                e.printStackTrace();
 | 
					 | 
				
			||||||
                Logger logger = PaidSigns.getInstance().getLogger();
 | 
					 | 
				
			||||||
                logger.log(Level.SEVERE, "Exception encountered while trying to write to the data file");
 | 
					 | 
				
			||||||
                logger.log(Level.SEVERE, Arrays.toString(e.getStackTrace()));
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -0,0 +1,103 @@
 | 
				
			|||||||
 | 
					package net.knarcraft.paidsigns.listener;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import net.knarcraft.paidsigns.PaidSigns;
 | 
				
			||||||
 | 
					import net.knarcraft.paidsigns.manager.TrackedSignManager;
 | 
				
			||||||
 | 
					import org.bukkit.block.Block;
 | 
				
			||||||
 | 
					import org.bukkit.block.Sign;
 | 
				
			||||||
 | 
					import org.bukkit.entity.Player;
 | 
				
			||||||
 | 
					import org.bukkit.event.EventHandler;
 | 
				
			||||||
 | 
					import org.bukkit.event.EventPriority;
 | 
				
			||||||
 | 
					import org.bukkit.event.Listener;
 | 
				
			||||||
 | 
					import org.bukkit.event.block.BlockBreakEvent;
 | 
				
			||||||
 | 
					import org.bukkit.event.block.BlockExplodeEvent;
 | 
				
			||||||
 | 
					import org.bukkit.event.block.BlockPistonExtendEvent;
 | 
				
			||||||
 | 
					import org.bukkit.event.block.BlockPistonRetractEvent;
 | 
				
			||||||
 | 
					import org.bukkit.event.entity.EntityChangeBlockEvent;
 | 
				
			||||||
 | 
					import org.bukkit.event.entity.EntityExplodeEvent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.io.IOException;
 | 
				
			||||||
 | 
					import java.util.List;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * A listener that listens for any tracked signs being broken
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					public class SignBreakListener implements Listener {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @EventHandler(priority = EventPriority.MONITOR)
 | 
				
			||||||
 | 
					    public void onBlockBreak(BlockBreakEvent event) {
 | 
				
			||||||
 | 
					        if (event.isCancelled()) {
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        removeTrackedSign(event.getBlock(), true);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @EventHandler(priority = EventPriority.MONITOR)
 | 
				
			||||||
 | 
					    public void onExplosion(BlockExplodeEvent event) {
 | 
				
			||||||
 | 
					        if (event.isCancelled()) {
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        removeTrackedSigns(event.blockList());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @EventHandler(priority = EventPriority.MONITOR)
 | 
				
			||||||
 | 
					    public void onEntityExplosion(EntityExplodeEvent event) {
 | 
				
			||||||
 | 
					        if (event.isCancelled()) {
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        removeTrackedSigns(event.blockList());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @EventHandler(priority = EventPriority.MONITOR)
 | 
				
			||||||
 | 
					    public void onPistonPush(BlockPistonExtendEvent event) {
 | 
				
			||||||
 | 
					        if (event.isCancelled()) {
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        removeTrackedSigns(event.getBlocks());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @EventHandler(priority = EventPriority.MONITOR)
 | 
				
			||||||
 | 
					    public void onPistonPull(BlockPistonRetractEvent event) {
 | 
				
			||||||
 | 
					        if (event.isCancelled()) {
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        removeTrackedSigns(event.getBlocks());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @EventHandler(priority = EventPriority.MONITOR)
 | 
				
			||||||
 | 
					    public void onEntityBlockChange(EntityChangeBlockEvent event) {
 | 
				
			||||||
 | 
					        if (event.isCancelled()) {
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (event.getEntity() instanceof Player) {
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        removeTrackedSign(event.getBlock(), PaidSigns.getInstance().refundAlways());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Removes all tracked signs from the given blocks
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param blocks <p>The blocks to search for tracked signs</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private void removeTrackedSigns(List<Block> blocks) {
 | 
				
			||||||
 | 
					        for (Block block : blocks) {
 | 
				
			||||||
 | 
					            removeTrackedSign(block, PaidSigns.getInstance().refundAlways());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Tries to remove any tracked sign at the given block
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param block  <p>The block that might be a sign</p>
 | 
				
			||||||
 | 
					     * @param refund <p>Whether to perform a refund after un-tracking the sign</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private void removeTrackedSign(Block block, boolean refund) {
 | 
				
			||||||
 | 
					        if (block.getState() instanceof Sign) {
 | 
				
			||||||
 | 
					            try {
 | 
				
			||||||
 | 
					                TrackedSignManager.removeTrackedSign(block.getLocation(), refund);
 | 
				
			||||||
 | 
					            } catch (IOException ignored) {
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -2,6 +2,8 @@ package net.knarcraft.paidsigns.listener;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import net.knarcraft.paidsigns.PaidSigns;
 | 
					import net.knarcraft.paidsigns.PaidSigns;
 | 
				
			||||||
import net.knarcraft.paidsigns.container.PaidSign;
 | 
					import net.knarcraft.paidsigns.container.PaidSign;
 | 
				
			||||||
 | 
					import net.knarcraft.paidsigns.formatting.StringFormatter;
 | 
				
			||||||
 | 
					import net.knarcraft.paidsigns.formatting.TranslatableMessage;
 | 
				
			||||||
import net.knarcraft.paidsigns.manager.EconomyManager;
 | 
					import net.knarcraft.paidsigns.manager.EconomyManager;
 | 
				
			||||||
import net.knarcraft.paidsigns.manager.TrackedSignManager;
 | 
					import net.knarcraft.paidsigns.manager.TrackedSignManager;
 | 
				
			||||||
import org.bukkit.entity.Player;
 | 
					import org.bukkit.entity.Player;
 | 
				
			||||||
@@ -11,10 +13,7 @@ import org.bukkit.event.Listener;
 | 
				
			|||||||
import org.bukkit.event.block.SignChangeEvent;
 | 
					import org.bukkit.event.block.SignChangeEvent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.io.IOException;
 | 
					import java.io.IOException;
 | 
				
			||||||
import java.util.Arrays;
 | 
					 | 
				
			||||||
import java.util.Map;
 | 
					import java.util.Map;
 | 
				
			||||||
import java.util.logging.Level;
 | 
					 | 
				
			||||||
import java.util.logging.Logger;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * A listener for listening to registered paid signs
 | 
					 * A listener for listening to registered paid signs
 | 
				
			||||||
@@ -72,19 +71,17 @@ public class SignListener implements Listener {
 | 
				
			|||||||
        double cost = paidSign.getCost();
 | 
					        double cost = paidSign.getCost();
 | 
				
			||||||
        boolean canAfford = EconomyManager.canAfford(player, cost);
 | 
					        boolean canAfford = EconomyManager.canAfford(player, cost);
 | 
				
			||||||
        if (!canAfford) {
 | 
					        if (!canAfford) {
 | 
				
			||||||
            player.sendMessage("[PaidSigns] You cannot afford to create this sign");
 | 
					            player.sendMessage(StringFormatter.getTranslatedErrorMessage(TranslatableMessage.ERROR_CANNOT_AFFORD));
 | 
				
			||||||
            event.setCancelled(true);
 | 
					            event.setCancelled(true);
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            String unit = EconomyManager.getCurrency(cost != 1);
 | 
					            String unit = EconomyManager.getCurrency(cost != 1);
 | 
				
			||||||
            player.sendMessage(String.format("[PaidSigns] You paid %.2f %s to create the sign", cost, unit));
 | 
					 | 
				
			||||||
            EconomyManager.withdraw(player, cost);
 | 
					            EconomyManager.withdraw(player, cost);
 | 
				
			||||||
 | 
					            player.sendMessage(String.format(StringFormatter.replacePlaceholders(
 | 
				
			||||||
 | 
					                    StringFormatter.getTranslatedInfoMessage(TranslatableMessage.SUCCESS_PAID_FOR_SIGN),
 | 
				
			||||||
 | 
					                    new String[]{"{cost}", "{unit}"}, new String[]{"%.2f", "%s"}), cost, unit));
 | 
				
			||||||
            try {
 | 
					            try {
 | 
				
			||||||
                TrackedSignManager.addTrackedSign(event.getBlock().getLocation(), player.getUniqueId(), cost);
 | 
					                TrackedSignManager.addTrackedSign(event.getBlock().getLocation(), player.getUniqueId(), cost);
 | 
				
			||||||
            } catch (IOException e) {
 | 
					            } catch (IOException ignored) {
 | 
				
			||||||
                e.printStackTrace();
 | 
					 | 
				
			||||||
                Logger logger = PaidSigns.getInstance().getLogger();
 | 
					 | 
				
			||||||
                logger.log(Level.SEVERE, "Exception encountered while trying to write to the data file");
 | 
					 | 
				
			||||||
                logger.log(Level.SEVERE, Arrays.toString(e.getStackTrace()));
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -58,4 +58,14 @@ public final class EconomyManager {
 | 
				
			|||||||
        economy.withdrawPlayer(player, cost);
 | 
					        economy.withdrawPlayer(player, cost);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Deposits a given sum into the given player's account
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param player <p>The player to deposit money to</p>
 | 
				
			||||||
 | 
					     * @param sum    <p>The amount of money to deposit</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public static void deposit(OfflinePlayer player, double sum) {
 | 
				
			||||||
 | 
					        economy.depositPlayer(player, sum);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,9 +9,11 @@ import org.bukkit.configuration.file.YamlConfiguration;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import java.io.File;
 | 
					import java.io.File;
 | 
				
			||||||
import java.io.IOException;
 | 
					import java.io.IOException;
 | 
				
			||||||
 | 
					import java.util.Arrays;
 | 
				
			||||||
import java.util.HashMap;
 | 
					import java.util.HashMap;
 | 
				
			||||||
import java.util.Map;
 | 
					import java.util.Map;
 | 
				
			||||||
import java.util.logging.Level;
 | 
					import java.util.logging.Level;
 | 
				
			||||||
 | 
					import java.util.logging.Logger;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * A manager that keeps track of all registered paid signs
 | 
					 * A manager that keeps track of all registered paid signs
 | 
				
			||||||
@@ -96,7 +98,8 @@ public final class PaidSignManager {
 | 
				
			|||||||
            String permission = signSection.getString(name + ".permission");
 | 
					            String permission = signSection.getString(name + ".permission");
 | 
				
			||||||
            OptionState ignoreCase = OptionState.getFromBoolean(signSection.getBoolean(name + ".ignoreCase"));
 | 
					            OptionState ignoreCase = OptionState.getFromBoolean(signSection.getBoolean(name + ".ignoreCase"));
 | 
				
			||||||
            OptionState ignoreColor = OptionState.getFromBoolean(signSection.getBoolean(name + ".ignoreColor"));
 | 
					            OptionState ignoreColor = OptionState.getFromBoolean(signSection.getBoolean(name + ".ignoreColor"));
 | 
				
			||||||
            PaidSign sign = new PaidSign(name, cost, permission, ignoreCase, ignoreColor);
 | 
					            boolean matchAnyCondition = signSection.getBoolean(name + ".matchAnyCondition");
 | 
				
			||||||
 | 
					            PaidSign sign = new PaidSign(name, cost, permission, ignoreCase, ignoreColor, matchAnyCondition);
 | 
				
			||||||
            loadConditions(signSection, sign);
 | 
					            loadConditions(signSection, sign);
 | 
				
			||||||
            paidSigns.put(name, sign);
 | 
					            paidSigns.put(name, sign);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -119,15 +122,36 @@ public final class PaidSignManager {
 | 
				
			|||||||
     * @throws IOException <p>If unable to write to the signs file</p>
 | 
					     * @throws IOException <p>If unable to write to the signs file</p>
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public static void saveSigns(Map<String, PaidSign> signs) throws IOException {
 | 
					    public static void saveSigns(Map<String, PaidSign> signs) throws IOException {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
            YamlConfiguration configuration = YamlConfiguration.loadConfiguration(signsFile);
 | 
					            YamlConfiguration configuration = YamlConfiguration.loadConfiguration(signsFile);
 | 
				
			||||||
            ConfigurationSection signSection = configuration.createSection("paidSigns");
 | 
					            ConfigurationSection signSection = configuration.createSection("paidSigns");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            for (PaidSign sign : signs.values()) {
 | 
					            for (PaidSign sign : signs.values()) {
 | 
				
			||||||
 | 
					                saveSign(signSection, sign);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            configuration.save(signsFile);
 | 
				
			||||||
 | 
					        } catch (IOException exception) {
 | 
				
			||||||
 | 
					            Logger logger = PaidSigns.getInstance().getLogger();
 | 
				
			||||||
 | 
					            logger.log(Level.SEVERE, "Exception encountered while trying to write " +
 | 
				
			||||||
 | 
					                    "to the data file");
 | 
				
			||||||
 | 
					            logger.log(Level.SEVERE, Arrays.toString(exception.getStackTrace()));
 | 
				
			||||||
 | 
					            throw exception;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Saves the given sign to the given configuration section
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param signSection <p>The configuration section to save the sign to</p>
 | 
				
			||||||
 | 
					     * @param sign        <p>The sign to save</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private static void saveSign(ConfigurationSection signSection, PaidSign sign) {
 | 
				
			||||||
        String name = sign.getName();
 | 
					        String name = sign.getName();
 | 
				
			||||||
        signSection.set(name + ".cost", sign.getCost());
 | 
					        signSection.set(name + ".cost", sign.getCost());
 | 
				
			||||||
        signSection.set(name + ".permission", sign.getPermission());
 | 
					        signSection.set(name + ".permission", sign.getPermission());
 | 
				
			||||||
        signSection.set(name + ".ignoreCase", sign.getIgnoreCase());
 | 
					        signSection.set(name + ".ignoreCase", sign.getIgnoreCase());
 | 
				
			||||||
        signSection.set(name + ".ignoreColor", sign.getIgnoreColor());
 | 
					        signSection.set(name + ".ignoreColor", sign.getIgnoreColor());
 | 
				
			||||||
 | 
					        signSection.set(name + ".matchAnyCondition", sign.matchAnyCondition());
 | 
				
			||||||
        ConfigurationSection conditionsSection = signSection.createSection(name + ".conditions");
 | 
					        ConfigurationSection conditionsSection = signSection.createSection(name + ".conditions");
 | 
				
			||||||
        Map<Short, PaidSignCondition> signConditions = sign.getConditions();
 | 
					        Map<Short, PaidSignCondition> signConditions = sign.getConditions();
 | 
				
			||||||
        for (short lineIndex : signConditions.keySet()) {
 | 
					        for (short lineIndex : signConditions.keySet()) {
 | 
				
			||||||
@@ -138,8 +162,6 @@ public final class PaidSignManager {
 | 
				
			|||||||
            conditionsSection.set(lineIndex + ".ignoreColor", condition.ignoreColor());
 | 
					            conditionsSection.set(lineIndex + ".ignoreColor", condition.ignoreColor());
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
        configuration.save(signsFile);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Loads any saved paid sign conditions and applies them to the given sign
 | 
					     * Loads any saved paid sign conditions and applies them to the given sign
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,9 +2,12 @@ package net.knarcraft.paidsigns.manager;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import net.knarcraft.paidsigns.PaidSigns;
 | 
					import net.knarcraft.paidsigns.PaidSigns;
 | 
				
			||||||
import net.knarcraft.paidsigns.container.TrackedSign;
 | 
					import net.knarcraft.paidsigns.container.TrackedSign;
 | 
				
			||||||
 | 
					import net.knarcraft.paidsigns.formatting.StringFormatter;
 | 
				
			||||||
 | 
					import net.knarcraft.paidsigns.formatting.TranslatableMessage;
 | 
				
			||||||
import org.bukkit.Bukkit;
 | 
					import org.bukkit.Bukkit;
 | 
				
			||||||
import org.bukkit.Location;
 | 
					import org.bukkit.Location;
 | 
				
			||||||
import org.bukkit.OfflinePlayer;
 | 
					import org.bukkit.OfflinePlayer;
 | 
				
			||||||
 | 
					import org.bukkit.block.Sign;
 | 
				
			||||||
import org.bukkit.configuration.ConfigurationSection;
 | 
					import org.bukkit.configuration.ConfigurationSection;
 | 
				
			||||||
import org.bukkit.configuration.InvalidConfigurationException;
 | 
					import org.bukkit.configuration.InvalidConfigurationException;
 | 
				
			||||||
import org.bukkit.configuration.file.YamlConfiguration;
 | 
					import org.bukkit.configuration.file.YamlConfiguration;
 | 
				
			||||||
@@ -46,23 +49,27 @@ public final class TrackedSignManager {
 | 
				
			|||||||
     * Removes a tracked sign from the manager
 | 
					     * Removes a tracked sign from the manager
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param signLocation <p>The location the sign was removed from</p>
 | 
					     * @param signLocation <p>The location the sign was removed from</p>
 | 
				
			||||||
 | 
					     * @param refund       <p>Whether to perform a refund after un-tracking the sign</p>
 | 
				
			||||||
     * @throws IOException <p>If unable to save the tracked signs</p>
 | 
					     * @throws IOException <p>If unable to save the tracked signs</p>
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public static void removeTrackedSign(Location signLocation) throws IOException {
 | 
					    public static void removeTrackedSign(Location signLocation, boolean refund) throws IOException {
 | 
				
			||||||
        if (!trackedSigns.containsKey(signLocation)) {
 | 
					        if (!trackedSigns.containsKey(signLocation)) {
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        TrackedSign trackedSign = trackedSigns.get(signLocation);
 | 
					        TrackedSign trackedSign = trackedSigns.get(signLocation);
 | 
				
			||||||
        trackedSigns.remove(signLocation);
 | 
					        trackedSigns.remove(signLocation);
 | 
				
			||||||
        saveTrackedSigns();
 | 
					        saveTrackedSigns();
 | 
				
			||||||
        if (!PaidSigns.getInstance().areRefundsEnabled()) {
 | 
					        if (!PaidSigns.getInstance().areRefundsEnabled() || !refund) {
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(trackedSign.getPlayerId());
 | 
					        OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(trackedSign.getPlayerId());
 | 
				
			||||||
        double refundSum = trackedSign.getCost() / 100 * PaidSigns.getInstance().getRefundPercentage();
 | 
					        double refundSum = trackedSign.getCost() / 100 * PaidSigns.getInstance().getRefundPercentage();
 | 
				
			||||||
        EconomyManager.withdraw(offlinePlayer, -refundSum);
 | 
					        EconomyManager.deposit(offlinePlayer, refundSum);
 | 
				
			||||||
        if (offlinePlayer instanceof Player player) {
 | 
					        if (offlinePlayer instanceof Player player) {
 | 
				
			||||||
            player.sendMessage("You were refunded " + refundSum + " for your broken sign");
 | 
					            player.sendMessage(String.format(StringFormatter.replacePlaceholders(
 | 
				
			||||||
 | 
					                            StringFormatter.getTranslatedInfoMessage(TranslatableMessage.SUCCESS_REFUNDED),
 | 
				
			||||||
 | 
					                            new String[]{"{cost}", "{unit}"}, new String[]{"%.2f", "%s"}), refundSum,
 | 
				
			||||||
 | 
					                    EconomyManager.getCurrency(refundSum != 1)));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -107,6 +114,13 @@ public final class TrackedSignManager {
 | 
				
			|||||||
            throw new InvalidConfigurationException("Invalid sign coordinates");
 | 
					            throw new InvalidConfigurationException("Invalid sign coordinates");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //Prevent destroyed signs from being tracked indefinitely
 | 
				
			||||||
 | 
					        if (!(signLocation.getBlock().getState() instanceof Sign)) {
 | 
				
			||||||
 | 
					            PaidSigns.getInstance().getLogger().log(Level.WARNING, "The sign at " + signLocation + " no longer " +
 | 
				
			||||||
 | 
					                    "exists. Removing from sign tracker.");
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        double cost = signSection.getDouble(key + ".cost");
 | 
					        double cost = signSection.getDouble(key + ".cost");
 | 
				
			||||||
        UUID playerId = UUID.fromString(Objects.requireNonNull(signSection.getString(key + ".playerId")));
 | 
					        UUID playerId = UUID.fromString(Objects.requireNonNull(signSection.getString(key + ".playerId")));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,63 @@
 | 
				
			|||||||
 | 
					package net.knarcraft.paidsigns.property;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * A representation of a paid sign condition's editable properties
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					public enum PaidSignConditionProperty {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * The string used to trigger the paid sign condition
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    STRING_TO_MATCH("stringToMatch"),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Whether to execute the match string as a regular expression
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    EXECUTE_REG_EX("executeRegEx"),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Whether to ignore case for the sign condition
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    IGNORE_CASE("ignoreCase"),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Whether to ignore color for the sign condition
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    IGNORE_COLOR("ignoreColor");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private final String stringRepresentation;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Instantiates a new paid sign condition property
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param stringRepresentation <p>The string representation of the paid sign condition property</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    PaidSignConditionProperty(String stringRepresentation) {
 | 
				
			||||||
 | 
					        this.stringRepresentation = stringRepresentation;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Gets the string representation of this paid sign condition property
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return <p>The string representation of this paid sign condition property</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public String getStringRepresentation() {
 | 
				
			||||||
 | 
					        return this.stringRepresentation;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Gets the paid sign property matching the given string
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param propertyString <p>The string representing a paid sign condition property</p>
 | 
				
			||||||
 | 
					     * @return <p>The matching paid sign condition property, or null if no such property exists</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public static PaidSignConditionProperty getFromString(String propertyString) {
 | 
				
			||||||
 | 
					        for (PaidSignConditionProperty paidSignProperty : PaidSignConditionProperty.values()) {
 | 
				
			||||||
 | 
					            if (paidSignProperty.getStringRepresentation().equalsIgnoreCase(propertyString)) {
 | 
				
			||||||
 | 
					                return paidSignProperty;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return null;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,73 @@
 | 
				
			|||||||
 | 
					package net.knarcraft.paidsigns.property;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * A representation of a paid sign's editable properties
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					public enum PaidSignProperty {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * The name of a paid sign
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    NAME("name"),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * The cost of creating a sign matching the paid sign
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    COST("cost"),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * The permission required to create the plugin sign matching the paid sign
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    PERMISSION("permission"),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Whether to ignore case for any sign conditions added to the sign
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    IGNORE_CASE("ignoreCase"),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Whether to ignore color for any sign conditions added to the sign
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    IGNORE_COLOR("ignoreColor"),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Whether to treat a single condition match as a full match
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    MATCH_ANY_CONDITION("matchAnyCondition");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private final String stringRepresentation;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Instantiates a new paid sign property
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param stringRepresentation <p>The string representation of the paid sign property</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    PaidSignProperty(String stringRepresentation) {
 | 
				
			||||||
 | 
					        this.stringRepresentation = stringRepresentation;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Gets the string representation of this paid sign property
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return <p>The string representation of this paid sign property</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public String getStringRepresentation() {
 | 
				
			||||||
 | 
					        return this.stringRepresentation;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Gets the paid sign property matching the given string
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param propertyString <p>The string representing a paid sign property</p>
 | 
				
			||||||
 | 
					     * @return <p>The matching paid sign property, or null if no such property exists</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public static PaidSignProperty getFromString(String propertyString) {
 | 
				
			||||||
 | 
					        for (PaidSignProperty paidSignProperty : PaidSignProperty.values()) {
 | 
				
			||||||
 | 
					            if (paidSignProperty.getStringRepresentation().equalsIgnoreCase(propertyString)) {
 | 
				
			||||||
 | 
					                return paidSignProperty;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return null;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,32 @@
 | 
				
			|||||||
 | 
					package net.knarcraft.paidsigns.utility;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.io.BufferedReader;
 | 
				
			||||||
 | 
					import java.io.FileNotFoundException;
 | 
				
			||||||
 | 
					import java.io.InputStream;
 | 
				
			||||||
 | 
					import java.io.InputStreamReader;
 | 
				
			||||||
 | 
					import java.nio.charset.StandardCharsets;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * A helper class for dealing with files
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					public final class FileHelper {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private FileHelper() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Gets a buffered reader for
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return <p>A buffered read for reading the file</p>
 | 
				
			||||||
 | 
					     * @throws FileNotFoundException <p>If unable to get an input stream for the given file</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public static BufferedReader getBufferedReaderForInternalFile(String file) throws FileNotFoundException {
 | 
				
			||||||
 | 
					        InputStream inputStream = FileHelper.class.getResourceAsStream(file);
 | 
				
			||||||
 | 
					        if (inputStream == null) {
 | 
				
			||||||
 | 
					            throw new FileNotFoundException("Unable to read the given file");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,16 +1,24 @@
 | 
				
			|||||||
package net.knarcraft.paidsigns.utility;
 | 
					package net.knarcraft.paidsigns.utility;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import net.knarcraft.paidsigns.PaidSigns;
 | 
					import net.knarcraft.paidsigns.PaidSigns;
 | 
				
			||||||
 | 
					import org.bukkit.Bukkit;
 | 
				
			||||||
 | 
					import org.bukkit.permissions.Permission;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.util.ArrayList;
 | 
					import java.util.ArrayList;
 | 
				
			||||||
 | 
					import java.util.HashMap;
 | 
				
			||||||
import java.util.List;
 | 
					import java.util.List;
 | 
				
			||||||
 | 
					import java.util.Map;
 | 
				
			||||||
import java.util.Set;
 | 
					import java.util.Set;
 | 
				
			||||||
 | 
					import java.util.StringJoiner;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * A helper class for providing common tab complete options
 | 
					 * A helper class for providing common tab complete options
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
public final class TabCompleteHelper {
 | 
					public final class TabCompleteHelper {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private static List<String> plugins;
 | 
				
			||||||
 | 
					    private static Map<String, List<String>> permissions;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private TabCompleteHelper() {
 | 
					    private TabCompleteHelper() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -122,4 +130,65 @@ public final class TabCompleteHelper {
 | 
				
			|||||||
        return conditionStrings;
 | 
					        return conditionStrings;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Gets the tab complete value for the permission typed
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param typedNode <p>The full permission node typed by the player</p>
 | 
				
			||||||
 | 
					     * @return <p>All known valid auto-complete options</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public static List<String> tabCompletePermission(String typedNode) {
 | 
				
			||||||
 | 
					        if (plugins == null) {
 | 
				
			||||||
 | 
					            loadAvailablePermissions();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        List<String> output;
 | 
				
			||||||
 | 
					        if (typedNode.contains(".")) {
 | 
				
			||||||
 | 
					            List<String> matchingPermissions = permissions.get(typedNode.substring(0, typedNode.lastIndexOf(".")));
 | 
				
			||||||
 | 
					            if (matchingPermissions == null) {
 | 
				
			||||||
 | 
					                output = new ArrayList<>();
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                //Filter by the typed text
 | 
				
			||||||
 | 
					                output = TabCompleteHelper.filterMatchingStartsWith(matchingPermissions, typedNode);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            output = plugins;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //Add previous permissions in the comma-separated lists as a prefix
 | 
				
			||||||
 | 
					        return output;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Loads all permissions available from bukkit plugins
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private static void loadAvailablePermissions() {
 | 
				
			||||||
 | 
					        plugins = new ArrayList<>();
 | 
				
			||||||
 | 
					        permissions = new HashMap<>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (Permission permission : Bukkit.getPluginManager().getPermissions()) {
 | 
				
			||||||
 | 
					            loadPermission(permission.getName());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Loads a given permission into the proper lists and maps
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param permissionName <p>The permission to load</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private static void loadPermission(String permissionName) {
 | 
				
			||||||
 | 
					        String[] permissionParts = permissionName.split("\\.");
 | 
				
			||||||
 | 
					        if (permissionParts.length == 1 && !plugins.contains(permissionParts[0])) {
 | 
				
			||||||
 | 
					            plugins.add(permissionParts[0]);
 | 
				
			||||||
 | 
					        } else if (permissionParts.length > 1) {
 | 
				
			||||||
 | 
					            StringJoiner pathJoiner = new StringJoiner(".");
 | 
				
			||||||
 | 
					            for (int j = 0; j < permissionParts.length - 1; j++) {
 | 
				
			||||||
 | 
					                pathJoiner.add(permissionParts[j]);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            String path = pathJoiner.toString();
 | 
				
			||||||
 | 
					            List<String> permissionList = permissions.computeIfAbsent(path, k -> new ArrayList<>());
 | 
				
			||||||
 | 
					            permissionList.add(permissionName);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            loadPermission(path);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,3 +1,6 @@
 | 
				
			|||||||
 | 
					# The currently enabled language. More languages can be added to the language file
 | 
				
			||||||
 | 
					language: en
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Whether to ignore the case (lowercase/uppercase) of the paid sign text. The option can be set on a per-sign basis, but
 | 
					# Whether to ignore the case (lowercase/uppercase) of the paid sign text. The option can be set on a per-sign basis, but
 | 
				
			||||||
# this value is used if not specified. The correct value depends on whether the plugin signs it should match are
 | 
					# this value is used if not specified. The correct value depends on whether the plugin signs it should match are
 | 
				
			||||||
# case-sensitive or not.
 | 
					# case-sensitive or not.
 | 
				
			||||||
@@ -10,7 +13,11 @@ ignoreColor: false
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
# Whether to enable refunds to the sign creator when a sign detected as a paid sign is broken (payment will always go
 | 
					# Whether to enable refunds to the sign creator when a sign detected as a paid sign is broken (payment will always go
 | 
				
			||||||
# to the original creator)
 | 
					# to the original creator)
 | 
				
			||||||
enableRefunds: true
 | 
					refundsEnabled: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# The percentage of the paid sign cost to refund (0-100)
 | 
					# The percentage of the paid sign cost to refund (0-100)
 | 
				
			||||||
refundPercentage: 100
 | 
					refundPercentage: 100
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Whether to refund when signs that players have paid for are broken by anything. This includes tnt, creepers, pistons
 | 
				
			||||||
 | 
					# and similar
 | 
				
			||||||
 | 
					refundAlways: false
 | 
				
			||||||
@@ -9,26 +9,44 @@ description: Add costs for creating plugin signs
 | 
				
			|||||||
website: https://git.knarcraft.net/EpicKnarvik97/PaidSigns
 | 
					website: https://git.knarcraft.net/EpicKnarvik97/PaidSigns
 | 
				
			||||||
commands:
 | 
					commands:
 | 
				
			||||||
  addpaidsign:
 | 
					  addpaidsign:
 | 
				
			||||||
 | 
					    aliases:
 | 
				
			||||||
 | 
					      - aps
 | 
				
			||||||
    description: Used to add a new paid sign
 | 
					    description: Used to add a new paid sign
 | 
				
			||||||
    usage: /<command> <name> <cost> [permission] [ignore case] [ignore color]
 | 
					    usage: /<command> <name> <cost> [permission] [ignore case] [ignore color] [match any condition]
 | 
				
			||||||
    permission: paidsigns.manage
 | 
					    permission: paidsigns.manage
 | 
				
			||||||
  addpaidsigncondition:
 | 
					  addpaidsigncondition:
 | 
				
			||||||
 | 
					    aliases:
 | 
				
			||||||
 | 
					      - apsc
 | 
				
			||||||
    description: Used to add a new match condition for a paid sign
 | 
					    description: Used to add a new match condition for a paid sign
 | 
				
			||||||
    usage: /<command> <name (of a paid sign)> <line number> <string to match> [executeRegEx] [ignoreCase] [ignoreColor]
 | 
					    usage: /<command> <name (of a paid sign)> <line number> <string to match> [executeRegEx] [ignoreCase] [ignoreColor]
 | 
				
			||||||
    permission: paidsigns.manage
 | 
					    permission: paidsigns.manage
 | 
				
			||||||
  listpaidsigns:
 | 
					  listpaidsigns:
 | 
				
			||||||
 | 
					    aliases:
 | 
				
			||||||
 | 
					      - lps
 | 
				
			||||||
    description: Lists all previously added paid signs
 | 
					    description: Lists all previously added paid signs
 | 
				
			||||||
    usage: /<command> [sign name] [line number]
 | 
					    usage: /<command> [sign name] [line number]
 | 
				
			||||||
    permission: paidsigns.manage
 | 
					    permission: paidsigns.manage
 | 
				
			||||||
 | 
					  editpaidsign:
 | 
				
			||||||
 | 
					    aliases:
 | 
				
			||||||
 | 
					      - eps
 | 
				
			||||||
 | 
					    description: Edits a property of a paid sign or a paid sign condition
 | 
				
			||||||
 | 
					    usage: /<command> <sign name> <property>/<line number> [new value]/<property> [new value]
 | 
				
			||||||
 | 
					    permission: paidsigns.manage
 | 
				
			||||||
  removepaidsigncondition:
 | 
					  removepaidsigncondition:
 | 
				
			||||||
 | 
					    aliases:
 | 
				
			||||||
 | 
					      - rpsc
 | 
				
			||||||
    description: Used to remove a match condition from a paid sign
 | 
					    description: Used to remove a match condition from a paid sign
 | 
				
			||||||
    usage: /<command> <name (of a paid sign)> <line number>
 | 
					    usage: /<command> <name (of a paid sign)> <line number>
 | 
				
			||||||
    permission: paidsigns.manage
 | 
					    permission: paidsigns.manage
 | 
				
			||||||
  removepaidsign:
 | 
					  removepaidsign:
 | 
				
			||||||
 | 
					    aliases:
 | 
				
			||||||
 | 
					      - rps
 | 
				
			||||||
    description: Used to remove a paid sign
 | 
					    description: Used to remove a paid sign
 | 
				
			||||||
    usage: /<command> <name (of a paid sign)>
 | 
					    usage: /<command> <name (of a paid sign)>
 | 
				
			||||||
    permission: paidsigns.manage
 | 
					    permission: paidsigns.manage
 | 
				
			||||||
  reload:
 | 
					  reload:
 | 
				
			||||||
 | 
					    aliases:
 | 
				
			||||||
 | 
					      - r
 | 
				
			||||||
    description: Reloads paid signs from disk
 | 
					    description: Reloads paid signs from disk
 | 
				
			||||||
    usage: /<command>
 | 
					    usage: /<command>
 | 
				
			||||||
    permision: paidsigns.reload
 | 
					    permision: paidsigns.reload
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										27
									
								
								src/main/resources/strings.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								src/main/resources/strings.yml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					en:
 | 
				
			||||||
 | 
					  PREFIX: "[PaidSigns]"
 | 
				
			||||||
 | 
					  SUCCESS_ADDED_PAID_SIGN: "&bSuccessfully added new paid sign"
 | 
				
			||||||
 | 
					  SUCCESS_ADDED_PAID_SIGN_CONDITION: "&bSuccessfully added new paid sign condition"
 | 
				
			||||||
 | 
					  SUCCESS_UPDATED_PAID_SIGN: "&bSuccessfully updated the paid sign property"
 | 
				
			||||||
 | 
					  SUCCESS_UPDATED_PAID_SIGN_CONDITION: "&bSuccessfully updated the paid sign condition property"
 | 
				
			||||||
 | 
					  SUCCESS_REMOVED_PAID_SIGN: "&bSuccessfully removed paid sign"
 | 
				
			||||||
 | 
					  SUCCESS_REMOVED_CONDITION: "&bSuccessfully removed paid sign condition"
 | 
				
			||||||
 | 
					  SUCCESS_RELOADED: "&bSuccessfully reloaded configuration"
 | 
				
			||||||
 | 
					  SUCCESS_PAID_FOR_SIGN: "&bYou paid &3{cost} {unit} &bto create the sign"
 | 
				
			||||||
 | 
					  SUCCESS_REFUNDED: "&bYou were refunded &3{cost} {unit} &bfor your broken sign"
 | 
				
			||||||
 | 
					  PAID_SIGNS_INFO: "&f---&3Paid signs&f---{signs}\n&f-----------"
 | 
				
			||||||
 | 
					  PAID_SIGNS_INFO_FORMAT: "\n&f| &3{name}"
 | 
				
			||||||
 | 
					  PAID_SIGN_INFO: "&f---&3Paid sign&f---\n&f| &bName: &3{name}\n&f| &bCost: &3{cost}\n&f| &bPermission: &3{permission}\n&f| &bIgnore case: &3{case}\n&f| &bIgnore color: &3{color}\n&f| &bMatch any condition: &3{any}\n&f| &bSign conditions: &3{conditions}\n&f---------------"
 | 
				
			||||||
 | 
					  PAID_SIGN_INFO_CONDITION_FORMAT: "\n&f|  &b{line}: &3{condition}"
 | 
				
			||||||
 | 
					  PAID_SIGN_CONDITION_INFO: "&f---&3Paid sign condition&f---\n&f| &bPaid sign name: &3{name}\n&f| &bCondition line: &3{line}\n&f| &bMatch string: &3{match}\n&f| &bExecute RegEx: &3{regex}\n&f| &bIgnore case: &3{case}\n&f| &bIgnore color: &3{color}\n&f---------------"
 | 
				
			||||||
 | 
					  BOOLEAN_TRUE: "&2true"
 | 
				
			||||||
 | 
					  BOOLEAN_FALSE: "&4false"
 | 
				
			||||||
 | 
					  ERROR_INVALID_NUMBER: "&bYou provided an invalid number"
 | 
				
			||||||
 | 
					  ERROR_NAME_DUPLICATE: "&bA paid sign with the same name already exists"
 | 
				
			||||||
 | 
					  ERROR_EXCEPTION_OCCURRED: "&bAn exception occurred. Please notify the server administrator or check the server log."
 | 
				
			||||||
 | 
					  ERROR_INVALID_INPUT: "&bInvalid input: {input}"
 | 
				
			||||||
 | 
					  ERROR_PAID_SIGN_NOT_FOUND: "&bNo such paid sign exists"
 | 
				
			||||||
 | 
					  ERROR_NO_SUCH_CONDITION: "&bThe paid sign you specified has no condition for line {line}"
 | 
				
			||||||
 | 
					  ERROR_CANNOT_AFFORD: "&bYou cannot afford to create this sign"
 | 
				
			||||||
 | 
					  ERROR_INVALID_REGULAR_EXPRESSION: "&bThe provided regular expression is invalid"
 | 
				
			||||||
 | 
					  ERROR_PROPERTY_NOT_RECOGNIZED: "&bThe property you tried to change was not recognized"
 | 
				
			||||||
		Reference in New Issue
	
	Block a user