Package com.bergerkiller.bukkit.tc

Source Code of com.bergerkiller.bukkit.tc.TrainCarts

package com.bergerkiller.bukkit.tc;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;

import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.block.BlockEvent;
import org.bukkit.plugin.Plugin;

import com.bergerkiller.bukkit.common.inventory.ItemParser;
import com.bergerkiller.bukkit.common.Common;
import com.bergerkiller.bukkit.common.PluginBase;
import com.bergerkiller.bukkit.common.StringReplaceBundle;
import com.bergerkiller.bukkit.common.Task;
import com.bergerkiller.bukkit.common.config.ConfigurationNode;
import com.bergerkiller.bukkit.common.config.FileConfiguration;
import com.bergerkiller.bukkit.common.conversion.Conversion;
import com.bergerkiller.bukkit.sl.API.Variables;
import com.bergerkiller.bukkit.tc.commands.Commands;
import com.bergerkiller.bukkit.tc.controller.MemberConverter;
import com.bergerkiller.bukkit.tc.controller.MinecartGroup;
import com.bergerkiller.bukkit.tc.controller.MinecartGroupStore;
import com.bergerkiller.bukkit.tc.controller.MinecartMember;
import com.bergerkiller.bukkit.tc.controller.MinecartMemberStore;
import com.bergerkiller.bukkit.tc.detector.DetectorRegion;
import com.bergerkiller.bukkit.tc.itemanimation.ItemAnimation;
import com.bergerkiller.bukkit.tc.pathfinding.PathNode;
import com.bergerkiller.bukkit.tc.pathfinding.PathProvider;
import com.bergerkiller.bukkit.tc.properties.CartPropertiesStore;
import com.bergerkiller.bukkit.tc.properties.TrainProperties;
import com.bergerkiller.bukkit.tc.signactions.SignAction;
import com.bergerkiller.bukkit.tc.signactions.SignActionDetector;
import com.bergerkiller.bukkit.tc.signactions.SignActionSpawn;
import com.bergerkiller.bukkit.tc.statements.Statement;
import com.bergerkiller.bukkit.tc.storage.OfflineGroupManager;
import com.bergerkiller.bukkit.common.protocol.PacketType;
import com.bergerkiller.bukkit.common.utils.CommonUtil;
import com.bergerkiller.bukkit.common.utils.LogicUtil;
import com.bergerkiller.bukkit.common.utils.MaterialUtil;
import com.bergerkiller.bukkit.common.utils.MathUtil;
import com.bergerkiller.bukkit.common.utils.ParseUtil;
import com.bergerkiller.bukkit.common.utils.StringUtil;
import com.bergerkiller.bukkit.common.utils.WorldUtil;

public class TrainCarts extends PluginBase {
  /*
   * Settings
   */ 
  public static double maxVelocity;
  public static double maxEjectDistance;
  public static double cartDistance;
  public static double turnedCartDistance;
  public static double cartDistanceForcer;
  public static double turnedCartDistanceForcer;
  public static double nearCartDistanceFactor;
  public static double maxCartDistance;
  public static boolean breakCombinedCarts;
  public static double poweredCartBoost;
  public static double poweredRailBoost;
  public static double pushAwayForce;
  public static double launchForce;
  public static boolean collisionIgnoreGlobalOwners;
  public static boolean collisionIgnoreOwners;
  public static boolean useCoalFromStorageCart;
  public static boolean setOwnerOnPlacement;
  public static boolean keepChunksLoadedOnlyWhenMoving;
  public static boolean playSoundAtStation;
  private Set<Material> allowedBlockBreakTypes = new HashSet<Material>();
  private Set<String> disabledWorlds = new HashSet<String>();
  public static int maxDetectorLength;
  public static int maxMinecartStackSize;
  public static int defaultTransferRadius;
  public static int maxTransferRadius;
  public static boolean showTransferAnimations;
  public static boolean slowDownEmptyCarts;
  public static double slowDownMultiplierSlow;
  public static double slowDownMultiplierNormal;
  public static boolean refillAtStations;
  public static boolean instantCreativeDestroy;
  public static boolean allowRailEditing;
  private static String currencyFormat;
  public static double manualMovementSpeed;
  public static boolean allMinecartsAreTrainCarts;
  public static boolean useNetworkSynchronizer;
  public static boolean allowVerticalPitch;
  public static int collisionReEnterDelay = 100; // Delay before letting mobs/player enter again
  public static final StringReplaceBundle messageShortcuts = new StringReplaceBundle();
  public static final StringReplaceBundle statementShortcuts = new StringReplaceBundle();
  private static Task fixGroupTickTask;

