Initial commit
This commit is contained in:
commit
ed5690d197
113
.gitignore
vendored
Normal file
113
.gitignore
vendored
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
# User-specific stuff
|
||||||
|
.idea/
|
||||||
|
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
*.iws
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
out/
|
||||||
|
|
||||||
|
# Compiled class file
|
||||||
|
*.class
|
||||||
|
|
||||||
|
# Log file
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# BlueJ files
|
||||||
|
*.ctxt
|
||||||
|
|
||||||
|
# Package Files #
|
||||||
|
*.jar
|
||||||
|
*.war
|
||||||
|
*.nar
|
||||||
|
*.ear
|
||||||
|
*.zip
|
||||||
|
*.tar.gz
|
||||||
|
*.rar
|
||||||
|
|
||||||
|
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||||
|
hs_err_pid*
|
||||||
|
|
||||||
|
*~
|
||||||
|
|
||||||
|
# temporary files which can be created if a process still has a handle open of a deleted file
|
||||||
|
.fuse_hidden*
|
||||||
|
|
||||||
|
# KDE directory preferences
|
||||||
|
.directory
|
||||||
|
|
||||||
|
# Linux trash folder which might appear on any partition or disk
|
||||||
|
.Trash-*
|
||||||
|
|
||||||
|
# .nfs files are created when an open file is removed but is still being accessed
|
||||||
|
.nfs*
|
||||||
|
|
||||||
|
# General
|
||||||
|
.DS_Store
|
||||||
|
.AppleDouble
|
||||||
|
.LSOverride
|
||||||
|
|
||||||
|
# Icon must end with two \r
|
||||||
|
Icon
|
||||||
|
|
||||||
|
# Thumbnails
|
||||||
|
._*
|
||||||
|
|
||||||
|
# Files that might appear in the root of a volume
|
||||||
|
.DocumentRevisions-V100
|
||||||
|
.fseventsd
|
||||||
|
.Spotlight-V100
|
||||||
|
.TemporaryItems
|
||||||
|
.Trashes
|
||||||
|
.VolumeIcon.icns
|
||||||
|
.com.apple.timemachine.donotpresent
|
||||||
|
|
||||||
|
# Directories potentially created on remote AFP share
|
||||||
|
.AppleDB
|
||||||
|
.AppleDesktop
|
||||||
|
Network Trash Folder
|
||||||
|
Temporary Items
|
||||||
|
.apdisk
|
||||||
|
|
||||||
|
# Windows thumbnail cache files
|
||||||
|
Thumbs.db
|
||||||
|
Thumbs.db:encryptable
|
||||||
|
ehthumbs.db
|
||||||
|
ehthumbs_vista.db
|
||||||
|
|
||||||
|
# Dump file
|
||||||
|
*.stackdump
|
||||||
|
|
||||||
|
# Folder config file
|
||||||
|
[Dd]esktop.ini
|
||||||
|
|
||||||
|
# Recycle Bin used on file shares
|
||||||
|
$RECYCLE.BIN/
|
||||||
|
|
||||||
|
# Windows Installer files
|
||||||
|
*.cab
|
||||||
|
*.msi
|
||||||
|
*.msix
|
||||||
|
*.msm
|
||||||
|
*.msp
|
||||||
|
|
||||||
|
# Windows shortcuts
|
||||||
|
*.lnk
|
||||||
|
|
||||||
|
target/
|
||||||
|
|
||||||
|
pom.xml.tag
|
||||||
|
pom.xml.releaseBackup
|
||||||
|
pom.xml.versionsBackup
|
||||||
|
pom.xml.next
|
||||||
|
|
||||||
|
release.properties
|
||||||
|
dependency-reduced-pom.xml
|
||||||
|
buildNumber.properties
|
||||||
|
.mvn/timing.properties
|
||||||
|
.mvn/wrapper/maven-wrapper.jar
|
||||||
|
.flattened-pom.xml
|
||||||
|
|
||||||
|
# Common working directory
|
||||||
|
run/
|
92
pom.xml
Normal file
92
pom.xml
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>net.knarcraft</groupId>
|
||||||
|
<artifactId>paidsigns</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<name>Paid Signs</name>
|
||||||
|
|
||||||
|
<description>Add costs for creating plugin signs</description>
|
||||||
|
<properties>
|
||||||
|
<java.version>17</java.version>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
<url>https://git.knarcraft.net</url>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>3.8.1</version>
|
||||||
|
<configuration>
|
||||||
|
<source>16</source>
|
||||||
|
<target>16</target>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-shade-plugin</artifactId>
|
||||||
|
<version>3.2.4</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>shade</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
<resources>
|
||||||
|
<resource>
|
||||||
|
<directory>src/main/resources</directory>
|
||||||
|
<filtering>true</filtering>
|
||||||
|
</resource>
|
||||||
|
</resources>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>spigotmc-repo</id>
|
||||||
|
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
|
||||||
|
</repository>
|
||||||
|
<repository>
|
||||||
|
<id>sonatype</id>
|
||||||
|
<url>https://oss.sonatype.org/content/groups/public/</url>
|
||||||
|
</repository>
|
||||||
|
<repository>
|
||||||
|
<id>vault-repo</id>
|
||||||
|
<url>http://nexus.hc.to/content/repositories/pub_releases</url>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.spigotmc</groupId>
|
||||||
|
<artifactId>spigot-api</artifactId>
|
||||||
|
<version>1.18.1-R0.1-SNAPSHOT</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>net.milkbowl.vault</groupId>
|
||||||
|
<artifactId>VaultAPI</artifactId>
|
||||||
|
<version>1.7</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jetbrains</groupId>
|
||||||
|
<artifactId>annotations</artifactId>
|
||||||
|
<version>22.0.0</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
147
src/main/java/net/knarcraft/paidsigns/PaidSigns.java
Normal file
147
src/main/java/net/knarcraft/paidsigns/PaidSigns.java
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
package net.knarcraft.paidsigns;
|
||||||
|
|
||||||
|
import net.knarcraft.paidsigns.command.AddCommand;
|
||||||
|
import net.knarcraft.paidsigns.command.AddTabCompleter;
|
||||||
|
import net.knarcraft.paidsigns.command.ReloadTabCommand;
|
||||||
|
import net.knarcraft.paidsigns.command.RemoveCommand;
|
||||||
|
import net.knarcraft.paidsigns.command.RemoveTabCompleter;
|
||||||
|
import net.knarcraft.paidsigns.listener.SignListener;
|
||||||
|
import net.knarcraft.paidsigns.manager.EconomyManager;
|
||||||
|
import net.knarcraft.paidsigns.manager.PaidSignManager;
|
||||||
|
import net.milkbowl.vault.economy.Economy;
|
||||||
|
import org.bukkit.command.PluginCommand;
|
||||||
|
import org.bukkit.command.TabExecutor;
|
||||||
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
|
import org.bukkit.plugin.PluginManager;
|
||||||
|
import org.bukkit.plugin.RegisteredServiceProvider;
|
||||||
|
import org.bukkit.plugin.ServicesManager;
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The PaidSigns plugin's main class
|
||||||
|
*/
|
||||||
|
public final class PaidSigns extends JavaPlugin {
|
||||||
|
|
||||||
|
private static PaidSigns paidSigns;
|
||||||
|
private PaidSignManager signManager;
|
||||||
|
private boolean ignoreCase;
|
||||||
|
private boolean ignoreColor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a new paid signs object
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public PaidSigns() {
|
||||||
|
paidSigns = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets an instance of this plugin
|
||||||
|
*
|
||||||
|
* @return <p>An instance of this plugin</p>
|
||||||
|
*/
|
||||||
|
public static PaidSigns getInstance() {
|
||||||
|
return paidSigns;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onEnable() {
|
||||||
|
setupVault();
|
||||||
|
signManager = new PaidSignManager(PaidSignManager.loadSigns());
|
||||||
|
loadConfig();
|
||||||
|
|
||||||
|
PluginManager pluginManager = getServer().getPluginManager();
|
||||||
|
pluginManager.registerEvents(new SignListener(), this);
|
||||||
|
|
||||||
|
registerCommands();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDisable() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reloads this plugin
|
||||||
|
*/
|
||||||
|
public void reload() {
|
||||||
|
this.reloadConfig();
|
||||||
|
loadConfig();
|
||||||
|
signManager = new PaidSignManager(PaidSignManager.loadSigns());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the paid sign manager used to manage paid signs
|
||||||
|
*
|
||||||
|
* @return <p>The paid sign manager</p>
|
||||||
|
*/
|
||||||
|
public PaidSignManager getSignManager() {
|
||||||
|
return signManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the default setting for whether to ignore the case of paid sign ids
|
||||||
|
*
|
||||||
|
* @return <p>The default ignore case value</p>
|
||||||
|
*/
|
||||||
|
public boolean ignoreCase() {
|
||||||
|
return this.ignoreCase;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the default setting for whether to ignore the color of paid sign ids
|
||||||
|
*
|
||||||
|
* @return <p>The default ignore color value</p>
|
||||||
|
*/
|
||||||
|
public boolean ignoreColor() {
|
||||||
|
return this.ignoreColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers the commands used by this plugin
|
||||||
|
*/
|
||||||
|
private void registerCommands() {
|
||||||
|
PluginCommand addCommand = this.getCommand("addPaidSign");
|
||||||
|
if (addCommand != null) {
|
||||||
|
addCommand.setExecutor(new AddCommand());
|
||||||
|
addCommand.setTabCompleter(new AddTabCompleter());
|
||||||
|
}
|
||||||
|
|
||||||
|
PluginCommand removeCommand = this.getCommand("removePaidSign");
|
||||||
|
if (removeCommand != null) {
|
||||||
|
removeCommand.setExecutor(new RemoveCommand());
|
||||||
|
removeCommand.setTabCompleter(new RemoveTabCompleter());
|
||||||
|
}
|
||||||
|
|
||||||
|
PluginCommand reloadCommand = this.getCommand("reload");
|
||||||
|
if (reloadCommand != null) {
|
||||||
|
TabExecutor reloadTabExecutor = new ReloadTabCommand();
|
||||||
|
reloadCommand.setExecutor(reloadTabExecutor);
|
||||||
|
reloadCommand.setTabCompleter(reloadTabExecutor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the configuration file
|
||||||
|
*/
|
||||||
|
private void loadConfig() {
|
||||||
|
FileConfiguration config = this.getConfig();
|
||||||
|
config.options().copyDefaults(true);
|
||||||
|
this.saveDefaultConfig();
|
||||||
|
ignoreCase = config.getBoolean("ignoreCase", true);
|
||||||
|
ignoreColor = config.getBoolean("ignoreColor", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets up Vault by getting plugins from their providers
|
||||||
|
*/
|
||||||
|
private void setupVault() {
|
||||||
|
ServicesManager servicesManager = this.getServer().getServicesManager();
|
||||||
|
RegisteredServiceProvider<Economy> economyProvider = servicesManager.getRegistration(Economy.class);
|
||||||
|
if (economyProvider != null) {
|
||||||
|
EconomyManager.initialize(economyProvider.getProvider());
|
||||||
|
} else {
|
||||||
|
throw new IllegalStateException("[PaidSigns] Error: Vault could not be loaded");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,76 @@
|
|||||||
|
package net.knarcraft.paidsigns.command;
|
||||||
|
|
||||||
|
import net.knarcraft.paidsigns.PaidSigns;
|
||||||
|
import net.knarcraft.paidsigns.container.PaidSign;
|
||||||
|
import net.knarcraft.paidsigns.manager.PaidSignManager;
|
||||||
|
import net.knarcraft.paidsigns.property.OptionState;
|
||||||
|
import net.knarcraft.paidsigns.utility.Tokenizer;
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandExecutor;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A representation of the command for adding a new paid sign
|
||||||
|
*/
|
||||||
|
public class AddCommand implements CommandExecutor {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label,
|
||||||
|
@NotNull String[] args) {
|
||||||
|
if (args.length < 3) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
PaidSignManager manager = PaidSigns.getInstance().getSignManager();
|
||||||
|
List<String> arguments = Tokenizer.tokenize(String.join(" ", args));
|
||||||
|
|
||||||
|
String id = arguments.get(0);
|
||||||
|
short line;
|
||||||
|
double cost;
|
||||||
|
try {
|
||||||
|
line = (short) (Short.parseShort(arguments.get(1)) - 1);
|
||||||
|
cost = Double.parseDouble(arguments.get(2));
|
||||||
|
} catch (NumberFormatException exception) {
|
||||||
|
sender.sendMessage("You provided an invalid number");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
OptionState ignoreCase = OptionState.DEFAULT;
|
||||||
|
OptionState ignoreColor = OptionState.DEFAULT;
|
||||||
|
if (arguments.size() > 3) {
|
||||||
|
ignoreCase = OptionState.fromString(arguments.get(3));
|
||||||
|
}
|
||||||
|
if (arguments.size() > 4) {
|
||||||
|
ignoreColor = OptionState.fromString(arguments.get(4));
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
PaidSign sign = new PaidSign(id, line, cost, ignoreCase, ignoreColor);
|
||||||
|
for (PaidSign similarSign : manager.getPaidSigns(sign.getCleanId(), sign.getLineIndex())) {
|
||||||
|
if (sign.matches(similarSign)) {
|
||||||
|
sender.sendMessage("A paid sign with the same id and line already exists");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
manager.addPaidSign(sign);
|
||||||
|
sender.sendMessage("Successfully added new paid sign");
|
||||||
|
return true;
|
||||||
|
} catch (IOException e) {
|
||||||
|
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()));
|
||||||
|
sender.sendMessage("An exception occurred. Please notify the server administrator or check the server log.");
|
||||||
|
return false;
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
sender.sendMessage("Invalid input: " + e.getMessage());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,71 @@
|
|||||||
|
package net.knarcraft.paidsigns.command;
|
||||||
|
|
||||||
|
import net.knarcraft.paidsigns.utility.Tokenizer;
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.command.TabCompleter;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The tab completer for the add paid sign command
|
||||||
|
*/
|
||||||
|
public class AddTabCompleter implements TabCompleter {
|
||||||
|
|
||||||
|
private static List<String> ids;
|
||||||
|
private static List<String> lines;
|
||||||
|
private static List<String> costs;
|
||||||
|
private static List<String> options;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias,
|
||||||
|
@NotNull String[] args) {
|
||||||
|
if (ids == null) {
|
||||||
|
initializeValues();
|
||||||
|
}
|
||||||
|
List<String> arguments = Tokenizer.tokenize(String.join(" ", args));
|
||||||
|
|
||||||
|
if (arguments.size() < 1) {
|
||||||
|
return ids;
|
||||||
|
} else if (arguments.size() < 2) {
|
||||||
|
return lines;
|
||||||
|
} else if (arguments.size() < 3) {
|
||||||
|
return costs;
|
||||||
|
} else if (arguments.size() < 5) {
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the values available for tab completion
|
||||||
|
*/
|
||||||
|
private static void initializeValues() {
|
||||||
|
ids = new ArrayList<>();
|
||||||
|
ids.add("[Gate]");
|
||||||
|
ids.add("\"[Lift Up]\"");
|
||||||
|
ids.add("\"[Lift Down]\"");
|
||||||
|
|
||||||
|
lines = new ArrayList<>();
|
||||||
|
lines.add("1");
|
||||||
|
lines.add("2");
|
||||||
|
lines.add("3");
|
||||||
|
lines.add("4");
|
||||||
|
|
||||||
|
costs = new ArrayList<>();
|
||||||
|
costs.add("1");
|
||||||
|
costs.add("5");
|
||||||
|
costs.add("10");
|
||||||
|
costs.add("15");
|
||||||
|
|
||||||
|
options = new ArrayList<>();
|
||||||
|
options.add("default");
|
||||||
|
options.add("true");
|
||||||
|
options.add("false");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package net.knarcraft.paidsigns.command;
|
||||||
|
|
||||||
|
import net.knarcraft.paidsigns.PaidSigns;
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.command.TabExecutor;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A representation of the command for reloading the plugin
|
||||||
|
*/
|
||||||
|
public class ReloadTabCommand implements TabExecutor {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label,
|
||||||
|
@NotNull String[] args) {
|
||||||
|
PaidSigns.getInstance().reload();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias,
|
||||||
|
@NotNull String[] args) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,55 @@
|
|||||||
|
package net.knarcraft.paidsigns.command;
|
||||||
|
|
||||||
|
import net.knarcraft.paidsigns.PaidSigns;
|
||||||
|
import net.knarcraft.paidsigns.utility.Tokenizer;
|
||||||
|
import org.apache.commons.lang.ArrayUtils;
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandExecutor;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A representation of the command for removing a paid sign
|
||||||
|
*/
|
||||||
|
public class RemoveCommand implements CommandExecutor {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label,
|
||||||
|
@NotNull String[] args) {
|
||||||
|
if (args.length < 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
List<String> arguments = Tokenizer.tokenize(String.join(" ", args));
|
||||||
|
String[] input = arguments.get(0).split("\\|");
|
||||||
|
short line;
|
||||||
|
try {
|
||||||
|
line = (short) (Short.parseShort(input[0]) - 1);
|
||||||
|
} catch (NumberFormatException exception) {
|
||||||
|
sender.sendMessage("Invalid line number given");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
String id = String.join("|", (String[]) ArrayUtils.remove(input, 0));
|
||||||
|
try {
|
||||||
|
if (PaidSigns.getInstance().getSignManager().removePaidSign(id, line)) {
|
||||||
|
sender.sendMessage("Successfully removed paid sign");
|
||||||
|
} else {
|
||||||
|
sender.sendMessage("No matching paid sign was found");
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} catch (IOException e) {
|
||||||
|
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()));
|
||||||
|
sender.sendMessage("An exception occurred. Please notify the server administrator or check the server log.");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
package net.knarcraft.paidsigns.command;
|
||||||
|
|
||||||
|
import net.knarcraft.paidsigns.PaidSigns;
|
||||||
|
import net.knarcraft.paidsigns.container.PaidSign;
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.command.TabCompleter;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The tab completer for the remove command
|
||||||
|
*/
|
||||||
|
public class RemoveTabCompleter implements TabCompleter {
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias,
|
||||||
|
@NotNull String[] args) {
|
||||||
|
List<PaidSign> allPaidSigns = PaidSigns.getInstance().getSignManager().getAllPaidSigns();
|
||||||
|
List<String> signIds = new ArrayList<>();
|
||||||
|
for (PaidSign sign : allPaidSigns) {
|
||||||
|
signIds.add("\"" + (sign.getLineIndex() + 1) + "|" + sign.getId() + "\"");
|
||||||
|
}
|
||||||
|
return signIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
157
src/main/java/net/knarcraft/paidsigns/container/PaidSign.java
Normal file
157
src/main/java/net/knarcraft/paidsigns/container/PaidSign.java
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
package net.knarcraft.paidsigns.container;
|
||||||
|
|
||||||
|
import net.knarcraft.paidsigns.PaidSigns;
|
||||||
|
import net.knarcraft.paidsigns.property.OptionState;
|
||||||
|
import net.knarcraft.paidsigns.utility.ColorHelper;
|
||||||
|
import net.md_5.bungee.api.ChatColor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A representation of a paid sign
|
||||||
|
*/
|
||||||
|
public class PaidSign {
|
||||||
|
|
||||||
|
private final String id;
|
||||||
|
private final String cleanId;
|
||||||
|
private final short lineIndex;
|
||||||
|
private final double cost;
|
||||||
|
private final OptionState ignoreCase;
|
||||||
|
private final OptionState ignoreColor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a new paid sign
|
||||||
|
*
|
||||||
|
* @param id <p>The string that identifies this type of paid sign</p>
|
||||||
|
* @param lineIndex <p>The line the id has to be on to trigger payment</p>
|
||||||
|
* @param cost <p>The cost of creating this paid 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>
|
||||||
|
*/
|
||||||
|
public PaidSign(String id, short lineIndex, double cost, OptionState ignoreCase, OptionState ignoreColor) {
|
||||||
|
if (id == null || id.trim().isBlank()) {
|
||||||
|
throw new IllegalArgumentException("Id cannot be empty");
|
||||||
|
}
|
||||||
|
if (cost <= 0) {
|
||||||
|
throw new IllegalArgumentException("Cost must be larger than 0");
|
||||||
|
}
|
||||||
|
if (lineIndex < 0 || lineIndex > 3) {
|
||||||
|
throw new IllegalArgumentException("Sign line must be between 0 and 3");
|
||||||
|
}
|
||||||
|
if (ignoreCase == null || ignoreColor == null) {
|
||||||
|
throw new IllegalArgumentException("Ignore case and ignore color options cannot be null");
|
||||||
|
}
|
||||||
|
this.id = id;
|
||||||
|
this.lineIndex = lineIndex;
|
||||||
|
this.cost = cost;
|
||||||
|
this.ignoreCase = ignoreCase;
|
||||||
|
this.ignoreColor = ignoreColor;
|
||||||
|
this.cleanId = getCleanString(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the id string of this paid sign
|
||||||
|
*
|
||||||
|
* @return <p>The id string of this paid sign</p>
|
||||||
|
*/
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the cost of creating a sign matching this paid sign
|
||||||
|
*
|
||||||
|
* @return <p>The cost of creating a sign matching this paid sign</p>
|
||||||
|
*/
|
||||||
|
public double getCost() {
|
||||||
|
return this.cost;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the line on the sign the id must be on to trigger payment
|
||||||
|
*
|
||||||
|
* @return <p>The sign line to search for the id</p>
|
||||||
|
*/
|
||||||
|
public short getLineIndex() {
|
||||||
|
return lineIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the clean id of this paid sign
|
||||||
|
*
|
||||||
|
* @return <p>The clean id of this paid sign</p>
|
||||||
|
*/
|
||||||
|
public String getCleanId() {
|
||||||
|
return cleanId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the "clean" version of the given string
|
||||||
|
*
|
||||||
|
* <p>The "cleaning" removes color codes and lower-cases the string.</p>
|
||||||
|
*
|
||||||
|
* @param string <p>The string to clean</p>
|
||||||
|
* @return <p>The cleaned string</p>
|
||||||
|
*/
|
||||||
|
public static String getCleanString(String string) {
|
||||||
|
return ChatColor.stripColor(ColorHelper.translateAllColorCodes(string.toLowerCase()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether this paid sign matches the given line
|
||||||
|
*
|
||||||
|
* @param lineNumber <p>The line number of the given line</p>
|
||||||
|
* @param line <p>The line to compare against this paid sign's id</p>
|
||||||
|
* @return <p>True if the line matches this sign</p>
|
||||||
|
*/
|
||||||
|
public boolean matches(short lineNumber, String line) {
|
||||||
|
if (lineNumber != this.lineIndex) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
String idCopy = id;
|
||||||
|
if (getIgnoreCase()) {
|
||||||
|
idCopy = idCopy.toLowerCase();
|
||||||
|
line = line.toLowerCase();
|
||||||
|
}
|
||||||
|
if (getIgnoreColor()) {
|
||||||
|
idCopy = ColorHelper.stripColorCodes(idCopy);
|
||||||
|
line = ColorHelper.stripColorCodes(line);
|
||||||
|
}
|
||||||
|
return idCopy.equals(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether this paid sign matches another paid sign
|
||||||
|
*
|
||||||
|
* @param paidSign <p>The other paid sign to compare to</p>
|
||||||
|
* @return <p>True if the signs match</p>
|
||||||
|
*/
|
||||||
|
public boolean matches(PaidSign paidSign) {
|
||||||
|
return matches(paidSign.lineIndex, paidSign.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets whether the text case should be ignored for this paid sign
|
||||||
|
*
|
||||||
|
* @return <p>Whether the text case should be ignored for this paid sign</p>
|
||||||
|
*/
|
||||||
|
public boolean getIgnoreCase() {
|
||||||
|
if (this.ignoreCase == OptionState.DEFAULT) {
|
||||||
|
return PaidSigns.getInstance().ignoreCase();
|
||||||
|
} else {
|
||||||
|
return OptionState.getBooleanValue(this.ignoreCase);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets whether the text color should be ignored for this paid sign
|
||||||
|
*
|
||||||
|
* @return <p>Whether the text color should be ignored for this paid sign</p>
|
||||||
|
*/
|
||||||
|
public boolean getIgnoreColor() {
|
||||||
|
if (this.ignoreColor == OptionState.DEFAULT) {
|
||||||
|
return PaidSigns.getInstance().ignoreColor();
|
||||||
|
} else {
|
||||||
|
return OptionState.getBooleanValue(this.ignoreColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,69 @@
|
|||||||
|
package net.knarcraft.paidsigns.listener;
|
||||||
|
|
||||||
|
import net.knarcraft.paidsigns.PaidSigns;
|
||||||
|
import net.knarcraft.paidsigns.container.PaidSign;
|
||||||
|
import net.knarcraft.paidsigns.manager.EconomyManager;
|
||||||
|
import net.knarcraft.paidsigns.manager.PaidSignManager;
|
||||||
|
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.SignChangeEvent;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A listener for listening to registered paid signs
|
||||||
|
*/
|
||||||
|
public class SignListener implements Listener {
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.LOW)
|
||||||
|
public void onSignChange(SignChangeEvent event) {
|
||||||
|
if (event.isCancelled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String[] lines = event.getLines();
|
||||||
|
PaidSignManager signManager = PaidSigns.getInstance().getSignManager();
|
||||||
|
for (short lineIndex = 0; lineIndex < lines.length; lineIndex++) {
|
||||||
|
//Get all "weak" matches (any paid sign with a clean id matching the clean line)
|
||||||
|
List<PaidSign> matchingSigns = signManager.getPaidSigns(PaidSign.getCleanString(lines[lineIndex]), lineIndex);
|
||||||
|
if (matchingSigns.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (testMatchingSigns(lineIndex, lines[lineIndex], matchingSigns, event)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests all weak matches of paid signs to check if a strong match is found
|
||||||
|
*
|
||||||
|
* @param lineIndex <p>The index of the currently managed line</p>
|
||||||
|
* @param line <p>The text on the currently managed line</p>
|
||||||
|
* @param matchingSigns <p>The signs that weakly match the </p>
|
||||||
|
* @param event <p>The triggered sign change event</p>
|
||||||
|
* @return <p>True if a match was found and thw work is finished</p>
|
||||||
|
*/
|
||||||
|
private boolean testMatchingSigns(short lineIndex, String line, List<PaidSign> matchingSigns, SignChangeEvent event) {
|
||||||
|
for (PaidSign paidSign : matchingSigns) {
|
||||||
|
if (paidSign.matches(lineIndex, line)) {
|
||||||
|
Player player = event.getPlayer();
|
||||||
|
double cost = paidSign.getCost();
|
||||||
|
boolean canAfford = EconomyManager.canAfford(player, cost);
|
||||||
|
if (!canAfford) {
|
||||||
|
player.sendMessage("[PaidSigns] You cannot afford to create this sign");
|
||||||
|
event.setCancelled(true);
|
||||||
|
} else {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
package net.knarcraft.paidsigns.manager;
|
||||||
|
|
||||||
|
import net.milkbowl.vault.economy.Economy;
|
||||||
|
import org.bukkit.OfflinePlayer;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A manager that performs all Economy tasks
|
||||||
|
*/
|
||||||
|
public final class EconomyManager {
|
||||||
|
|
||||||
|
private static Economy economy;
|
||||||
|
|
||||||
|
private EconomyManager() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the economy manager
|
||||||
|
*
|
||||||
|
* @param economy <p>The economy object to use for everything economy-related</p>
|
||||||
|
*/
|
||||||
|
public static void initialize(Economy economy) {
|
||||||
|
EconomyManager.economy = economy;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the given player can afford the given cost
|
||||||
|
*
|
||||||
|
* @param player <p>The player to pay the cost</p>
|
||||||
|
* @param cost <p>The cost the player needs to pay</p>
|
||||||
|
* @return <p>True if the player is able to afford the cost</p>
|
||||||
|
*/
|
||||||
|
public static boolean canAfford(OfflinePlayer player, double cost) {
|
||||||
|
return economy.has(player, cost);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the name of the used currency
|
||||||
|
*
|
||||||
|
* @param plural <p>Whether to get the plural name or the singular name</p>
|
||||||
|
* @return <p>The name of the used currency</p>
|
||||||
|
*/
|
||||||
|
public static String getCurrency(boolean plural) {
|
||||||
|
if (plural) {
|
||||||
|
return economy.currencyNamePlural();
|
||||||
|
} else {
|
||||||
|
return economy.currencyNameSingular();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Withdraws the given cost from the given player's account
|
||||||
|
*
|
||||||
|
* @param player <p>The player to withdraw money from</p>
|
||||||
|
* @param cost <p>The amount of money to withdraw</p>
|
||||||
|
*/
|
||||||
|
public static void withdraw(Player player, double cost) {
|
||||||
|
economy.withdrawPlayer(player, cost);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,160 @@
|
|||||||
|
package net.knarcraft.paidsigns.manager;
|
||||||
|
|
||||||
|
import net.knarcraft.paidsigns.PaidSigns;
|
||||||
|
import net.knarcraft.paidsigns.container.PaidSign;
|
||||||
|
import net.knarcraft.paidsigns.property.OptionState;
|
||||||
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A manager that keeps track of all registered paid signs
|
||||||
|
*/
|
||||||
|
public final class PaidSignManager {
|
||||||
|
|
||||||
|
private final List<PaidSign> paidSigns;
|
||||||
|
private static final File signsFile = new File(PaidSigns.getInstance().getDataFolder(), "data.yml");
|
||||||
|
private static final String signLineIdSeparator = "-,_,-";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate a new paid sign manager
|
||||||
|
*
|
||||||
|
* @param paidSigns <p>The paid signs this manager should manage</p>
|
||||||
|
*/
|
||||||
|
public PaidSignManager(List<PaidSign> paidSigns) {
|
||||||
|
this.paidSigns = paidSigns;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a new paid sign to this paid sign manager
|
||||||
|
*
|
||||||
|
* @param paidSign <p>The paid sign to add</p>
|
||||||
|
* @throws IOException <p>If unable to write to the signs file</p>
|
||||||
|
*/
|
||||||
|
public void addPaidSign(PaidSign paidSign) throws IOException {
|
||||||
|
this.paidSigns.add(paidSign);
|
||||||
|
saveSigns(this.paidSigns);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a paid sign from this paid sign manager
|
||||||
|
*
|
||||||
|
* @param id <p>The identifier for the paid sign to remove</p>
|
||||||
|
* @param line <p>The line the identifier has to match to be valid</p>
|
||||||
|
* @return <p>True if a sign was removed</p>
|
||||||
|
* @throws IOException <p>If unable to write to the signs file</p>
|
||||||
|
*/
|
||||||
|
public boolean removePaidSign(String id, short line) throws IOException {
|
||||||
|
boolean removed = this.paidSigns.removeIf((sign) -> sign.getId().equals(id) && sign.getLineIndex() == line);
|
||||||
|
if (!removed) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
saveSigns(this.paidSigns);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the paid signs that match the given properties
|
||||||
|
*
|
||||||
|
* @param cleanId <p>The clean id to search for</p>
|
||||||
|
* @param line <p>The line number to search for</p>
|
||||||
|
* @return <p>The paid signs that matched the given properties</p>
|
||||||
|
*/
|
||||||
|
public List<PaidSign> getPaidSigns(String cleanId, short line) {
|
||||||
|
return filterPaidSigns(filterPaidSigns(paidSigns, line), cleanId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a copy of all registered paid signs
|
||||||
|
*
|
||||||
|
* @return <p>All registered paid signs</p>
|
||||||
|
*/
|
||||||
|
public List<PaidSign> getAllPaidSigns() {
|
||||||
|
return new ArrayList<>(paidSigns);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filters a list of paid signs to match the given line number
|
||||||
|
*
|
||||||
|
* @param paidSigns <p>The list of paid signs to start with</p>
|
||||||
|
* @param line <p>The line number to filter by</p>
|
||||||
|
* @return <p>The filtered list of paid signs</p>
|
||||||
|
*/
|
||||||
|
private static List<PaidSign> filterPaidSigns(List<PaidSign> paidSigns, short line) {
|
||||||
|
return filterPaidSigns(paidSigns, (paidSign) -> paidSign.getLineIndex() == line);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads paid signs from the signs file
|
||||||
|
*
|
||||||
|
* @return <p>The loaded paid signs</p>
|
||||||
|
*/
|
||||||
|
public static List<PaidSign> loadSigns() {
|
||||||
|
YamlConfiguration configuration = YamlConfiguration.loadConfiguration(signsFile);
|
||||||
|
ConfigurationSection signSection = configuration.getConfigurationSection("paidSigns");
|
||||||
|
if (signSection == null) {
|
||||||
|
PaidSigns.getInstance().getLogger().log(Level.WARNING, "Signs section not found in data.yml");
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<PaidSign> paidSigns = new ArrayList<>();
|
||||||
|
for (String combinedId : signSection.getKeys(false)) {
|
||||||
|
String[] idParts = combinedId.split(signLineIdSeparator);
|
||||||
|
short lineNumber = Short.parseShort(idParts[0]);
|
||||||
|
String id = idParts[1];
|
||||||
|
double cost = signSection.getDouble(combinedId + ".cost");
|
||||||
|
OptionState ignoreCase = OptionState.getFromBoolean(signSection.getBoolean(combinedId + ".ignoreCase"));
|
||||||
|
OptionState ignoreColor = OptionState.getFromBoolean(signSection.getBoolean(combinedId + ".ignoreColor"));
|
||||||
|
paidSigns.add(new PaidSign(id, lineNumber, cost, ignoreCase, ignoreColor));
|
||||||
|
}
|
||||||
|
return paidSigns;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves the given paid signs to the signs file
|
||||||
|
*
|
||||||
|
* @param signs <p>The signs to save</p>
|
||||||
|
* @throws IOException <p>If unable to write to the signs file</p>
|
||||||
|
*/
|
||||||
|
public static void saveSigns(List<PaidSign> signs) throws IOException {
|
||||||
|
YamlConfiguration configuration = YamlConfiguration.loadConfiguration(signsFile);
|
||||||
|
ConfigurationSection signSection = configuration.createSection("paidSigns");
|
||||||
|
|
||||||
|
for (PaidSign sign : signs) {
|
||||||
|
String signId = sign.getLineIndex() + signLineIdSeparator + sign.getId();
|
||||||
|
signSection.set(signId + ".cost", sign.getCost());
|
||||||
|
signSection.set(signId + ".ignoreCase", sign.getIgnoreCase());
|
||||||
|
signSection.set(signId + ".ignoreColor", sign.getIgnoreColor());
|
||||||
|
}
|
||||||
|
configuration.save(signsFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filters a list of paid signs to match the given clean id
|
||||||
|
*
|
||||||
|
* @param paidSigns <p>The list of paid signs to start with</p>
|
||||||
|
* @param cleanId <p>The clean id to filter by</p>
|
||||||
|
* @return <p>The filtered list of paid signs</p>
|
||||||
|
*/
|
||||||
|
private static List<PaidSign> filterPaidSigns(List<PaidSign> paidSigns, String cleanId) {
|
||||||
|
return filterPaidSigns(paidSigns, (paidSign) -> paidSign.getCleanId().equals(cleanId));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filters a list of paid signs using the given predicate
|
||||||
|
*
|
||||||
|
* @param paidSigns <p>The list of paid signs to start with</p>
|
||||||
|
* @param predicate <p>The predicate used to filter paid signs</p>
|
||||||
|
* @return <p>The filtered list of paid signs</p>
|
||||||
|
*/
|
||||||
|
private static List<PaidSign> filterPaidSigns(List<PaidSign> paidSigns, Predicate<PaidSign> predicate) {
|
||||||
|
return new ArrayList<>(paidSigns).stream().filter(predicate).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,65 @@
|
|||||||
|
package net.knarcraft.paidsigns.property;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A class representing the different available states for a paid sign option
|
||||||
|
*/
|
||||||
|
public enum OptionState {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The option is enabled
|
||||||
|
*/
|
||||||
|
TRUE,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The option is disabled
|
||||||
|
*/
|
||||||
|
FALSE,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The option is the same as the default value
|
||||||
|
*/
|
||||||
|
DEFAULT;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the boolean value of the given option state if it's boolean compatible
|
||||||
|
*
|
||||||
|
* @param optionState <p>The option state to get the boolean from</p>
|
||||||
|
* @return <p>The boolean value, or an illegal argument exception if called on DEFAULT</p>
|
||||||
|
*/
|
||||||
|
public static boolean getBooleanValue(OptionState optionState) {
|
||||||
|
return switch (optionState) {
|
||||||
|
case TRUE -> true;
|
||||||
|
case FALSE -> false;
|
||||||
|
case DEFAULT -> throw new IllegalArgumentException("No boolean value available for DEFAULT");
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the corresponding option state from the given boolean
|
||||||
|
*
|
||||||
|
* @param value <p>The boolean to parse</p>
|
||||||
|
* @return <p>The corresponding option state</p>
|
||||||
|
*/
|
||||||
|
public static OptionState getFromBoolean(boolean value) {
|
||||||
|
if (value) {
|
||||||
|
return OptionState.TRUE;
|
||||||
|
} else {
|
||||||
|
return OptionState.FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the option state corresponding to the given string
|
||||||
|
*
|
||||||
|
* @param string <p>The string to parse to an option state</p>
|
||||||
|
* @return <p>The option state corresponding to the given string</p>
|
||||||
|
*/
|
||||||
|
public static OptionState fromString(String string) {
|
||||||
|
if (string.equalsIgnoreCase("default") || string.equalsIgnoreCase("def")) {
|
||||||
|
return OptionState.DEFAULT;
|
||||||
|
} else {
|
||||||
|
return getFromBoolean(Boolean.parseBoolean(string));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
package net.knarcraft.paidsigns.utility;
|
||||||
|
|
||||||
|
import net.md_5.bungee.api.ChatColor;
|
||||||
|
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A helper class for dealing with colors
|
||||||
|
*/
|
||||||
|
public final class ColorHelper {
|
||||||
|
|
||||||
|
private ColorHelper() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Strips all color codes from the given message
|
||||||
|
*
|
||||||
|
* @param message <p>The message to strip color codes from</p>
|
||||||
|
* @return <p>The message without color codes</p>
|
||||||
|
*/
|
||||||
|
public static String stripColorCodes(String message) {
|
||||||
|
return ChatColor.stripColor(translateAllColorCodes(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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
99
src/main/java/net/knarcraft/paidsigns/utility/Tokenizer.java
Normal file
99
src/main/java/net/knarcraft/paidsigns/utility/Tokenizer.java
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
package net.knarcraft.paidsigns.utility;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A tokenizer for being able to support quotes in commands
|
||||||
|
*/
|
||||||
|
public class Tokenizer {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tokenizes a string
|
||||||
|
*
|
||||||
|
* @param input <p>A string.</p>
|
||||||
|
* @return <p>A list of tokens.</p>
|
||||||
|
*/
|
||||||
|
public static List<String> tokenize(String input) {
|
||||||
|
List<String> tokens = new ArrayList<>();
|
||||||
|
boolean startedQuote = false;
|
||||||
|
StringBuilder currentToken = new StringBuilder();
|
||||||
|
for (int index = 0; index < input.length(); index++) {
|
||||||
|
char character = input.charAt(index);
|
||||||
|
switch (character) {
|
||||||
|
case ' ':
|
||||||
|
if (tokenizeSpace(startedQuote, currentToken, tokens)) {
|
||||||
|
currentToken = new StringBuilder();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '"':
|
||||||
|
if (startedQuote) {
|
||||||
|
//This quote signifies the end of the argument
|
||||||
|
if (isNotEmpty(currentToken)) {
|
||||||
|
tokens.add(currentToken.toString());
|
||||||
|
currentToken = new StringBuilder();
|
||||||
|
}
|
||||||
|
startedQuote = false;
|
||||||
|
} else {
|
||||||
|
//This quote signifies the start of the argument
|
||||||
|
startedQuote = true;
|
||||||
|
currentToken = new StringBuilder();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
tokenizeNormalCharacter(currentToken, character, input.length(), index, tokens);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tokens;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a normal character to the token. Adds the current token to tokens if at the end of the input
|
||||||
|
*
|
||||||
|
* @param currentToken <p>The string builder containing the current token.</p>
|
||||||
|
* @param character <p>The character found in the input.</p>
|
||||||
|
* @param inputLength <p>The length of the given input</p>
|
||||||
|
* @param index <p>The index of the read character.</p>
|
||||||
|
* @param tokens <p>The list of processed tokens.</p>
|
||||||
|
*/
|
||||||
|
private static void tokenizeNormalCharacter(StringBuilder currentToken, char character, int inputLength, int index,
|
||||||
|
List<String> tokens) {
|
||||||
|
currentToken.append(character);
|
||||||
|
if (index == inputLength - 1) {
|
||||||
|
tokens.add(currentToken.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tokenizes a space character
|
||||||
|
*
|
||||||
|
* @param startedQuote <p>Whether this space is inside a pair of quotes.</p>
|
||||||
|
* @param currentToken <p>The string builder containing the current token.</p>
|
||||||
|
* @param tokens <p>The list of processed tokens.</p>
|
||||||
|
* @return <p>True if the token is finished.</p>
|
||||||
|
*/
|
||||||
|
private static boolean tokenizeSpace(boolean startedQuote, StringBuilder currentToken, List<String> tokens) {
|
||||||
|
if (!startedQuote) {
|
||||||
|
//If not inside "", a space marks the end of a parameter
|
||||||
|
if (isNotEmpty(currentToken)) {
|
||||||
|
tokens.add(currentToken.toString());
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
currentToken.append(' ');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether a string builder is empty
|
||||||
|
*
|
||||||
|
* @param builder <p>The string builder to check.</p>
|
||||||
|
* @return <p>True if the string builder is non empty.</p>
|
||||||
|
*/
|
||||||
|
private static boolean isNotEmpty(StringBuilder builder) {
|
||||||
|
return !builder.toString().trim().equals("");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
8
src/main/resources/config.yml
Normal file
8
src/main/resources/config.yml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# 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 case-sensitive or not.
|
||||||
|
ignoreCase: true
|
||||||
|
|
||||||
|
# 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 whether the plugin
|
||||||
|
# signs it should match allow coloring or not.
|
||||||
|
ignoreColor: false
|
39
src/main/resources/plugin.yml
Normal file
39
src/main/resources/plugin.yml
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
name: PaidSigns
|
||||||
|
version: '${project.version}'
|
||||||
|
main: net.knarcraft.paidsigns.PaidSigns
|
||||||
|
api-version: 1.18
|
||||||
|
prefix: PaidSigns
|
||||||
|
depend: [ Vault ]
|
||||||
|
authors: [ EpicKnarvik97 ]
|
||||||
|
description: Add costs for creating plugin signs
|
||||||
|
website: https://git.knarcraft.net
|
||||||
|
commands:
|
||||||
|
addpaidsign:
|
||||||
|
description: Used to add a new paid sign
|
||||||
|
usage: /<command> <id (the text to look for)> <line> <cost> [ignore case] [ignore color]
|
||||||
|
permission: paidsigns.add
|
||||||
|
removepaidsign:
|
||||||
|
description: Used to remove a paid sign
|
||||||
|
usage: /<command> <id (the text to look for)> <line>
|
||||||
|
permission: paidsigns.remove
|
||||||
|
reload:
|
||||||
|
description: Reloads paid signs from disk
|
||||||
|
usage: /<command>
|
||||||
|
permision: paidsigns.reload
|
||||||
|
permissions:
|
||||||
|
paidsigns.*:
|
||||||
|
description: Grants all paid signs permissions
|
||||||
|
default: op
|
||||||
|
children:
|
||||||
|
paidsigns.create: true
|
||||||
|
paidsigns.paymentexempt: true
|
||||||
|
paidsigns.reload: true
|
||||||
|
paidsigns.add:
|
||||||
|
description: Grants the permission to add/remove a paid sign
|
||||||
|
default: false
|
||||||
|
paidsigns.reload:
|
||||||
|
description: Grants the permissions to reload the plugin
|
||||||
|
default: false
|
||||||
|
paidsigns.paymentexempt:
|
||||||
|
description: Makes this player exempt from the cost of paid signs
|
||||||
|
default: false
|
Loading…
Reference in New Issue
Block a user