I made this class to show how easy it is to create one of those fancy dynamic sign-walls that servers like Hypixel, Armadacraft and MineCade (last 2 are basically the same) are having. I added comments to explain what I'm doing in every method. The only thing you have to do is create a GameInstance class that represents an instance of your minigame. Feel free to modify or give me some constructive criticism! Code:java import org.bukkit.block.Sign;import org.bukkit.event.EventHandler;import org.bukkit.event.Listener;import org.bukkit.event.block.Action;import org.bukkit.event.player.PlayerInteractEvent;import org.bukkit.plugin.java.JavaPlugin;import org.bukkit.scheduler.BukkitRunnable; import java.util.ArrayList;import java.util.HashMap;import java.util.LinkedList;import java.util.Queue; /** * User: Ivan * Date: 24/08/13 * Time: 0:05 * IDE: IntelliJ IDEA * Look me up on bukkit forums! * [url]http://forums.bukkit.org/members/ivan.5352/[/url] */public class SignWall extends BukkitRunnable implements Listener { HashMap<Sign,GameInstance> signpool = new HashMap(); Queue<GameInstance> gamequeue = new LinkedList<GameInstance>(); JavaPlugin plugin; /* The constructor fills our signpool up with sig schedules a new bukkit task and registers the associated listener for us. */ public SignWall(Sign[] signs,JavaPlugin plugin){ for(Sign sign:signs) signpool.put(sign,null); this.plugin = plugin; this.runTaskTimer(plugin, 0, 20L); plugin.getServer().getPluginManager().registerEvents(this, plugin); } /* Gets an empty sign out of our signpool */ public Sign getEmptySign(){ for(Sign sign:signpool.keySet()){ if(signpool.get(sign) == null) return sign; } return null; } /* This will be used by the listener that will check if there is a game associated with the clicked sign. */ public GameInstance getBySign(Sign sign){ return signpool.get(sign); } /* This method will be called by your gameinstance or by some kind of handler that decides when a game should show up here on the signwall */ public void addToQueue(GameInstance instance){ gamequeue.offer(instance); } /* This is the method called by our loop that will decide what pops up when the sign is empty. */ private void formatEmptySign(Sign sign){ sign.setLine(0,"------------"); sign.setLine(1," Waiting "); sign.setLine(3,"------------"); } /* This is our loop. Here is where the magic happens :). */ @Override public void run() { /* This part removes full games from the signwall, since they don't need players anymore*/ for(Sign sign:signpool.keySet()){ GameInstance instance = signpool.get(sign); /* If it no longer needs players, remove it from the board*/ if(!instance.needsPlayers()){ signpool.put(sign,null); formatEmptySign(sign); sign.update(); } } /* This part checks if more games have to be added to the list */ while(!gamequeue.isEmpty()){ Sign emptysign = getEmptySign(); /* If no signs are availible, break out of the loop */ if(emptysign == null) break; GameInstance instance = gamequeue.poll(); instance.formatSign(emptysign); emptysign.update(); signpool.put(emptysign, instance); } } /* This is the listener part of our controller. It checks if a game is associated with the clicked sign. */ @EventHandler public void onJoinAttempt(PlayerInteractEvent event){ if(event.getPlayer().getWorld().getName().equalsIgnoreCase("lobby") && event.getAction() == Action.RIGHT_CLICK_BLOCK && event.getClickedBlock().getState() instanceof Sign){ GameInstance instance = getBySign((Sign) event.getClickedBlock().getState()); /* If there is a game associated, tell the gameinstance that someone is trying to join. It will return us a string with the message that the player will receive. If there is still a spot left for him, the instance can teleport him using the joinAttempt() method. */ if(instance != null) event.getPlayer().sendMessage(instance.joinAttempt(event.getPlayer())); } }}
If I remember right it's more efficient to check the type of the block than get its state and check if it's a sign. Not positive, though.