  public static boolean EssentialsEnabled = false;
  public static boolean SignLinkEnabled = false;
  public static boolean MinecartManiaEnabled = false;
  public static boolean MyWorldsEnabled = false;

  public static TrainCarts plugin;
  private Task signtask;
  private TCPacketListener packetListener;
  private FileConfiguration config;
  private Map<String, ItemParser[]> parsers = new HashMap<String, ItemParser[]>();

  /**
   * Writes the latest changes in message shortcuts to file
   */
  public void saveShortcuts() {
    messageShortcuts.save(config.getNode("messageShortcuts"));
    config.save();
  }

  /**
   * Obtains all Item parsers associated with a certain key and amount.
   * If none was found in the TrainCarts item mapping, it is parsed.
   *
   * @param key to get
   * @param amount to multiply the result with. Use 1 to ignore.
   * @return An array of associated item parsers
   */
  public ItemParser[] getParsers(String key, int amount) {
    ItemParser[] rval = parsers.get(key.toLowerCase(Locale.ENGLISH));
    if (rval == null) {
      return new ItemParser[] {ItemParser.parse(key, amount == -1 ? null : Integer.toString(amount))};
    }
    // Clone to avoid altering the values in the map
    rval = LogicUtil.cloneArray(rval);
    if (amount == -1) {
      // Set to any amount
      for (int i = 0; i < rval.length; i++) {
        rval[i] = rval[i].setAmount(-1);
      }
    } else if (amount > 1) {
      // Multiply by amount (ignore 1)
      for (int i = 0; i < rval.length; i++) {
        rval[i] = rval[i].multiplyAmount(amount);
      }
    }
    return rval;
  }

  public void putParsers(String key, ItemParser[] parsers) {
    if (LogicUtil.nullOrEmpty(parsers)) {
      this.parsers.remove(key.toLowerCase(Locale.ENGLISH));
    } else {
      this.parsers.put(key.toLowerCase(Locale.ENGLISH), parsers);
    }
  }

  public static boolean canBreak(Material type) {
    return plugin.allowedBlockBreakTypes.contains(type);
  }

