From BergerHealer Wiki
Jump to navigation Jump to search
This page contains changes which are not marked for translation.

« Go back

This TrainCarts API allows custom signs to be registered, so that the registered executor callback is automatically run when trains go past them. This makes it very easy to make trains perform unique actions using a third-party plugin.

Example Template

To begin, create a new class in your plugin with the following code:

import org.bukkit.entity.Player;


 * Displays a welcome message to the players in the train
public class SignActionWelcome extends SignAction {

    public boolean match(SignActionEvent info) {
        // Checks that the second line starts with 'welcome' (case-insensitive)
        return info.isType("welcome");

    public void execute(SignActionEvent info) {
        // When a [train] sign is placed, activate when powered by redstone when the train
        // goes over the sign, or when redstone is activated.
        if (info.isTrainSign()
                && info.isAction(SignActionType.GROUP_ENTER, SignActionType.REDSTONE_ON)
                && info.isPowered() && info.hasGroup()
        ) {
            for (MinecartMember<?> member : info.getGroup()) {
                sendGreetingForCart(info, member);

        // When a [cart] sign is placed, activate when powered by redstone when each cart
        // goes over the sign, or when redstone is activated.
        if (info.isCartSign()
                && info.isAction(SignActionType.MEMBER_ENTER, SignActionType.REDSTONE_ON)
                && info.isPowered() && info.hasMember()
        ) {
            sendGreetingForCart(info, info.getMember());

    public void sendGreetingForCart(SignActionEvent info, MinecartMember<?> member) {
        // Lines 3 and 4 configure the message to send
        String message = info.getLine(2) + info.getLine(3);

        // Send to all player passengers of the cart (could be multiple seats!)
        for (Player passenger : member.getEntity().getPlayerPassengers()) {

    public boolean build(SignChangeActionEvent event) {
        // This is executed when a player places down a sign matching this sign action
        // Permissions are checked and then a message is displayed to the player
        // For simplicity you can use the SignBuildOptions API for this.
        // You are free to use your own code here that checks permissions/etc.
        return SignBuildOptions.create()
                .setName(event.isCartSign() ? "cart welcome greeter" : "train welcome greeter")
                .setDescription("sends a welcome message to all players in the train")

This is a simple example of a sign that sends a message to all players in the train. By default signs will support the standard TrainCarts conventions for the first line, where redstone options can be configured. The second line is typically used to match the sign type, and the last two lines are free to be used for anything.

To register the above class, perform the following in your plugin's main class:



public class TCWelcomeSign extends JavaPlugin {
    public final SignActionWelcome signActionWelcome = new SignActionWelcome();

    public void onEnable() {
        // Register the signs

    public void onDisable() {
        // Unregister the signs to prevent problems during /reload

It is important to both register and unregister the sign. That way, when the server is reloaded, or the plugin or reloaded using for example PlugMan, things don't break.

The Execute Method

Various events are sent to signs and can be handled by the sign. All events are handled through the execute(event) callback.

Cart/Train Enter and Leave

When each individual cart hits a piece of track with a sign matching the sign action, the MEMBER_ENTER event is fired. When they move off the track again, a MEMBER_LEAVE event is fired. Similarly, for entire trains, a GROUP_ENTER and GROUP_LEAVE is fired.


When the sign becomes powered from an unpowered state, REDSTONE_ON and REDSTONE_CHANGE fire. In reverse, REDSTONE_OFF and REDSTONE_CHANGE fire. When the power state doesn't change, but other blocks nearby change redstone levels that might influence the sign behavior, just REDSTONE_CHANGE is fired. The event has helper methods to figure out the power state of the sign or a given direction of the sign.


Every tick, while the train is moving, a MEMBER_MOVE event is fired. By default through, this is disabled for performance reasons. To use this event, override isMemberMoveHandled(event) and return true there.


When players enter the train, leave it, properties change or other similar events occur, a MEMBER_UPDATE event fires. This is useful if the sign uses such information to, for example, toggle a lever.

Loaded Changed Event

The loadedChanged(event, loaded) method can be overrided to get notified when a sign matching this sign action is loaded or unloaded on the server. A sign is loaded when placed, or when a chunk loads with the sign in it. A sign is unloaded when destroyed, or when a chunk unloads with the sign in it. Be careful not to load or unload chunks in this method. This is a useful method to cache data in memory while the sign is in use.

Remote Control

Remote control enables the sign to be activated by redstone, to then operate on one or more trains by name pattern. To use remote control with the sign, override canSupportRC() and return true.

Path Finding

Some advanced methods can be overrided to make the sign act as a node in the path-finding network:

  • isRailSwitcher(event) - Return true if this sign switches the rails from/to any direction
  • getRailDestinationName(event) - Return non-null to provide a unique destination name
  • isPathFindingBlocked(event, railState) - Return true to tell the path finding algorithm that in this direction no further movement is possible