Initial commit
This commit is contained in:
commit
ea3f25e278
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/
|
28
README.md
Normal file
28
README.md
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
# Placeholder Signs
|
||||||
|
|
||||||
|
This is a minimal plugin created for a single purpose: Displaying placeholders from PlaceholderAPI on signs. Note that
|
||||||
|
this plugin only works for placeholders which do not require a player, as the same text will be displayed to everyone!
|
||||||
|
|
||||||
|
How it works: After installing this plugin, whenever a sign is changed to contain a placeholder replaced by
|
||||||
|
PlaceholderAPI, the location of the sign, and the lines containing placeholders are saved. Those lines are updated at a
|
||||||
|
set pace by using the saved original lines, and letting PlaceholderAPI replace them. Any color, formatting or RGB color
|
||||||
|
codes in the original text will be converted each time the sign is updated.
|
||||||
|
|
||||||
|
The /editSign command is basically just a command to allow placeholders that won't fit on a sign to be used. As an
|
||||||
|
additional benefit, formatting, color and RGB color codes are automatically converted whenever the command is used to
|
||||||
|
change sign text.
|
||||||
|
|
||||||
|
Note that when clicking a sign after using /editSign, a SignChangeEvent is triggered. This means that the sign text
|
||||||
|
won't be changed unless the player passes all world protection checks.
|
||||||
|
|
||||||
|
## Commands
|
||||||
|
|
||||||
|
| Command | Arguments | Description |
|
||||||
|
|-----------|-----------------------------|-----------------------------------------------------------------------------------------------|
|
||||||
|
| /editSign | \<line> \<text> \<text> ... | Sets the text of the sign line (1-4) to the given input. Then right-click the sign to update. |
|
||||||
|
|
||||||
|
## Permissions
|
||||||
|
|
||||||
|
| Permission | Description |
|
||||||
|
|-----------------------|-----------------------------------------|
|
||||||
|
| placeholdersigns.edit | Allows the use of the /editSign command |
|
90
pom.xml
Normal file
90
pom.xml
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
<?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>PlaceholderSigns</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<name>PlaceholderSigns</name>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<java.version>16</java.version>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<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>placeholderapi</id>
|
||||||
|
<url>https://repo.extendedclip.com/content/repositories/placeholderapi/</url>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.spigotmc</groupId>
|
||||||
|
<artifactId>spigot-api</artifactId>
|
||||||
|
<version>1.19.4-R0.1-SNAPSHOT</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jetbrains</groupId>
|
||||||
|
<artifactId>annotations</artifactId>
|
||||||
|
<version>24.0.1</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>me.clip</groupId>
|
||||||
|
<artifactId>placeholderapi</artifactId>
|
||||||
|
<version>2.10.0</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
@ -0,0 +1,181 @@
|
|||||||
|
package net.knarcraft.placeholdersigns;
|
||||||
|
|
||||||
|
import me.clip.placeholderapi.PlaceholderAPI;
|
||||||
|
import net.knarcraft.placeholdersigns.command.EditSignCommand;
|
||||||
|
import net.knarcraft.placeholdersigns.container.LineChangeRequest;
|
||||||
|
import net.knarcraft.placeholdersigns.container.PlaceholderSign;
|
||||||
|
import net.knarcraft.placeholdersigns.handler.PlaceholderSignHandler;
|
||||||
|
import net.knarcraft.placeholdersigns.listener.SignBreakListener;
|
||||||
|
import net.knarcraft.placeholdersigns.listener.SignClickListener;
|
||||||
|
import net.knarcraft.placeholdersigns.listener.SignTextListener;
|
||||||
|
import net.md_5.bungee.api.ChatColor;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.block.Sign;
|
||||||
|
import org.bukkit.command.PluginCommand;
|
||||||
|
import org.bukkit.configuration.serialization.ConfigurationSerialization;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This plugin's main class
|
||||||
|
*/
|
||||||
|
public final class PlaceholderSigns extends JavaPlugin {
|
||||||
|
|
||||||
|
private static PlaceholderSigns instance;
|
||||||
|
private PlaceholderSignHandler signHandler;
|
||||||
|
private Map<Player, LineChangeRequest> changeRequests;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets an instance of this plugin
|
||||||
|
*
|
||||||
|
* @return <p>A plugin instance</p>
|
||||||
|
*/
|
||||||
|
public static @NotNull PlaceholderSigns getInstance() {
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets this instance's placeholder sign handler
|
||||||
|
*
|
||||||
|
* @return <p>The sign handler</p>
|
||||||
|
*/
|
||||||
|
public @NotNull PlaceholderSignHandler getSignHandler() {
|
||||||
|
return this.signHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a sign change request
|
||||||
|
*
|
||||||
|
* <p>A sign change request is basically the result of running the editSign command, which must be stored until the
|
||||||
|
* player clicks a sign.</p>
|
||||||
|
*
|
||||||
|
* @param request <p>The sign change request to register</p>
|
||||||
|
*/
|
||||||
|
public void addChangeRequest(@NotNull LineChangeRequest request) {
|
||||||
|
changeRequests.put(request.player(), request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a sign change request
|
||||||
|
*
|
||||||
|
* @param player <p>The player to get the request for</p>
|
||||||
|
* @return <p>The sign change request, or null if not found</p>
|
||||||
|
*/
|
||||||
|
public @Nullable LineChangeRequest getChangeRequest(@NotNull Player player) {
|
||||||
|
return changeRequests.remove(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLoad() {
|
||||||
|
super.onLoad();
|
||||||
|
// Register serialization classes
|
||||||
|
ConfigurationSerialization.registerClass(PlaceholderSign.class);
|
||||||
|
ConfigurationSerialization.registerClass(PlaceholderSignHandler.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onEnable() {
|
||||||
|
instance = this;
|
||||||
|
signHandler = new PlaceholderSignHandler();
|
||||||
|
changeRequests = new HashMap<>();
|
||||||
|
signHandler.load();
|
||||||
|
|
||||||
|
if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") == null) {
|
||||||
|
getLogger().log(Level.WARNING, "Could not find PlaceholderAPI! This plugin is required.");
|
||||||
|
Bukkit.getPluginManager().disablePlugin(this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update signs' placeholders every second
|
||||||
|
Bukkit.getScheduler().runTaskTimer(this, this::updateSigns, 20 * 10, 20 * 5);
|
||||||
|
|
||||||
|
Bukkit.getPluginManager().registerEvents(new SignBreakListener(), this);
|
||||||
|
Bukkit.getPluginManager().registerEvents(new SignTextListener(), this);
|
||||||
|
Bukkit.getPluginManager().registerEvents(new SignClickListener(), this);
|
||||||
|
|
||||||
|
PluginCommand editCommand = Bukkit.getPluginCommand("editSign");
|
||||||
|
if (editCommand != null) {
|
||||||
|
editCommand.setExecutor(new EditSignCommand());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDisable() {
|
||||||
|
// Plugin shutdown logic
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates all loaded and registered placeholder signs
|
||||||
|
*/
|
||||||
|
private void updateSigns() {
|
||||||
|
for (PlaceholderSign placeholderSign : signHandler.getSigns()) {
|
||||||
|
// Ignore signs away from players
|
||||||
|
Location location = placeholderSign.location();
|
||||||
|
if (!location.getChunk().isLoaded()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no longer a sign, remove
|
||||||
|
if (!(location.getBlock().getState() instanceof Sign sign)) {
|
||||||
|
signHandler.unregisterSign(placeholderSign);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update placeholders
|
||||||
|
Map<Integer, String> placeholders = placeholderSign.placeholders();
|
||||||
|
String[] lines = sign.getLines();
|
||||||
|
boolean updateRequired = false;
|
||||||
|
for (int i = 0; i < lines.length; i++) {
|
||||||
|
String oldText = sign.getLine(i);
|
||||||
|
|
||||||
|
// The new text of the sign is either the same, or the original placeholder
|
||||||
|
String newText;
|
||||||
|
if (!placeholders.containsKey(i) || placeholders.get(i) == null) {
|
||||||
|
newText = oldText;
|
||||||
|
} else {
|
||||||
|
newText = PlaceholderAPI.setPlaceholders(null, placeholders.get(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert color codes
|
||||||
|
newText = translateAllColorCodes(newText);
|
||||||
|
|
||||||
|
// Only change the line if the text has changed
|
||||||
|
if (!newText.equals(oldText)) {
|
||||||
|
sign.setLine(i, newText);
|
||||||
|
updateRequired = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only update the sign if the text has changed
|
||||||
|
if (updateRequired) {
|
||||||
|
sign.update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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>
|
||||||
|
*/
|
||||||
|
private 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(1)));
|
||||||
|
}
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,72 @@
|
|||||||
|
package net.knarcraft.placeholdersigns.command;
|
||||||
|
|
||||||
|
import net.knarcraft.placeholdersigns.PlaceholderSigns;
|
||||||
|
import net.knarcraft.placeholdersigns.container.LineChangeRequest;
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.command.TabExecutor;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A command for setting a sign's text to anything longer than normally possible
|
||||||
|
*/
|
||||||
|
public class EditSignCommand implements TabExecutor {
|
||||||
|
|
||||||
|
private static final List<String> lineNumbers;
|
||||||
|
|
||||||
|
static {
|
||||||
|
lineNumbers = new ArrayList<>();
|
||||||
|
for (int i = 1; i < 5; i++) {
|
||||||
|
lineNumbers.add(String.valueOf(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCommand(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s,
|
||||||
|
@NotNull String[] args) {
|
||||||
|
if (args.length < 2 || !(commandSender instanceof Player player)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the specified line number
|
||||||
|
int lineNumber;
|
||||||
|
try {
|
||||||
|
lineNumber = Integer.parseInt(args[0]);
|
||||||
|
if (lineNumber < 0 || lineNumber > 4) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} catch (NumberFormatException exception) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get all arguments as a space-separated string
|
||||||
|
StringBuilder builder = new StringBuilder(args[1]);
|
||||||
|
for (int i = 2; i < args.length; i++) {
|
||||||
|
builder.append(" ").append(args[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register the line change request
|
||||||
|
LineChangeRequest request = new LineChangeRequest(player, lineNumber - 1, builder.toString());
|
||||||
|
PlaceholderSigns.getInstance().addChangeRequest(request);
|
||||||
|
|
||||||
|
commandSender.sendMessage("Please click the sign you want to change.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public List<String> onTabComplete(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s,
|
||||||
|
@NotNull String[] args) {
|
||||||
|
if (args.length == 1) {
|
||||||
|
return lineNumbers;
|
||||||
|
} else {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
package net.knarcraft.placeholdersigns.container;
|
||||||
|
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A record of a player's request to change a sign
|
||||||
|
*
|
||||||
|
* @param player <p>The player requesting the sign change</p>
|
||||||
|
* @param line <p>The line the player wants to change</p>
|
||||||
|
* @param text <p>The new text the player provided for the line</p>
|
||||||
|
*/
|
||||||
|
public record LineChangeRequest(Player player, int line, String text) {
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
package net.knarcraft.placeholdersigns.container;
|
||||||
|
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.configuration.serialization.ConfigurationSerializable;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A sign containing one or more placeholders
|
||||||
|
*
|
||||||
|
* @param location <p>The location of the sign</p>
|
||||||
|
* @param placeholders <p>The original placeholders typed on the sign</p>
|
||||||
|
*/
|
||||||
|
public record PlaceholderSign(Location location,
|
||||||
|
Map<Integer, String> placeholders) implements ConfigurationSerializable {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NotNull
|
||||||
|
public Map<String, Object> serialize() {
|
||||||
|
Map<String, Object> data = new HashMap<>();
|
||||||
|
data.put("location", location);
|
||||||
|
data.put("placeholders", placeholders);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deserializes the placeholder-sign specified in the given data
|
||||||
|
*
|
||||||
|
* @param data <p>The data to deserialize</p>
|
||||||
|
* @return <p>The deserialized placeholder sign</p>
|
||||||
|
*/
|
||||||
|
@SuppressWarnings({"unchecked", "unused"})
|
||||||
|
public static PlaceholderSign deserialize(Map<String, Object> data) {
|
||||||
|
return new PlaceholderSign((Location) data.get("location"), (Map<Integer, String>) data.get("placeholders"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,118 @@
|
|||||||
|
package net.knarcraft.placeholdersigns.handler;
|
||||||
|
|
||||||
|
import net.knarcraft.placeholdersigns.PlaceholderSigns;
|
||||||
|
import net.knarcraft.placeholdersigns.container.PlaceholderSign;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
|
import org.bukkit.configuration.serialization.ConfigurationSerializable;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A handler for keeping track of placeholder signs
|
||||||
|
*/
|
||||||
|
public class PlaceholderSignHandler implements ConfigurationSerializable {
|
||||||
|
|
||||||
|
private static final File signsFile = new File(PlaceholderSigns.getInstance().getDataFolder(), "signs.yml");
|
||||||
|
|
||||||
|
private Set<PlaceholderSign> placeholderSigns;
|
||||||
|
private Map<Location, PlaceholderSign> locationLookup;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets all registered signs
|
||||||
|
*
|
||||||
|
* @return <p>All registered signs</p>
|
||||||
|
*/
|
||||||
|
public @NotNull Set<PlaceholderSign> getSigns() {
|
||||||
|
return new HashSet<>(placeholderSigns);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a placeholder sign from the given location
|
||||||
|
*
|
||||||
|
* @param location <p>The location of the sign</p>
|
||||||
|
* @return <p>The sign at the location, or null if no such sign exists</p>
|
||||||
|
*/
|
||||||
|
public PlaceholderSign getFromLocation(@NotNull Location location) {
|
||||||
|
return locationLookup.get(location);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a new placeholder sign
|
||||||
|
*
|
||||||
|
* @param sign <p>The sign to register</p>
|
||||||
|
*/
|
||||||
|
public void registerSign(@NotNull PlaceholderSign sign) {
|
||||||
|
this.placeholderSigns.add(sign);
|
||||||
|
locationLookup.put(sign.location(), sign);
|
||||||
|
save();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Un-registers a placeholder sign
|
||||||
|
*
|
||||||
|
* @param sign <p>The sign to un-register</p>
|
||||||
|
*/
|
||||||
|
public void unregisterSign(@NotNull PlaceholderSign sign) {
|
||||||
|
locationLookup.remove(sign.location());
|
||||||
|
this.placeholderSigns.remove(sign);
|
||||||
|
save();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads all placeholder signs from disk
|
||||||
|
*/
|
||||||
|
public void load() {
|
||||||
|
YamlConfiguration configuration = YamlConfiguration.loadConfiguration(signsFile);
|
||||||
|
PlaceholderSignHandler loadedHandler = (PlaceholderSignHandler) configuration.get("signHandler");
|
||||||
|
this.placeholderSigns = loadedHandler != null ? loadedHandler.placeholderSigns : new HashSet<>();
|
||||||
|
this.locationLookup = loadedHandler != null ? loadedHandler.locationLookup : new HashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves all current placeholder signs
|
||||||
|
*/
|
||||||
|
public void save() {
|
||||||
|
try {
|
||||||
|
YamlConfiguration configuration = new YamlConfiguration();
|
||||||
|
configuration.set("signHandler", this);
|
||||||
|
configuration.save(signsFile);
|
||||||
|
} catch (IOException exception) {
|
||||||
|
PlaceholderSigns.getInstance().getLogger().log(Level.SEVERE, "Unable to save placeholder signs!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Map<String, Object> serialize() {
|
||||||
|
Map<String, Object> data = new HashMap<>();
|
||||||
|
data.put("signs", this.placeholderSigns);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deserializes the given placeholder sign handler data
|
||||||
|
*
|
||||||
|
* @param data <p>The data to deserialize</p>
|
||||||
|
* @return <p>The deserialized sign handler</p>
|
||||||
|
*/
|
||||||
|
@SuppressWarnings({"unchecked", "unused"})
|
||||||
|
public static PlaceholderSignHandler deserialize(@NotNull Map<String, Object> data) {
|
||||||
|
PlaceholderSignHandler placeholderSignHandler = new PlaceholderSignHandler();
|
||||||
|
placeholderSignHandler.placeholderSigns = (Set<PlaceholderSign>) data.get("signs");
|
||||||
|
Map<Location, PlaceholderSign> lookup = new HashMap<>();
|
||||||
|
for (PlaceholderSign sign : placeholderSignHandler.placeholderSigns) {
|
||||||
|
lookup.put(sign.location(), sign);
|
||||||
|
}
|
||||||
|
placeholderSignHandler.locationLookup = lookup;
|
||||||
|
return placeholderSignHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
package net.knarcraft.placeholdersigns.listener;
|
||||||
|
|
||||||
|
import net.knarcraft.placeholdersigns.PlaceholderSigns;
|
||||||
|
import net.knarcraft.placeholdersigns.container.PlaceholderSign;
|
||||||
|
import net.knarcraft.placeholdersigns.handler.PlaceholderSignHandler;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A listener for placeholder signs being broken
|
||||||
|
*/
|
||||||
|
public class SignBreakListener implements Listener {
|
||||||
|
|
||||||
|
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
|
||||||
|
public void onSignBreak(BlockBreakEvent event) {
|
||||||
|
Block block = event.getBlock();
|
||||||
|
|
||||||
|
if (!(block.getState() instanceof Sign)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
PlaceholderSignHandler signHandler = PlaceholderSigns.getInstance().getSignHandler();
|
||||||
|
PlaceholderSign sign = signHandler.getFromLocation(block.getLocation());
|
||||||
|
if (sign != null) {
|
||||||
|
signHandler.unregisterSign(sign);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
package net.knarcraft.placeholdersigns.listener;
|
||||||
|
|
||||||
|
import net.knarcraft.placeholdersigns.PlaceholderSigns;
|
||||||
|
import net.knarcraft.placeholdersigns.container.LineChangeRequest;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
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.SignChangeEvent;
|
||||||
|
import org.bukkit.event.player.PlayerInteractEvent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A listener for placeholder signs being clicked
|
||||||
|
*/
|
||||||
|
public class SignClickListener implements Listener {
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.MONITOR)
|
||||||
|
public void onSignClick(PlayerInteractEvent event) {
|
||||||
|
// Ignore if not a clicked sign
|
||||||
|
if (!event.hasBlock() || event.getClickedBlock() == null ||
|
||||||
|
!(event.getClickedBlock().getState() instanceof Sign sign)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Check if the player has run the /editSign command
|
||||||
|
LineChangeRequest request = PlaceholderSigns.getInstance().getChangeRequest(event.getPlayer());
|
||||||
|
if (request == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String[] lines = sign.getLines();
|
||||||
|
lines[request.line()] = request.text();
|
||||||
|
|
||||||
|
// Run the sign change event to allow protection plugins to cancel, and allow the sign text listener to trigger
|
||||||
|
SignChangeEvent changeEvent = new SignChangeEvent(event.getClickedBlock(), event.getPlayer(), lines);
|
||||||
|
Bukkit.getPluginManager().callEvent(changeEvent);
|
||||||
|
if (changeEvent.isCancelled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the sign with the new text
|
||||||
|
String[] finalLines = changeEvent.getLines();
|
||||||
|
for (int i = 0; i < finalLines.length; i++) {
|
||||||
|
sign.setLine(i, finalLines[i]);
|
||||||
|
}
|
||||||
|
sign.update();
|
||||||
|
|
||||||
|
event.getPlayer().sendMessage("The sign line was successfully changed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
package net.knarcraft.placeholdersigns.listener;
|
||||||
|
|
||||||
|
import me.clip.placeholderapi.PlaceholderAPI;
|
||||||
|
import net.knarcraft.placeholdersigns.PlaceholderSigns;
|
||||||
|
import net.knarcraft.placeholdersigns.container.PlaceholderSign;
|
||||||
|
import net.knarcraft.placeholdersigns.handler.PlaceholderSignHandler;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.EventPriority;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.block.SignChangeEvent;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A listener for signs being changed to contain on or more placeholders
|
||||||
|
*/
|
||||||
|
public class SignTextListener implements Listener {
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||||
|
public void onSignCreate(SignChangeEvent event) {
|
||||||
|
String[] lines = event.getLines();
|
||||||
|
Map<Integer, String> placeholders = new HashMap<>();
|
||||||
|
|
||||||
|
// Register any lines PlaceholderAPI wants to change
|
||||||
|
for (int i = 0; i < lines.length; i++) {
|
||||||
|
String line = lines[i];
|
||||||
|
String replaced = PlaceholderAPI.setPlaceholders(null, line);
|
||||||
|
if (line.equalsIgnoreCase(replaced)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
placeholders.put(i, line);
|
||||||
|
}
|
||||||
|
|
||||||
|
Location location = event.getBlock().getLocation();
|
||||||
|
PlaceholderSignHandler signHandler = PlaceholderSigns.getInstance().getSignHandler();
|
||||||
|
PlaceholderSign existingSign = signHandler.getFromLocation(location);
|
||||||
|
|
||||||
|
// Register the placeholder sign
|
||||||
|
if (!placeholders.isEmpty() && existingSign == null) {
|
||||||
|
PlaceholderSign placeholderSign = new PlaceholderSign(event.getBlock().getLocation(), placeholders);
|
||||||
|
signHandler.registerSign(placeholderSign);
|
||||||
|
} else if (!placeholders.isEmpty()) {
|
||||||
|
// Overwrite the placeholders of the existing placeholder sign
|
||||||
|
for (Map.Entry<Integer, String> entry : placeholders.entrySet()) {
|
||||||
|
existingSign.placeholders().put(entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
signHandler.save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
0
src/main/resources/config.yml
Normal file
0
src/main/resources/config.yml
Normal file
17
src/main/resources/plugin.yml
Normal file
17
src/main/resources/plugin.yml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
name: PlaceholderSigns
|
||||||
|
version: '${project.version}'
|
||||||
|
main: net.knarcraft.placeholdersigns.PlaceholderSigns
|
||||||
|
api-version: 1.19
|
||||||
|
depend:
|
||||||
|
- PlaceholderAPI
|
||||||
|
|
||||||
|
commands:
|
||||||
|
editSign:
|
||||||
|
usage: /<command> <line> <text> [text] ...
|
||||||
|
permission: placeholdersigns.edit
|
||||||
|
description: Changes the line of a sign without a text limit
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
placeholdersigns.edit:
|
||||||
|
description: Allows a player to use the /editSign command
|
||||||
|
default: op
|
Loading…
Reference in New Issue
Block a user