  public void loadConfig() {
    config = new FileConfiguration(this);
    config.load();
    config.setHeader("This is the configuration file of TrainCarts");
    config.addHeader("In here you can tweak TrainCarts to what you want");
    config.addHeader("For more information, you can visit the following websites:");
    config.addHeader("http://www.minecraftwiki.net/wiki/Bukkit/TrainCarts");
    config.addHeader("http://forums.bukkit.org/threads/traincarts.29491/");

    config.setHeader("normal", "\nSettings for normally-aligned (straight) carts");
    config.setHeader("normal.cartDistance", "The distance between two carts in a train");
    config.setHeader("normal.cartDistanceForcer", "The factor at which this distance is kept")
    cartDistance = config.get("normal.cartDistance", 1.5);
    cartDistanceForcer = config.get("normal.cartDistanceForcer", 0.1)
    config.setHeader("normal", "\nThe distance between two normally-aligned (straight) carts in a train");

    config.setHeader("turned", "\nSettings for turned (in curve) carts");
    config.setHeader("turned.cartDistance", "The distance between two carts in a train");
    config.setHeader("turned.cartDistanceForcer", "The factor at which this distance is kept");
    turnedCartDistance = config.get("turned.cartDistance", 1.6);
    turnedCartDistanceForcer = config.get("turned.cartDistanceForcer", 0.2)

    config.setHeader("nearCartDistanceFactor", "\nThe 'keep distance' factor to apply when carts are too close to each other");
    nearCartDistanceFactor = config.get("nearCartDistanceFactor", 1.2)

    config.setHeader("maxCartDistance", "\nThe maximum allowed cart distance, after this distance the carts break apart");
    maxCartDistance = config.get("maxCartDistance", 4.0);

    config.setHeader("breakCombinedCarts", "\nWhether or not the combined carts (powered/storage minecarts) break up into two items");
    breakCombinedCarts = config.get("breakCombinedCarts", false);

    config.setHeader("poweredCartBoost", "\nA performance boost to give to powered minecarts (0 = normal speed)");
    poweredCartBoost = config.get("poweredCartBoost", 0.1);

    config.setHeader("poweredRailBoost", "\nThe boosting factor of powered rails (default = 0.06)");
    poweredRailBoost = config.get("poweredRailBoost", 0.06);

    config.setHeader("maxVelocity", "\nThe maximum velocity (blocks/tick) a minecart can possibly have set");
    maxVelocity = config.get("maxVelocity", 5.0);

    config.setHeader("slowDownMultiplier", "\nThe multiplier used to slow down minecarts");
    config.addHeader("slowDownMultiplier", "Normal is the default, slow is when the minecart is meant to slow down.");
    slowDownMultiplierNormal = config.get("slowDownMultiplier.normal", 0.997);
    slowDownMultiplierSlow = config.get("slowDownMultiplier.slow", 0.96);
   
    config.setHeader("maxEjectDistance", "\nThe maximum allowed ejection distance for eject signs");
    maxEjectDistance = config.get("maxEjectDistance", 10.0);

    config.setHeader("launchForce", "\nThe amount of velocity stations give when launching trains");
    launchForce = config.get("launchForce", 10.0);

    // Deprecation backwards compatibility
    if (config.contains("pushAway")) {
      config.set("collision.ignoreOwners", config.get("pushAway.ignoreOwners", true));
      config.set("collision.ignoreGlobalOwners", config.get("pushAway.ignoreGlobalOwners", false));
      config.set("collision.pushAwayForce", config.get("pushAway.force", 0.2));
      config.remove("pushAway");
    }

    config.setHeader("pushAway", "\nSettings used when carts push away/aside others (if enabled)");
    config.setHeader("pushAway.ignoreOwners", "If train owners are ignored");
    config.setHeader("pushAway.ignoreGlobalOwners", "If global train owners are ignored");

    config.setHeader("collision", "\nSettings used when carts collide with entities");
    config.setHeader("collision.ignoreOwners", "If train owners are ignored");
    config.setHeader("collision.ignoreGlobalOwners", "If global train owners are ignored");
    config.setHeader("collision.pushAwayForce", "The amount of force at which minecarts push away others");
    collisionIgnoreOwners = config.get("collision.ignoreOwners", false);
    collisionIgnoreGlobalOwners = config.get("collision.ignoreGlobalOwners", false);
    pushAwayForce = config.get("collision.pushAwayForce", 0.2);

    config.setHeader("allMinecartsAreTrainCarts", "\nWhether or not all minecarts spawned on the server turn into TrainCarts' Minecarts");
    config.addHeader("allMinecartsAreTrainCarts", "Note that the TrainCart placement permission is then no longer active");
    allMinecartsAreTrainCarts = config.get("allMinecartsAreTrainCarts", false);

    config.setHeader("useCoalFromStorageCart", "\nWhether or not powered minecarts obtain their coal from attached storage minecarts");
    useCoalFromStorageCart = config.get("useCoalFromStorageCart", false);

    config.setHeader("setOwnerOnPlacement", "\nWhether or not the player that places a minecart is set owner");
    setOwnerOnPlacement = config.get("setOwnerOnPlacement", true);

    config.setHeader("playSoundAtStation", "\nWhether or not a hissing sound is made when trains stop at a station");
    playSoundAtStation = config.get("playSoundAtStation", true);

    config.setHeader("keepChunksLoadedOnlyWhenMoving", "\nWhether or not chunks are only kept loaded when the train is moving");
    keepChunksLoadedOnlyWhenMoving = config.get("keepChunksLoadedOnlyWhenMoving", false);

    config.setHeader("useNetworkSynchronizer", "\nAdvanced: Whether trains use a different way of server->client synchronization");
    config.addHeader("useNetworkSynchronizer", "With this enabled, trains are expected to move smoother with less bumping");
    config.addHeader("useNetworkSynchronizer", "With this disabled, no smoothing is applied. Only disable it if it causes problems/incompatibility");
    useNetworkSynchronizer = config.get("useNetworkSynchronizer", true);

    config.setHeader("maxDetectorLength", "\nThe maximum length a detector region (between two detectors) can be");
    maxDetectorLength = config.get("maxDetectorLength", 2000);

    config.setHeader("maxMinecartStackSize", "\nThe maximum amount of minecart items that can be stacked in one item");
    maxMinecartStackSize = config.get("maxMinecartStackSize", 64);

    config.setHeader("maxTransferRadius", "\nThe maximum radius chest/furnace sign systems look for the needed blocks");
    maxTransferRadius = config.get("maxTransferRadius", 5);

    config.setHeader("defaultTransferRadius", "\nThe default radius chest/furnace sign systems look for the needed blocks");
    defaultTransferRadius = MathUtil.clamp(config.get("defaultTransferRadius", 2), 1, maxTransferRadius);

    config.setHeader("slowDownEmptyCarts", "\nWhether or not empty minecarts slow down faster than occupied minecarts");
    slowDownEmptyCarts = config.get("slowDownEmptyCarts", false);

    config.setHeader("refillAtStations", "\nWhether storage minecarts get fuel when launching from stations");
    refillAtStations = config.get("refillAtStations", true);

    config.setHeader("instantCreativeDestroy", "\nWhether minecarts are instantly destroyed by creative players");
    config.addHeader("instantCreativeDestroy", "Note that manual minecart movement is not possible for creative players with this enabled");
    instantCreativeDestroy = config.get("instantCreativeDestroy", false);

    config.setHeader("allowVerticalPitch", "\nWhether minecarts are allowed to have a 90-degree pitch angle when going up vertical rails");
    config.addHeader("allowVerticalPitch", "When disabled, minecarts will keep a 0-degree pitch angle instead");
    allowVerticalPitch = config.get("allowVerticalPitch", true);

    config.setHeader("allowRailEditing", "\nWhether players (with build permissions) can edit existing rails by right-clicking on them");
    allowRailEditing = config.get("allowRailEditing", true);

    config.setHeader("manualMovementSpeed", "\nWhat velocity to set when a player tries to manually move a train (by damaging it)");
    manualMovementSpeed = config.get("manualMovementSpeed", 12.0);

    config.setHeader("currencyFormat", "\nThe currency Ticket signs will display in messages, %value% represents the displayed value");
    currencyFormat = config.get("currencyFormat", "%value% Dollars");

    config.setHeader("collisionReEnterDelay", "\nThe delay (in ticks) between ejecting and re-entering by collision (e.g. mobs auto-entering carts)");
    collisionReEnterDelay = config.get("collisionReEnterDelay", collisionReEnterDelay);
   
    config.setHeader("allowedBlockBreakTypes", "\nThe block materials that can be broken using minecarts");
    config.addHeader("allowedBlockBreakTypes", "Players with the admin block break permission can use any type");
    config.addHeader("allowedBlockBreakTypes", "Others have to use one from this list");
    allowedBlockBreakTypes.clear();
    if (config.contains("allowedBlockBreakTypes")) {
      for (String value : config.getList("allowedBlockBreakTypes", String.class)) {
        Material type = ParseUtil.parseMaterial(value, null);
        if (type != null) allowedBlockBreakTypes.add(type);
      }
    } else {
      allowedBlockBreakTypes.add(Material.CROPS);
      allowedBlockBreakTypes.add(Material.LOG);
    }
   
    config.setHeader("disabledWorlds", "\nA list of world names where TrainCarts should be disabled");
    config.addHeader("disabledWorlds", "World names are not case-sensitive");
    this.disabledWorlds.clear();
    if (!config.contains("disabledWorlds")) {
      ArrayList<String> defworlds = new ArrayList<String>();
      defworlds.add("DefaultWorld1");
      defworlds.add("DefaultWorld2");
      config.set("disabledWorlds", defworlds);
    }
    for (String world : config.getList("disabledWorlds", String.class)) {
      this.disabledWorlds.add(world.toLowerCase());
    }
   
    //set it again
    List<String> types = config.getList("allowedBlockBreakTypes", String.class);
    types.clear();
    for (Material mat : allowedBlockBreakTypes) {
      types.add(mat.toString());
    }
   
    config.setHeader("showTransferAnimations", "\nWhether or not to show item animations when transferring items");
    showTransferAnimations = config.get("showTransferAnimations", true);
   
    //message shortcuts
    config.setHeader("messageShortcuts", "\nSeveral shortcuts you can use on announce signs (text is replaced)");
    if (!config.contains("messageShortcuts")) {
      config.set("messageShortcuts.welcome", "&eWelcome to &f");
    }
    messageShortcuts.clear().load(config.getNode("messageShortcuts"));
   
    //statement shortcuts
    config.setHeader("statementShortcuts", "\nSeveral shortcuts you can use on switcher and detector signs (text is replaced)");
    if (!config.contains("statementShortcuts")) {
      config.set("statementShortcuts.diamond", "i@diamond");
    }
    statementShortcuts.clear().load(config.getNode("statementShortcuts"));
   
    //parser shortcuts
    config.setHeader("itemShortcuts", "\nSeveral shortcuts you can use on signs to set the items");
    ConfigurationNode itemshort = config.getNode("itemShortcuts");
    parsers.clear();

    // ================= Defaults ===============
    if (!itemshort.contains("fuel")) {
      itemshort.set("fuel", MaterialUtil.ISFUEL.toString());
    }
    if (!itemshort.contains("heatable")) {
      itemshort.set("heatable", MaterialUtil.ISHEATABLE.toString());
    }
    if (!itemshort.contains("armor")) {
      itemshort.set("armor", MaterialUtil.ISARMOR.toString());
    }
    if (!itemshort.contains("sword")) {
      itemshort.set("sword", MaterialUtil.ISSWORD.toString());
    }
    if (!itemshort.contains("boots")) {
      itemshort.set("boots", MaterialUtil.ISBOOTS.toString());
    }
    if (!itemshort.contains("leggings")) {
      itemshort.set("leggins", MaterialUtil.ISLEGGINGS.toString());
    }
    if (!itemshort.contains("chestplate")) {
      itemshort.set("chestplate", MaterialUtil.ISCHESTPLATE.toString());
    }
    if (!itemshort.contains("helmet")) {
      itemshort.set("helmet", MaterialUtil.ISHELMET.toString());
    }
    // ===========================================

    for (Map.Entry<String, String> entry : itemshort.getValues(String.class).entrySet()) {
      putParsers(entry.getKey(), Util.getParsers(entry.getValue()));
      itemshort.setRead(entry.getKey());
    }

    config.trim();
    config.save();
  }

