Package com.bergerkiller.bukkit.tc.signactions

Source Code of com.bergerkiller.bukkit.tc.signactions.SignActionSwitcher

package com.bergerkiller.bukkit.tc.signactions;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.Sign;

import com.bergerkiller.bukkit.common.collections.BlockMap;
import com.bergerkiller.bukkit.common.utils.BlockUtil;
import com.bergerkiller.bukkit.common.utils.LogicUtil;
import com.bergerkiller.bukkit.common.utils.MaterialUtil;
import com.bergerkiller.bukkit.tc.Direction;
import com.bergerkiller.bukkit.tc.DirectionStatement;
import com.bergerkiller.bukkit.tc.Permission;
import com.bergerkiller.bukkit.tc.actions.GroupActionWaitPathFinding;
import com.bergerkiller.bukkit.tc.events.SignActionEvent;
import com.bergerkiller.bukkit.tc.events.SignChangeActionEvent;
import com.bergerkiller.bukkit.tc.pathfinding.PathConnection;
import com.bergerkiller.bukkit.tc.pathfinding.PathNode;
import com.bergerkiller.bukkit.tc.pathfinding.PathProvider;
import com.bergerkiller.bukkit.tc.properties.IProperties;

public class SignActionSwitcher extends SignAction {
  private BlockMap<AtomicInteger> switchedTimes = new BlockMap<AtomicInteger>();
  private AtomicInteger getSwitchedTimes(Block signblock) {
    AtomicInteger i = switchedTimes.get(signblock);
    if (i == null) {
      i = new AtomicInteger();
      switchedTimes.put(signblock, i);
    }
    return i;
  }

  @Override
  public boolean match(SignActionEvent info) {
    return info.isType("switcher", "tag");
  }

  @Override
  public void execute(SignActionEvent info) {
    boolean doCart = false;
    boolean doTrain = false;
    if (info.isAction(SignActionType.GROUP_ENTER, SignActionType.GROUP_UPDATE) && info.isTrainSign()) {
      doTrain = true;
    } else if (info.isAction(SignActionType.MEMBER_ENTER, SignActionType.MEMBER_UPDATE) && info.isCartSign()) {
      doCart = true;
    } else if (info.isAction(SignActionType.MEMBER_LEAVE) && info.isCartSign()) {
      info.setLevers(false);
      return;
    } else if (info.isAction(SignActionType.GROUP_LEAVE) && info.isTrainSign()) {
      info.setLevers(false);
      return;
    } else {
      return;
    }
    if (!info.hasRailedMember()) {
      return;
    }
    final boolean facing = info.isFacing();
    if (facing) {
      final BlockFace cartDirection = info.getCartDirection();
      //find out what statements to parse
      List<DirectionStatement> statements = new ArrayList<DirectionStatement>();
      statements.add(new DirectionStatement(info.getLine(2), cartDirection, Direction.LEFT));
      statements.add(new DirectionStatement(info.getLine(3), cartDirection, Direction.RIGHT));
      //other signs below this sign we could parse?
      for (Sign sign : info.findSignsBelow()) {
        boolean valid = true;
        for (String line : sign.getLines()) {
          DirectionStatement stat = new DirectionStatement(line, cartDirection);
          if (stat.direction == Direction.NONE) {
            valid = false;
            break;
          } else {
            statements.add(stat);
          }
        }
        if (!valid) {
          break;
        }
      }
      Block signblock = info.getBlock();
      while (MaterialUtil.ISSIGN.get(signblock = signblock.getRelative(BlockFace.DOWN))) {
        Sign sign = BlockUtil.getSign(signblock);
        if (sign == null) break;
        boolean valid = true;
        for (String line : sign.getLines()) {
          DirectionStatement stat = new DirectionStatement(line, cartDirection);
          if (stat.direction == Direction.NONE) {
            valid = false;
            break;
          } else {
            statements.add(stat);
          }
        }
        if (!valid) break;
      }
      //parse all of the statements
      //are we going to use a counter?
      int maxcount = 0;
      int currentcount = 0;
      AtomicInteger signcounter = null;
      for (DirectionStatement stat : statements) {
        if (stat.hasNumber()) {
          maxcount += stat.number;
          if (signcounter == null) {
            signcounter = getSwitchedTimes(info.getBlock());
            if (info.isAction(SignActionType.MEMBER_ENTER, SignActionType.GROUP_ENTER)) {
              currentcount = signcounter.getAndIncrement();
            } else {
              currentcount = signcounter.get();
            }
          }
        }
      }
      if (signcounter != null && currentcount >= maxcount) {
        signcounter.set(1);
        currentcount = 0;
      }
     
      int counter = 0;
      Direction dir = Direction.NONE;
      for (DirectionStatement stat : statements) {
        if ((stat.hasNumber() && (counter += stat.number) > currentcount)
            || (doCart && stat.has(info, info.getMember()))
            || (doTrain && stat.has(info, info.getGroup()))) {

          dir = stat.direction;
          break;
        }
      }
      info.setLevers(dir != Direction.NONE);
      if (dir != Direction.NONE && info.isPowered()) {
        //handle this direction
        info.setRailsTo(dir);
        return; //don't do destination stuff
      }
    }

    // Handle destination alternatively
    if (info.isAction(SignActionType.MEMBER_ENTER, SignActionType.GROUP_ENTER) && (facing || !info.isWatchedDirectionsDefined())) {
      PathNode node = PathNode.getOrCreate(info);
      if (node != null) {
        String destination = null;
        IProperties prop = null;
        if (doCart && info.hasMember()) {
          prop = info.getMember().getProperties();
        } else if (doTrain && info.hasGroup()) {
          prop = info.getGroup().getProperties();
        }
        if (prop != null) {
          destination = prop.getDestination();
          prop.setLastPathNode(node.getName());
        }
        // Continue with path finding if a valid destination is specified
        // If the current node denotes the destination - don't switch!
        if (!LogicUtil.nullOrEmpty(destination) && !node.containsName(destination)) {
          if (PathProvider.isProcessing()) {
            double currentForce = info.getGroup().getAverageForce();
            // Add an action to let the train wait until the node IS explored
            info.getGroup().getActions().addAction(new GroupActionWaitPathFinding(info, node, destination));
            info.getMember().getActions().addActionLaunch(info.getMember().getDirectionFrom(), 1.0, currentForce);
            info.getGroup().stop();
          } else {
            // Switch the rails to the right direction
            PathConnection conn = node.findConnection(destination);
            if (conn != null) {
              info.setRailsTo(conn.direction);
            }
          }
        }
      }
    }
  }

  @Override
  public boolean build(SignChangeActionEvent event) {
    if (event.isCartSign()) {
      return handleBuild(event, Permission.BUILD_SWITCHER, "cart switcher", "switch between tracks based on properties of the cart above");
    } else if (event.isTrainSign()) {
      return handleBuild(event, Permission.BUILD_SWITCHER, "train switcher", "switch between tracks based on properties of the train above");
    }
    return false;
  }

  @Override
  public void destroy(SignActionEvent event) {
    // Remove the switcher name (location toString) from the available node names
    Block rails = event.getRails();
    if (rails != null) {
      PathNode node = PathNode.get(rails);
      if (node != null) {
        node.removeName(node.location.toString());
      }
    }
  }

  @Override
  public boolean overrideFacing() {
    return true;
  }
}
TOP

Related Classes of com.bergerkiller.bukkit.tc.signactions.SignActionSwitcher

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.