package me.desht.chesscraft.controlpanel; import chesspresso.Chess; import me.desht.chesscraft.ChessCraft; import me.desht.chesscraft.chess.BoardView; import me.desht.chesscraft.chess.ChessGame; import me.desht.chesscraft.chess.TimeControl; import me.desht.chesscraft.chess.TimeControlDefs; import me.desht.chesscraft.enums.BoardRotation; import me.desht.chesscraft.exceptions.ChessException; import me.desht.dhutils.PersistableLocation; import me.desht.dhutils.block.MassBlockUpdate; import me.desht.dhutils.cuboid.Cuboid; import me.desht.dhutils.cuboid.Cuboid.CuboidDirection; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.material.MaterialData; import java.util.HashMap; import java.util.Map; public class ControlPanel { public static final int PANEL_WIDTH = 8; private final BoardView view; private final BoardRotation signDir; private final Cuboid panelBlocks; private final Cuboid toMoveIndicator; private final PlyCountLabel plyCountLabel; private final HalfmoveClockLabel halfMoveClockLabel; private final ClockLabel[] clockLabels; private final Map<PersistableLocation, AbstractSignButton> buttonLocs; private final Map<String,AbstractSignButton> buttonNames; public ControlPanel(BoardView view) { this.view = view; BoardRotation boardDir = view.getRotation(); signDir = boardDir.getRight(); buttonLocs = new HashMap<PersistableLocation, AbstractSignButton>(); buttonNames = new HashMap<String, AbstractSignButton>(); panelBlocks = getPanelPosition(); createSignButtons(); setTimeControl(getView().getDefaultTcSpec()); plyCountLabel = new PlyCountLabel(this); halfMoveClockLabel = new HalfmoveClockLabel(this); clockLabels = new ClockLabel[2]; clockLabels[Chess.WHITE] = new ClockLabel(this, Chess.WHITE); clockLabels[Chess.BLACK] = new ClockLabel(this, Chess.BLACK); toMoveIndicator = panelBlocks.inset(CuboidDirection.Vertical, 1). expand(boardDir.getDirection(), -((PANEL_WIDTH - 2) / 2)). expand(boardDir.getDirection().opposite(), -((PANEL_WIDTH - 2) / 2)); } private void createSignButtons() { createSignButton(new BlackNoButton(this)); createSignButton(new BlackYesButton(this)); createSignButton(new BoardInfoButton(this)); createSignButton(new CreateGameButton(this)); createSignButton(new GameInfoButton(this)); createSignButton(new InviteAnyoneButton(this)); createSignButton(new InvitePlayerButton(this)); createSignButton(new OfferDrawButton(this)); createSignButton(new PromoteBlackButton(this)); createSignButton(new PromoteWhiteButton(this)); createSignButton(new ResignButton(this)); createSignButton(new StakeButton(this)); createSignButton(new StartButton(this)); createSignButton(new TeleportButton(this)); createSignButton(new TimeControlButton(this)); createSignButton(new UndoButton(this)); createSignButton(new WhiteNoButton(this)); createSignButton(new WhiteYesButton(this)); } private void createSignButton(AbstractSignButton button) { buttonLocs.put(button.getLocation(), button); buttonNames.put(button.getClass().getSimpleName(), button); } public void setTimeControl(String spec) { if (spec.isEmpty()) { spec = ChessCraft.getInstance().getConfig().getString("time_control.default"); } getTcDefs().addCustomSpec(spec); getSignButton(TimeControlButton.class).repaint(); } public BoardView getView() { return view; } public TimeControlDefs getTcDefs() { return getSignButton(TimeControlButton.class).getTcDefs(); } public void removeSigns() { panelBlocks.shift(signDir.getDirection(), 1).fill(new MaterialData(Material.AIR)); } public <T extends AbstractSignButton> T getSignButton(Class<T> type) { return type.cast(buttonNames.get(type.getSimpleName())); } public boolean isSignButton(Location location) { return buttonLocs.containsKey(new PersistableLocation(location)); } /** * Get a teleport-in location for this control panel. Player will be standing in front of the * control panel, facing it. * * @return The teleport-in location */ public Location getTeleportLocation() { double xOff = (panelBlocks.getUpperX() - panelBlocks.getLowerX()) / 2.0 + 0.5 + signDir.getXadjustment() * 3.5; double zOff = (panelBlocks.getUpperZ() - panelBlocks.getLowerZ()) / 2.0 + 0.5 + signDir.getZadjustment() * 3.5; return new Location(panelBlocks.getWorld(), panelBlocks.getLowerX() + xOff, panelBlocks.getLowerY(), panelBlocks.getLowerZ() + zOff, (signDir.getYaw() + 180.0f) % 360, 0.0f); } public Cuboid getPanelBlocks() { return panelBlocks; } public void repaintAll(MassBlockUpdate mbu) { if (mbu != null) { panelBlocks.fill(view.getControlPanelMaterial(), mbu); } else { panelBlocks.fill(view.getControlPanelMaterial()); } panelBlocks.forceLightLevel(view.getChessBoard().getBoardStyle().getLightLevel()); repaintControls(); } public void repaintControls() { repaintSignButtons(); repaintClocks(); halfMoveClockLabel.repaint(); plyCountLabel.repaint(); updateToMoveIndicator(); } public void repaintClocks() { ChessGame game = view.getGame(); if (game != null) { TimeControl tc = game.getTimeControl(); updateClock(Chess.WHITE, tc.getClockString()); updateClock(Chess.BLACK, tc.getClockString()); } } public void repaintSignButtons() { for (AbstractSignButton btn : buttonLocs.values()) { btn.repaint(); } } public void signClicked(PlayerInteractEvent event) throws ChessException { AbstractSignButton btn = buttonLocs.get(new PersistableLocation(event.getClickedBlock().getLocation())); if (btn != null) { btn.onClicked(event); } } public void updateToMoveIndicator() { int toPlay = Chess.NOBODY; if (view.getGame() != null) { toPlay = view.getGame().getPosition().getToPlay(); } updateToMoveIndicator(toPlay); } public void updateToMoveIndicator(int toPlay) { MaterialData mat = getView().getControlPanelMaterial(); if (toPlay == Chess.WHITE) { mat = getView().getWhiteSquareMaterial(); } else if (toPlay == Chess.BLACK) { mat = getView().getBlackSquareMaterial(); } toMoveIndicator.fill(mat); } public void updatePlyCount(int plyNumber) { plyCountLabel.setCount(plyNumber); plyCountLabel.repaint(); } public void updateHalfMoveClock(int halfMoveClock) { halfMoveClockLabel.setCount(halfMoveClock); halfMoveClockLabel.repaint(); } // public void updateClock(int colour, TimeControl tc) { // clockLabels[colour].setTimeControl(tc); // clockLabels[colour].repaint(); // } public void updateClock(int colour, String timeStr) { clockLabels[colour].setLabel(timeStr); clockLabels[colour].repaint(); } /** * Calculate the control panel position based on the boardview's position * and rotation. * * @return a Cuboid representing the panel position */ private Cuboid getPanelPosition() { BoardRotation dir = view.getRotation(); BoardRotation dirLeft = dir.getLeft(); Location a1 = view.getA1Square(); int panelOffset = 4 * view.getSquareSize() - PANEL_WIDTH / 2; int frameOffset = (int) Math.ceil((view.getFrameWidth() + .5) / 2); // for the control panel edge, move <panelOffset> blocks in the board's direction, then // <frameOffset> blocks to the left of that. int x = a1.getBlockX() + dir.getXadjustment(panelOffset) + dirLeft.getXadjustment(frameOffset); int y = a1.getBlockY() + 1; int z = a1.getBlockZ() + dir.getZadjustment(panelOffset) + dirLeft.getZadjustment(frameOffset); // then expand the cuboid in the board's direction by the panel's desired width Cuboid panel = new Cuboid(new Location(a1.getWorld(), x, y, z)); return panel.expand(dir.getDirection(), PANEL_WIDTH - 1).expand(CuboidDirection.Up, 2); } }