  @Override
  public void updateDependency(Plugin plugin, String pluginName, boolean enabled) {
    if (pluginName.equals("SignLink")) {
      Task.stop(signtask);
      if (SignLinkEnabled = enabled) {
        log(Level.INFO, "SignLink detected, support for arrival signs added!");
        signtask = new Task(this) {
          public void run() {
            ArrivalSigns.updateAll();
          }
        };
        signtask.start(0, 10);
      } else {
        signtask = null;
      }
    } else if (pluginName.equals("My Worlds")) {
      if (MyWorldsEnabled = enabled) {
        log(Level.INFO, "MyWorlds detected, support for portal sign train teleportation added!");
      }
    } else if (pluginName.equals("Essentials")) {
      EssentialsEnabled = enabled;
    }
  }

  @Override
  public int getMinimumLibVersion() {
    return Common.VERSION;
  }

  public void enable() {
    plugin = this;

    //registering
    this.register(packetListener = new TCPacketListener(), PacketType.IN_STEER_VEHICLE);
    this.register(TCListener.class);
    this.register(RedstoneTracker.class);
    this.register("train", "cart");
    Conversion.register(MemberConverter.toMember);

    //Load configuration
    loadConfig();

    //update max item stack
    if (maxMinecartStackSize != 1) {
      for (Material material : Material.values())  {
        if (MaterialUtil.ISMINECART.get(material)) {
          Util.setItemMaxSize(material, maxMinecartStackSize);
        }
      }
    }

    //init statements
    Statement.init();

    //Init signs
    SignAction.init();

    //Load properties
    TrainProperties.load();

    //Load groups
    OfflineGroupManager.init(getDataFolder() + File.separator + "trains.groupdata");

    //Convert Minecarts
    MinecartMemberStore.convertAll();

    //Load destinations
    PathNode.init(getDataFolder() + File.separator + "destinations.dat");

    //Load arrival times
    ArrivalSigns.init(getDataFolder() + File.separator + "arrivaltimes.txt");

    //Load detector regions
    DetectorRegion.init(getDataFolder() + File.separator + "detectorregions.dat")

    //Load detector sign locations
    SignActionDetector.init(getDataFolder() + File.separator + "detectorsigns.dat");

    //Load spawn sign locations
    SignActionSpawn.init(getDataFolder() + File.separator + "spawnsigns.dat");

    //Restore carts where possible
    TrainCarts.plugin.log(Level.INFO, "Restoring trains and loading nearby chunks...");
    OfflineGroupManager.refresh();

    // Start the path finding task
    PathProvider.init();

    // Hackish fix the chunk persistence failing
    fixGroupTickTask = new Task(this) {
      public void run() {
        MinecartGroupStore.doFixedTick();
      }
    }.start(1, 1);

    //Properly dispose of partly-referenced carts
    CommonUtil.nextTick(new Runnable() {
      public void run() {
        for (World world : WorldUtil.getWorlds()) {
          OfflineGroupManager.removeBuggedMinecarts(world);
        }
      }
    });
  }

