Package com.bergerkiller.bukkit.tc

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

package com.bergerkiller.bukkit.tc;

import java.util.logging.Level;

import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.BlockState;
import org.bukkit.block.Sign;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockPhysicsEvent;
import org.bukkit.event.block.BlockRedstoneEvent;
import org.bukkit.event.world.ChunkLoadEvent;

import com.bergerkiller.bukkit.common.collections.BlockSet;
import com.bergerkiller.bukkit.common.utils.BlockUtil;
import com.bergerkiller.bukkit.common.utils.CommonUtil;
import com.bergerkiller.bukkit.common.utils.FaceUtil;
import com.bergerkiller.bukkit.common.utils.LogicUtil;
import com.bergerkiller.bukkit.common.utils.MaterialUtil;
import com.bergerkiller.bukkit.common.utils.WorldUtil;
import com.bergerkiller.bukkit.tc.events.SignActionEvent;
import com.bergerkiller.bukkit.tc.signactions.SignAction;
import com.bergerkiller.bukkit.tc.signactions.SignActionType;

/**
* Keeps track of Redstone Power for signs, raising proper Sign redstone events in the process
*/
public class RedstoneTracker implements Listener {
  private final BlockSet ignoredSigns = new BlockSet();
  private BlockSet poweredBlocks = new BlockSet();

  @EventHandler(priority = EventPriority.MONITOR)
  public void onChunkLoad(ChunkLoadEvent event) {
    // Set the initial power state of all signs within this Chunk
    SignActionEvent info;
    try {
      for (BlockState state : WorldUtil.getBlockStates(event.getChunk())) {
        if (state instanceof Sign) {
          info = new SignActionEvent(state.getBlock());
          LogicUtil.addOrRemove(poweredBlocks, info.getBlock(), isPowered(info));
        }
      }
    } catch (Throwable t) {
      TrainCarts.plugin.getLogger().log(Level.SEVERE, "Error while initializing sign power states in chunk " + event.getChunk().getX() + "/" + event.getChunk().getZ(), t);
    }
  }

  @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
  public void onBlockPhysics(BlockPhysicsEvent event) {
    final Block block = event.getBlock();
    final Material type = block.getType();
    if (MaterialUtil.ISSIGN.get(type)) {
      if (Util.isSupported(block)) {
        // Check for potential redstone changes
        updateRedstonePower(block);
      } else {
        // Remove from block power storage
        poweredBlocks.remove(block);
      }
    } else if (MaterialUtil.ISREDSTONETORCH.get(type)) {
      // Send proper update events for all signs around this power source
      for (BlockFace face : FaceUtil.RADIAL) {
        final Block rel = event.getBlock().getRelative(face);
        if (MaterialUtil.ISSIGN.get(rel)) {
          CommonUtil.nextTick(new Runnable() {
            public void run() {
              updateRedstonePower(rel);
            }
          });
        }
      }
    }
  }

  @EventHandler(priority = EventPriority.HIGHEST)
  public void onBlockRedstoneChange(BlockRedstoneEvent event) {
    if (TrainCarts.isWorldDisabled(event)) {
      return;
    }
    Material type = event.getBlock().getType();
    if (BlockUtil.isType(type, Material.LEVER)) {
      Block up = event.getBlock().getRelative(BlockFace.UP);
      Block down = event.getBlock().getRelative(BlockFace.DOWN);
      if (MaterialUtil.ISSIGN.get(up)) {
        updateRedstonePower(up, event.getNewCurrent() > 0);
      }
      if (MaterialUtil.ISSIGN.get(down)) {
        updateRedstonePower(down, event.getNewCurrent() > 0);
      }
      ignoreOutputLever(event.getBlock());
    } else if (MaterialUtil.ISSIGN.get(type)) {
      updateRedstonePower(event.getBlock(), event.getNewCurrent() > 0);
    }
  }

  /**
   * Ignores signs of current-tick redstone changes caused by the lever
   *
   * @param lever to ignore
   */
  public void ignoreOutputLever(Block lever) {
    // Ignore signs that are attached to the block the lever is attached to
    Block att = BlockUtil.getAttachedBlock(lever);
    for (BlockFace face : FaceUtil.ATTACHEDFACES) {
      Block signblock = att.getRelative(face);
      if (MaterialUtil.ISSIGN.get(signblock) && BlockUtil.getAttachedFace(signblock) == face.getOppositeFace()) {
        if (ignoredSigns.isEmpty()) {
          // clear this the next tick
          CommonUtil.nextTick(new Runnable() {
            public void run() {
              ignoredSigns.clear();
            }
          });
        }
        ignoredSigns.add(signblock);
      }
    }
  }

  public boolean isPowered(SignActionEvent info) {
    return info.isPoweredRaw(false);
  }

  public void updateRedstonePower(final Block signblock) {
    final SignActionEvent info = new SignActionEvent(signblock);
    SignAction.executeAll(info, SignActionType.REDSTONE_CHANGE);
    // Do not proceed if the sign disallows on/off changes
    if (info.isPowerAlwaysOn() || ignoredSigns.remove(signblock)) {
      return;
    }
    // Update power level
    setRedstonePower(info, isPowered(info));
  }

  public void updateRedstonePower(final Block signblock, boolean isPowered) {
    final SignActionEvent info = new SignActionEvent(signblock);
    SignAction.executeAll(info, SignActionType.REDSTONE_CHANGE);
    // Do not proceed if the sign disallows on/off changes
    if (info.isPowerAlwaysOn() || ignoredSigns.remove(signblock)) {
      return;
    }

    // Validate with the SignActionEvent whether the power state is correct
    if (isPowered(info) != isPowered) {
      return;
    }
    // Update power level
    setRedstonePower(info, isPowered);
  }

  public void setRedstonePower(SignActionEvent info, boolean newPowerState) {
    // Change in redstone power?
    if (!LogicUtil.addOrRemove(poweredBlocks, info.getBlock(), newPowerState)) {
      return;
    }
    // Execute event
    SignAction.executeAll(info, info.isPowerInverted() != newPowerState ?
        SignActionType.REDSTONE_ON : SignActionType.REDSTONE_OFF);
  }
}
TOP

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

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.