Individual Signs
Description
This plugin displays the text on signs for each player individual differently.
By default this plugin only replaces [PLAYER] on signs with the name and [DISPLAY] with the nick name of the player looking at it.
The permission nodes to create signs containing those tags are insigns.create.player and insigns.create.display.
However InSigns also includes an API for developers of other plugins to easily add own player-specific sign content.
This plugin could for example be used for individual greeting signs at your spawn. Your players will be amazed to see their own name on a sign!
IMPORTANT
This plugin needs ProtocolLib to work.
Make sure you have installed the right version of ProtocolLib.
This plugin should stay compatible with further versions of minecraft and bukkit as long as ProtocolLib doesn't have to change anything on it's API which InSigns is relying on, and the minecraft protocol isn't changing anything sign-related.
Quick Presentation by VariationVault
For plugin developers: easy-to-use API
Here is a small example of how you can use this in your own plugin to display player-specific values on signs.
1.) First of all: add the IndividualSigns jar to your build path (just like you do it with the bukkit.jar)
2.) You can then create a listener which listens for the SignSendEvent (just like you create listeners for bukkit events): This event gets called every time the server is about to update the sign contents for a player.
3.) The event provides easy methods to get the current sign text and to change it:
- getPlayer() - Gets the player which receives the sign packet.
- getLocation() - Gets the location of the sign which text is being sent.
- getLine(int index) - Gets the line of text at the specified index (0-3). The lines are in json format.
- setLine(int index, String line) - Sets the line of text at the specified index. Has to be in proper json format.
- isModified() - Whether or not this event was modified by some plugin.
- setCancelled(boolean cancelled) - If the event is cancelled the sign contents won't get updated for the affected player, leaving it at their current content (blank if all SignSendEvents get cancelled).
- isCancelled() - Checks whether or not some plugin cancelled this event already.
Example usage of the event to replace "[PLAYER]" with the player's name:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
public class SignSendListener implements Listener { public SignSendListener(Plugin plugin) { Bukkit.getServer().getPluginManager().registerEvents(this, plugin); } @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) public void onSignSend(SignSendEvent event) { for (int i = 0; i < 4; i++) { String line = event.getLine(i); if (line.contains("[PLAYER]")) { event.setLine(i, line.replace("[PLAYER]", event.getPlayer().getName())); } } } } |
That's it. The InSigns-Plugin will handle all the needed packet manipulation for you.
Some other useful utilities provided by InSigns are:
- The SimpleChanger class which can be used to easily create a listener for simple key->value replacements and permission checks during sign creation. Example for the built-in [PLAYER] -> playerName replacement:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
@Override public void onEnable() { Plugin insignsPlugin = getServer().getPluginManager().getPlugin("InSigns"); if ((insignsPlugin != null) && insignsPlugin.isEnabled()) { // Replaces "[PLAYER]" with the player's name on signs and checks for the 'insigns.create.player' permission whenever a player tries to create a sign with "[PLAYER]" on it new SimpleChanger(this, "[PLAYER]", "insigns.create.player") { @Override public String getValue(Player player, Location location) { return player.getName(); } }; getLogger().info("Plugin 'InSigns' found. Using it now."); } else { getLogger().info("Plugin 'InSigns' not found. Additional sign features disabled."); } } |
Plugins using InSigns
- Paintball War Edition - Offering individual paintball statistics signs.
- ScoreboardStats - Offering some individual general statistics signs.
Let me know if your plugin uses InSigns and you want to be mentioned here.
Statistics
This plugin uses bStats to collect anonymous usage statistics to determine the how many servers are using the plugin and with which minecraft versions it is used with the most. All collected information can be publicly viewed here: https://bstats.org/plugin/bukkit/InSigns
You can disable bStats for all plugins on your server by editing the file plugins/bStats/config.yml, or alternatively disable it only for IndividualSigns by setting 'metrics-stats' to 'false' inside InSigns' config.
Donations
If you like this plugin, consider supporting its development by making a donation.
Thanks in advance!
Hi! So, I have 1 problem:
I am currently creating a bank system and it's getting managed by signs. So, on the signs is the current money the player has in his bank and I want it to keep auto-updating because you are getting pay tax.
I tried to loop all loaded chunks and look out for sings and send an update, but it doesn't changes anything
Greets, Smootey
As of this moment, V2.0 does not work on Spigot 1.8 and
Protocollib for 1.8 has been released at this website
@LethalWrath
I hope and assume that ProtocolLib will keep functioning and maybe even getting maintained for the near future.
After that I will of course have to look for alternative ways of hooking into minecraft's packet sending.
ProtocolLib has now become INACTIVE on its plugin page, I was wondering what will happen will happen to this plugin?
@blablubbabc
Ok, I moved the signs out of the way (to the paintball lobby), which will make it less likely for players to log in there. I guess I'll manage... :-)
@pgmann
That is because paintball loads your player statistics in the background after you finished joining the server (for performance reasons).
And IndividualSigns only intercepts sign packets (which get sent immediately when you join the server). It doesn't keep track of it's affected signs, nor does it automatically update those signs (for performance reaons as well).
So your player statistics are not yet loaded when the server sends you the sign text, therefore it prints the '-not found-' thing instead.
I don't think that is that big of a problem though.
@blablubbabc
I found a bug when using this plugin to display scores from your paintball plugin. If I log in looking at the signs they will display '-not foun' in red until I right click them or go away to another location.
How can i use this plugin for my paintball plugin, what do i need to write in the signs (PLEASE HELP !!!)
Well, thanks a lot for that API, I was just about to write own method to show individual signs, and I found that plugin, you saved a lot of my time =)
@xXBadeye
The error with the + is very likly an issue of your String.matches() method which checks for regexes and the + has a special meaning for regexes.. So you will have to escape that character.
@blablubbabc
Well, i hate spaming your comments but i got strange stack traces now. I have now (finaly) got it working, problem was that the plugin loaded BEFORE protocolLib and InSigns and taht i forgot the onEnable part :D Well, one more, strange packet error. The class is still the same as in the commend underneath.
Stack Trace aaa is being printed out (see class in my last comment), so the getValue is called. Something seems to be wrong with the "+" on the sign, but it should be okay since it is just a string, right?
Edit: Didn't refreshed the page, your comment came to late, but you figured the problems i had :)
Edit 2: Well, it worked with removing the "+" from the string check... this is realy weird. So the text got replaced with the correct value, but there are no chat colors yet :D &4 did not work, have you implemented something like that?
Edit 3: Tryed return (ChatColor.GREEN + "My text"); and it worked :> only problem are the god damm "+" :D
@xXBadeye
Well, you have to call this class inside your onEnable() and you have to softdepend InSigns in your plugin.yml.
Between, if you have some sort of list of all your possible weapons you could replace your repeating code lines with a loop.
@blablubbabc
Wrote my code, it should work but even my debug statements are not being called. Do i have to register the event in my onEnable main class?
Sign class, i have not modified anything in other classes after using this:
i know awful if statement chain, but sadly it is needed :/ Working with those permissions when executing commands and giving players kits.
Pastebin code, the statements are that long that they are messing up the formating :D
@blablubbabc
Hah okay thank you, i assumed that aswell but i had no idea how the changer works :) Nice api, then, perfectly suits my needs!
@xXBadeye
That's exactly what the Changer is for: you simple have to replace the "[PLAYER]" from the example to your own key (which gets replaced), and change the permissions node from 'insigns.create.player' to your own as well, and inside the getValue() method you insert your own logic and return the string which shall be displayed to the player.
@blablubbabc Thanks alot :>
Ah, one last question: Let's say i want to modify [PLAYER] to a custom variable, lets say to the String "hi". How would i do that? That way i could for example use my self written sign shop component of my plugin, get a value from the config/hashmap if the player has bought the item and depending on if the palyer has bought the item or not the [PLAYER] (or something else) on the sign gets changed to "Already bought" or "Buy this"
@xXBadeye
Ah, I now know why it suggest that import: actually I already included a first draft of a possible SignSendEvent class in that version, but it wasn't yet used (that's why I moved it into the 'unused' package..)
I updated the example in the comment below: You basicly have to get the InSigns plugin instance just like in the example with the 'SimpleChanger' above, but instead of creating a new 'SimpleChanger' you cast the plugin to 'InSigns' and use the 'addChanger' method to add a new 'Changer' object and fill in the getValue() method for that Changer object.
InSigns will then check the permission you provide it whenever a player tries to create a sign with the key on it (the key is the first string argument, the one which gets replaced with what your custom getValue() method returns).
Edit: Here is the old project page, which has the example for the old API: http://dev.bukkit.org/bukkit-plugins/individual-signs/pages/main/r65/
@blablubbabc
Hah okay, that is strange o.o Eclipse know what i want, so it gets created. Well, interesting. But thanks for the extremly fast response!
So there is no way to modify packages with the "api" in 1.4, or is the insigns.addChanger(new Changer("[PLAYER]", "player"){ ... } part changing [PLAYER] to the player value?
Edit: Importing worked, but you made a mistake, all your imports start with "me." they have to start with "de.". I wasn't able to find any of the methods til i changed it :)
@xXBadeye
The SignSendEvent was added in InSigns version 2.0, so the examples above don't help you much, if you are using version 1.4.
In version 1.4 you only had the possibility to register 'Changer's, which basicly handle basic key-value replacements and permission checks during sign creation (similar to the 'SimpleChanger' example above).
This is the example on that old api (Edit: now updated example below for v1.4):
Edit: I don't know where your import 'unused.SignSendEvent' is coming from. I assume your IDE has created an own SignSendEvent class for you, because it can't find that class in the InSigns version you are using (because it didn't yet exist in that version).. That's also the reason why it doesn't find those methods there..
Uhm... Having problem with this. I tried to use the api (Individual Signs version 1.4 and craftbukkit 1.6.4). I have succesfully imported permissions ex and listened for their events, so that is no problem.
I made a new class and everything (i know how that works, no worries :P) and i have imported your event. however, the import: import unused.SignSendEvent; the .getLine method can't be found, i have just copied your example from above.
Edit 1: Okay the event found .getLines(), which is a string List. Well, i guess i have to use that now :P
Edit 2: Aw crap. Okay, there is no setLine method :/ can i just use getLines and modify the String[]? I do not think that is going to do it, or is it?