  /**
   * Saves all traincarts related information to file
   */
  public void save() {
    //Save properties
    TrainProperties.save();

    //Save destinations
    PathNode.save(getDataFolder() + File.separator + "destinations.dat");

    //Save arrival times
    ArrivalSigns.save(getDataFolder() + File.separator + "arrivaltimes.txt");

    //Save spawn sign locations
    SignActionSpawn.save(getDataFolder() + File.separator + "spawnsigns.dat");

    //Save detector sign locations
    SignActionDetector.save(getDataFolder() + File.separator + "detectorsigns.dat");

    //Save detector regions
    DetectorRegion.save(getDataFolder() + File.separator + "detectorregions.dat");

    // Save train information
    OfflineGroupManager.save(getDataFolder() + File.separator + "trains.groupdata");
  }

  public void disable() {
    //Unregister listeners
    this.unregister(packetListener);
    packetListener = null;

    //Stop tasks
    Task.stop(signtask);
    Task.stop(fixGroupTickTask);

    //update max item stack
    if (maxMinecartStackSize != 1) {
      for (Material material : Material.values())  {
        if (MaterialUtil.ISMINECART.get(material)) {
          Util.setItemMaxSize(material, 1);
        }
      }
    }

    //undo replacements for correct native saving
    for (MinecartGroup mg : MinecartGroup.getGroups()) {
      mg.unload();
    }

    //entities left behind?
    for (World world : WorldUtil.getWorlds()) {
      for (org.bukkit.entity.Entity entity : WorldUtil.getEntities(world)) {
        MinecartGroup group = MinecartGroup.get(entity);
        if (group != null) {
          group.unload();
        }
      }
    }

    save();

    // Deinit classes
    PathNode.deinit();
    ArrivalSigns.deinit();
    SignActionSpawn.deinit();
    Statement.deinit();
    SignAction.deinit();
    ItemAnimation.deinit();
    OfflineGroupManager.deinit();
    PathProvider.deinit();
  }

