/* * $Id$ * * Copyright (c) 2000-2003 by Rodney Kinney * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License (LGPL) as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, copies are available * at http://www.opensource.org. */ /* * Created by IntelliJ IDEA. * User: rkinney * Date: Jun 13, 2002 * Time: 9:52:40 PM * To change template for new class use * Code Style | Class Templates options (Tools | IDE Options). */ package VASSAL.counters; import java.awt.Component; import java.awt.Graphics; import java.awt.Rectangle; import java.awt.Shape; import java.util.Iterator; import javax.swing.Box; import javax.swing.JComponent; import javax.swing.KeyStroke; import VASSAL.build.GameModule; import VASSAL.build.module.Map; import VASSAL.build.module.PlayerRoster; import VASSAL.build.module.documentation.HelpFile; import VASSAL.command.ChangeTracker; import VASSAL.command.Command; import VASSAL.command.NullCommand; import VASSAL.configure.BooleanConfigurer; import VASSAL.configure.StringArrayConfigurer; import VASSAL.tools.SequenceEncoder; /** * A GamePiece with the Restricted trait can only be manipulated by the player playing a specific side */ public class Restricted extends Decorator implements EditablePiece { public static final String ID = "restrict;"; private String[] side; private boolean restrictByPlayer; private String owningPlayer=""; private boolean restrictMovement = true; private static PlayerRoster.SideChangeListener handleRetirement; public Restricted() { this(ID, null); } public Restricted(String type, GamePiece p) { setInner(p); mySetType(type); if (handleRetirement == null) { handleRetirement = new RetirementHandler(); PlayerRoster.addSideChangeListener(handleRetirement); } } public String getDescription() { return "Restricted Access"; } public HelpFile getHelpFile() { return HelpFile.getReferenceManualPage("RestrictedAccess.htm"); } public void mySetType(String type) { type = type.substring(ID.length()); SequenceEncoder.Decoder st = new SequenceEncoder.Decoder(type,';'); side = st.nextStringArray(0); restrictByPlayer = st.nextBoolean(false); restrictMovement = st.nextBoolean(true); } public Shape getShape() { return piece.getShape(); } public Rectangle boundingBox() { return piece.boundingBox(); } public void draw(Graphics g, int x, int y, Component obs, double zoom) { piece.draw(g, x, y, obs, zoom); } public String getName() { return piece.getName(); } protected KeyCommand[] myGetKeyCommands() { return new KeyCommand[0]; } public boolean isRestricted() { boolean restricted = false; if (restrictByPlayer) { restricted = owningPlayer.length() > 0 && !GameModule.getUserId().equals(owningPlayer); } if ((restricted || !restrictByPlayer) && PlayerRoster.isActive() && GameModule.getGameModule().getGameState().isGameStarted()) { restricted = true; for (int i = 0; i < side.length; ++i) { if (side[i].equals(PlayerRoster.getMySide())) { restricted = false; break; } } } return restricted; } /* @Override public void setMap(Map m) { if (m != null && restrictByPlayer && owningPlayer.length() == 0) { owningPlayer = GameModule.getUserId(); } super.setMap(m); } */ @Override public void setProperty(Object key, Object val) { if (Properties.SELECTED.equals(key) && Boolean.TRUE.equals(val) && restrictByPlayer && owningPlayer.length() == 0) { if (getMap() != null) { owningPlayer = GameModule.getUserId(); } else { System.err.println("Selected, but map == null"); } } super.setProperty(key, val); } protected KeyCommand[] getKeyCommands() { if (!isRestricted()) { return super.getKeyCommands(); } else { return new KeyCommand[0]; } } @Override public Object getLocalizedProperty(Object key) { if (Properties.RESTRICTED.equals(key)) { return Boolean.valueOf(isRestricted()); } else if (Properties.RESTRICTED_MOVEMENT.equals(key)) { return Boolean.valueOf(isRestricted() && restrictMovement); } else { return super.getLocalizedProperty(key); } } public Object getProperty(Object key) { if (Properties.RESTRICTED.equals(key)) { return Boolean.valueOf(isRestricted()); } else if (Properties.RESTRICTED_MOVEMENT.equals(key)) { return Boolean.valueOf(isRestricted() && restrictMovement); } else { return super.getProperty(key); } } public String myGetState() { return owningPlayer; } public String myGetType() { return ID + new SequenceEncoder(';').append(side).append(restrictByPlayer).append(restrictMovement).getValue(); } public Command myKeyEvent(KeyStroke stroke) { return null; } public Command keyEvent(KeyStroke stroke) { if (!isRestricted()) { return super.keyEvent(stroke); } else { return null; } } public void mySetState(String newState) { owningPlayer = newState; } public PieceEditor getEditor() { return new Ed(this); } public static class Ed implements PieceEditor { private BooleanConfigurer byPlayer; private StringArrayConfigurer config; private BooleanConfigurer movementConfig; private Box box; public Ed(Restricted r) { byPlayer = new BooleanConfigurer(null,"Also belongs to initially-placing player?",r.restrictByPlayer); config = new StringArrayConfigurer(null, "Belongs to side", r.side); movementConfig = new BooleanConfigurer(null, "Prevent non-owning players from moving piece?", r.restrictMovement); box = Box.createVerticalBox(); ((JComponent)byPlayer.getControls()).setAlignmentX(Box.LEFT_ALIGNMENT); ((JComponent)movementConfig.getControls()).setAlignmentX(Box.LEFT_ALIGNMENT); box.add(config.getControls()); box.add(byPlayer.getControls()); box.add(movementConfig.getControls()); } public Component getControls() { return box; } public String getState() { return ""; } public String getType() { return ID + new SequenceEncoder(';').append(config.getValueString()).append(byPlayer.booleanValue()).append(movementConfig.booleanValue()).getValue(); } } /** * When a player changes sides to become an observer, relinquish ownership of all pieces * @author rodneykinney * */ private static class RetirementHandler implements PlayerRoster.SideChangeListener, PieceVisitor { public void sideChanged(String oldSide, String newSide) { if (newSide == null) { PieceVisitorDispatcher d = new PieceVisitorDispatcher(this); Command c = new NullCommand(); for(Map m : GameModule.getGameModule().getComponentsOf(Map.class)) { for (GamePiece piece : m.getPieces()) { c = c.append((Command)d.accept(piece)); } } GameModule.getGameModule().sendAndLog(c); } } public Object visitDefault(GamePiece p) { Restricted r = (Restricted)Decorator.getDecorator(p, Restricted.class); if (r != null && r.restrictByPlayer && GameModule.getUserId().equals(r.owningPlayer)) { ChangeTracker t = new ChangeTracker(p); r.owningPlayer = ""; return t.getChangeCommand(); } return null; } public Object visitStack(Stack s) { Command c = new NullCommand(); for (Iterator<GamePiece> it = s.getPiecesIterator(); it.hasNext();) { c = c.append((Command)visitDefault(it.next())); } return c; } } }