  public boolean command(CommandSender sender, String cmd, String[] args) {
    return Commands.execute(sender, cmd, args);
  }

  @Override
  public void localization() {
    this.loadLocales(Localization.class);
  }

  @Override
  public void permissions() {
    this.loadPermissions(Permission.class);
  }

  /**
   * Gets the Currency text to display a currency value
   *
   * @param value to display
   * @return currency text
   */
  public static String getCurrencyText(double value) {
    return currencyFormat.replace("%value%", Double.toString(value));
  }

  /**
   * Converts generic text to a formatted message based on style codes and message shortcuts
   *
   * @param text to convert
   * @return message
   */
  public static String getMessage(String text) {
    return StringUtil.ampToColor(messageShortcuts.replace(text));
  }

  /**
   * Sends a message to a player, keeping player-specific text variables in mind
   *
   * @param player to send the message to
   * @param text to send
   */
  public static void sendMessage(Player player, String text) {
    if (TrainCarts.SignLinkEnabled) {
      int startindex, endindex;
      while ((startindex = text.indexOf('%')) != -1 && (endindex = text.indexOf('%', startindex + 1)) != -1) {
        String varname = text.substring(startindex + 1, endindex);
        String value = varname.isEmpty() ? "%" : Variables.get(varname).get(player.getName());
        text = text.substring(0, startindex) + value + text.substring(endindex + 1);
      }
    }
    player.sendMessage(text);
  }

  public static boolean isWorldDisabled(BlockEvent event) {
    return isWorldDisabled(event.getBlock().getWorld());
  }
  public static boolean isWorldDisabled(Block worldContainer) {
    return isWorldDisabled(worldContainer.getWorld());
  }
  public static boolean isWorldDisabled(World world) {
    return isWorldDisabled(world.getName());
  }
  public static boolean isWorldDisabled(String worldname) {
    return plugin.disabledWorlds.contains(worldname.toLowerCase());
  }

  public static boolean handlePlayerVehicleChange(Player player, Entity newVehicle) {
    try {
      MinecartMember<?> newMinecart = MinecartMemberStore.get(newVehicle);
      if (newMinecart != null) {
        CartPropertiesStore.setEditing(player, newMinecart.getProperties());
      }
      // Allow exiting the current minecart
      MinecartMember<?> entered = MinecartMemberStore.get(player.getVehicle());
      if (entered != null && !entered.getProperties().getPlayersExit()) {
        return false;
      }
    } catch (Throwable t) {
      TrainCarts.plugin.handle(t);
    }
    return true;
  }
}
TOP

Related Classes of com.bergerkiller.bukkit.tc.TrainCarts

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.