use of soc.game.SOCBoardLarge in project JSettlers2 by jdmonin.
the class SOCDisplaylessPlayerClient method handleBOARDLAYOUT2.
/**
* handle the "board layout" message, new format
* @param games Games the client is playing, for method reuse by SOCPlayerClient
* @param mes the message
* @since 1.1.08
* @return True if game was found and layout understood, false otherwise
*/
public static boolean handleBOARDLAYOUT2(Map<String, SOCGame> games, SOCBoardLayout2 mes) {
SOCGame ga = games.get(mes.getGame());
if (ga == null)
return false;
SOCBoard bd = ga.getBoard();
final int bef = mes.getBoardEncodingFormat();
if (bef == SOCBoard.BOARD_ENCODING_LARGE) {
// v3
((SOCBoardLarge) bd).setLandHexLayout(mes.getIntArrayPart("LH"));
ga.setPlayersLandHexCoordinates();
int hex = mes.getIntPart("RH");
if (hex != 0)
bd.setRobberHex(hex, false);
hex = mes.getIntPart("PH");
if (hex != 0)
((SOCBoardLarge) bd).setPirateHex(hex, false);
int[] portLayout = mes.getIntArrayPart("PL");
if (portLayout != null)
bd.setPortsLayout(portLayout);
int[] x = mes.getIntArrayPart("PX");
if (x != null)
((SOCBoardLarge) bd).setPlayerExcludedLandAreas(x);
x = mes.getIntArrayPart("RX");
if (x != null)
((SOCBoardLarge) bd).setRobberExcludedLandAreas(x);
x = mes.getIntArrayPart("CV");
if (x != null)
((SOCBoardLarge) bd).setVillageAndClothLayout(x);
x = mes.getIntArrayPart("LS");
if (x != null)
((SOCBoardLarge) bd).addLoneLegalSettlements(ga, x);
HashMap<String, int[]> others = mes.getAddedParts();
if (others != null)
((SOCBoardLarge) bd).setAddedLayoutParts(others);
} else if (bef <= SOCBoard.BOARD_ENCODING_6PLAYER) {
// v1 or v2
bd.setHexLayout(mes.getIntArrayPart("HL"));
bd.setNumberLayout(mes.getIntArrayPart("NL"));
bd.setRobberHex(mes.getIntPart("RH"), false);
int[] portLayout = mes.getIntArrayPart("PL");
if (portLayout != null)
bd.setPortsLayout(portLayout);
} else {
// Should not occur: Server has sent an unrecognized format
System.err.println("Cannot recognize game encoding v" + bef + " for game " + ga.getName());
return false;
}
ga.updateAtBoardLayout();
return true;
}
use of soc.game.SOCBoardLarge in project JSettlers2 by jdmonin.
the class SOCBoardPanel method flushBoardLayoutAndRepaint.
/**
* Clear the board layout (as rendered in the empty-board buffer) and trigger a repaint.
*<P>
* If needed, update margins and visual shift from Added Layout Part {@code "VS"}.
* Doing so will call {@link #rescaleBoard(int, int, boolean)} and may change
* the board panel's minimum size and/or current size. Returns true if current size changes
* here: If so, caller must re-do layout of this panel within its container.
*<P>
* "VS" is part of the initial board layout from the server and its value won't change at
* start of the game. This method and {@code rescaleBoard} check for zero or changed margins because
* the board layout and margins are unknown (0) at SOCBoardPanel construction time.
*
* @return Null unless current {@link #getSize()} has changed from Visual Shift ({@code "VS"}).
* If not null, the delta change (new - old) in this panel's width and height
* @since 1.1.08
* @see SOCPlayerInterface#updateAtNewBoard()
*/
public Dimension flushBoardLayoutAndRepaint() {
Dimension ret = null;
if (board instanceof SOCBoardLarge) {
final int prevSBX = panelShiftBX, prevSBY = panelShiftBY;
final int sBX, sBY;
boolean changed = false;
int[] boardVS = ((SOCBoardLarge) board).getAddedLayoutPart("VS");
if (boardVS != null) {
sBY = (boardVS[0] * halfdeltaY) / 2;
sBX = (boardVS[1] * halfdeltaX) / 2;
} else {
sBY = 0;
sBX = 0;
}
if (sBX != prevSBX) {
if (prevSBX > 0)
panelMinBW -= prevSBX;
panelShiftBX = sBX;
changed = true;
if (sBX > 0)
panelMinBW += sBX;
}
if (sBY != prevSBY) {
if (prevSBY > 0)
panelMinBH -= prevSBY;
panelShiftBY = sBY;
changed = true;
if (sBY > 0)
panelMinBH += sBY;
}
if (changed) {
final int w = scaledPanelW, h = scaledPanelH;
rescaleBoard(w, h, true);
// If margins increased, also may have updated minSize, panelMinBW, scaledPanelH, etc.
if ((w != scaledPanelW) || (h != scaledPanelH)) {
ret = new Dimension(scaledPanelW - w, scaledPanelH - h);
super.setSize(scaledPanelW, scaledPanelH);
}
}
}
if (emptyBoardBuffer != null) {
emptyBoardBuffer.flush();
emptyBoardBuffer = null;
}
if (isScaled) {
// reset the image-scaling timeout
scaledAt = System.currentTimeMillis();
scaledMissedImage = false;
}
repaint();
return ret;
}
use of soc.game.SOCBoardLarge in project JSettlers2 by jdmonin.
the class SOCBoardPanel method drawBoardEmpty.
/**
* Draw the whole board (water, hexes, ports, numbers) but no placed pieces.
* This is drawn once, then stored.
* If the board layout changes (at start of game or
* {@link SOCBoardLarge#FOG_HEX fog hex} reveal, for example),
* call {@link #flushBoardLayoutAndRepaint()} to clear the buffered copy.
*<P>
* For scenario option {@link SOCGameOption#K_SC_CLVI _SC_CLVI},
* <tt>drawBoardEmpty</tt> draws the board's {@link SOCVillage}s.
*<P>
* If {@link #panelMarginX} or {@link #panelMarginY} != 0, do not translate {@code g}
* before calling. This method will internally translate.
*
* @param g Graphics, typically from {@link #emptyBoardBuffer}
* @since 1.1.08
* @see SOCPlayerInterface#updateAtNewBoard()
*/
private void drawBoardEmpty(Graphics g) {
// ask for antialiasing if available
if (g instanceof Graphics2D)
((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Set<Integer> landHexShow;
final int SC_6;
if (debugShowPotentials[8] && isLargeBoard) {
landHexShow = ((SOCBoardLarge) board).getLandHexCoordsSet();
SC_6 = scaleToActual(6);
} else {
// almost always null, unless debugging large board
landHexShow = null;
// unused unless debugging large board
SC_6 = 0;
}
g.setPaintMode();
g.setColor(getBackground());
g.fillRect(0, 0, scaledPanelW, scaledPanelH);
if (scaledPorts[0] == null) {
// Check if port graphics are ready. This probably isn't needed, because
// doLayout already called position/sizing methods which call rescaleBoard.
renderPortImages();
}
final boolean xlat = (panelMarginX != 0) || (panelMarginY != 0);
if (xlat)
g.translate(panelMarginX, panelMarginY);
// drawHex will set scaledMissedImage if missed.
if (!isLargeBoard) {
// Draw water hexes to all edges of the panel;
// these are outside the board coordinate system.
boolean isRowOffset = isRotated;
for (int hy = -deltaY; hy < panelMinBH; hy += deltaY, isRowOffset = !isRowOffset) {
int hx = 0;
if (isRowOffset)
hx -= halfdeltaX;
for (; hx < panelMinBW; hx += deltaX) if (0 == findHex(hx, hy))
drawHex(g, hx, hy, SOCBoard.WATER_HEX, -1, -1);
}
if (is6player)
drawPortsRing(g);
for (int i = 0; i < hexX.length; i++) if ((inactiveHexNums == null) || !inactiveHexNums[i])
drawHex(g, i);
} else {
// Large Board has a rectangular array of hexes.
// (r,c) are board coordinates.
// (x,y) are unscaled pixel coordinates.
// Top border rows:
final int bMarginX = scaleFromActual(panelMarginX), marginNumHex = (bMarginX + deltaX - 1) / deltaX;
// Top border ("row -2"): Needed only when panelMarginY is +1 or more "VS" units (1/4 or more of row height)
if (panelMarginY >= (halfdeltaY / 2)) {
final int y = -halfdeltaY - deltaY, xmin = -(deltaX * marginNumHex) - halfdeltaX;
for (int x = xmin; x < panelMinBW; x += deltaX) {
drawHex(g, x, y, SOCBoard.WATER_HEX, -1, -1);
}
}
// The initial x-coord formula aligns just enough water hexes to cover -panelMarginX.
for (int x = -(deltaX * marginNumHex); x < panelMinBW; x += deltaX) {
drawHex(g, x, -halfdeltaY, SOCBoard.WATER_HEX, -1, -1);
}
// In-bounds board hexes and bottom border:
final int bw = board.getBoardWidth(), bh = board.getBoardHeight();
for (int r = 1, y = halfdeltaY; r < bh || y < (scaledPanelH + HEXY_OFF_SLOPE_HEIGHT); r += 2, y += deltaY) {
final int rshift = (r << 8);
int c, x;
if (((r / 2) % 2) == 1) {
// odd hex rows start at 1
c = 1;
x = 0;
} else {
// top row, even rows start at 2
c = 2;
x = halfdeltaX;
}
if ((panelMarginX != 0) || (x != 0)) {
// xleft drawn at >= 0 after g.translate for panelMarginX
for (int xleft = x; xleft > -(panelMarginX + deltaX); xleft -= deltaX) drawHex(g, xleft, y, SOCBoard.WATER_HEX, -1, -1);
}
for (; c < bw; c += 2, x += deltaX) {
final int hexCoord = rshift | c;
final int hexType = (r < bh) ? board.getHexTypeFromCoord(hexCoord) : SOCBoard.WATER_HEX;
drawHex(g, x, y, hexType, -1, hexCoord);
if ((landHexShow != null) && landHexShow.contains(new Integer(hexCoord))) {
g.setColor(Color.RED);
g.drawRoundRect(scaleToActual(x + (halfdeltaX / 2)), scaleToActual(y + ((halfdeltaY + HEXY_OFF_SLOPE_HEIGHT) / 2) + 1), scaleToActual(halfdeltaX), scaleToActual(halfdeltaY + 1), SC_6, SC_6);
}
}
// If board is narrower than panel, fill in with water
int xmax = panelMinBW - 1;
if (panelMarginX < 0)
xmax -= panelMarginX;
while (x < xmax) {
final int hexCoord = rshift | c;
drawHex(g, x, y, SOCBoard.WATER_HEX, -1, hexCoord);
c += 2;
x += deltaX;
}
}
// All ports
drawPorts_LargeBoard(g);
// For scenario _SC_PIRI, check for the Pirate Path and Lone Settlement locations.
// Draw path only if the pirate fleet is still on the board
// Draw our player's permitted sea edges for ships, if restricted
{
final int[] ppath = ((SOCBoardLarge) board).getAddedLayoutPart("PP");
if ((ppath != null) && (0 != ((SOCBoardLarge) board).getPirateHex()))
drawBoardEmpty_drawPiratePath(g, ppath);
final int[] ls = ((SOCBoardLarge) board).getAddedLayoutPart("LS");
if (ls != null) {
for (int pn = 0; pn < ls.length; ++pn) if (ls[pn] != 0)
drawSettlement(g, ls[pn], pn, false, true);
}
final HashSet<Integer> lse = (player != null) ? player.getRestrictedLegalShips() : null;
if (lse != null)
drawSeaEdgeLines(g, null, lse);
}
// For scenario _SC_FTRI, draw markers at the SVP edges and dev card edges (added layout parts "CE", "VE")
if (((SOCBoardLarge) board).hasSpecialEdges())
drawBoardEmpty_specialEdges(g);
// For scenario _SC_CLVI, draw the cloth villages
HashMap<Integer, SOCVillage> villages = ((SOCBoardLarge) board).getVillages();
if (villages != null) {
Iterator<SOCVillage> villIter = villages.values().iterator();
while (villIter.hasNext()) drawVillage(g, villIter.next());
}
// For scenario _SC_WOND, draw special nodes (layout parts N1, N2, N3)
if (game.isGameOptionSet(SOCGameOption.K_SC_WOND)) {
// brown
drawBoardEmpty_specialNodes(g, "N1", new Color(180, 90, 40));
// violet
drawBoardEmpty_specialNodes(g, "N2", new Color(120, 40, 120));
drawBoardEmpty_specialNodes(g, "N3", Color.RED);
}
// check debugShowPotentials[0 - 9]
drawBoardEmpty_drawDebugShowPotentials(g);
}
if (xlat)
g.translate(-panelMarginX, -panelMarginY);
if (scaledMissedImage) {
// With recent board resize, one or more rescaled images still hasn't
// been completed after 7 seconds. We've asked for a new scaled copy
// of this image. Repaint now, and repaint 3 seconds later.
// (The delay gives time for the new scaling to complete.)
scaledAt = System.currentTimeMillis();
repaint();
new DelayedRepaint(this).start();
}
}
use of soc.game.SOCBoardLarge in project JSettlers2 by jdmonin.
the class SOCBoardPanel method setDebugShowPotentialsFlag.
/**
* Set or clear a debug flag to show player 0's potential/legal coordinate sets.
* Currently implemented only for the sea board layout ({@link SOCBoardLarge}).
* @param pieceType Piece type; 0=road, 1=settle, 2=city, 3=ship;
* Use 8 for land hexes, 9 for nodes on board. Or, -1 for all.
* See {@link #debugShowPotentials} javadoc for all values.
* @param setPotential If true, show/hide the potential set, not the legal set
* @param setOn If true, set the flag; if false, clear it
* @since 2.0.00
*/
void setDebugShowPotentialsFlag(int pieceType, final boolean setPotential, final boolean setOn) {
if (pieceType == -1) {
// all flags
Arrays.fill(debugShowPotentials, setOn);
} else {
if (setPotential && (pieceType < 4))
pieceType += 4;
if (setOn == debugShowPotentials[pieceType])
// nothing to do
return;
debugShowPotentials[pieceType] = setOn;
}
// force redraw of the empty board
scaledMissedImage = true;
// to call drawBoard, drawBoardEmpty
repaint();
if (setOn && ((pieceType == 2) || (pieceType == -1))) {
int[] vs = (board instanceof SOCBoardLarge) ? ((SOCBoardLarge) board).getAddedLayoutPart("VS") : null;
if (vs == null)
vs = new int[] { 0, 0 };
System.err.println("debugShowPotentials: Board size (height, width) = 0x" + Integer.toHexString(board.getBoardWidth()) + ",0x" + Integer.toHexString(board.getBoardHeight()) + ", VS (down, right) = " + vs[0] + "," + vs[1]);
System.err.println(" Panel size (width, height): unscaled = " + panelMinBW + "," + panelMinBH + ((isRotated) ? ", rotated" : "") + ", current = " + scaledPanelW + "," + scaledPanelH + ", margin (left, top) = " + panelMarginX + "," + panelMarginY + ", unscaled shift (right, down) = " + panelShiftBX + "," + panelShiftBY);
int w = playerInterface.getWidth(), h = playerInterface.getHeight();
Insets ins = playerInterface.getInsets();
System.err.println(" PI window size (width, height) = " + w + "," + h + ", inner = " + (w - ins.left - ins.right) + "," + (h - ins.top - ins.bottom) + ", insets (left, right, top, bottom) = " + ins.left + "," + ins.right + "," + ins.top + "," + ins.bottom);
}
}
use of soc.game.SOCBoardLarge in project JSettlers2 by jdmonin.
the class SOCBoardPanel method drawBoardEmpty_specialEdges.
/**
* For the {@link SOCGameOption#K_SC_FTRI _SC_FTRI} game scenario on {@link SOCBoardLarge},
* draw markers at all Special Edges for the players to reach and be rewarded.
*<P>
* Each marker's color will be determined by its edge's type, such as {@link SOCBoardLarge#SPECIAL_EDGE_DEV_CARD}.
* Unknown types will be drawn gray.
* @since 2.0.00
*/
private final void drawBoardEmpty_specialEdges(final Graphics g) {
Iterator<Map.Entry<Integer, Integer>> seIter = ((SOCBoardLarge) board).getSpecialEdges();
while (seIter.hasNext()) {
final Map.Entry<Integer, Integer> entry = seIter.next();
// marker color
final Color mc;
switch(entry.getValue()) {
case SOCBoardLarge.SPECIAL_EDGE_DEV_CARD:
mc = Color.YELLOW;
break;
case SOCBoardLarge.SPECIAL_EDGE_SVP:
mc = Color.GREEN;
break;
default:
mc = Color.LIGHT_GRAY;
}
final int edge = entry.getKey();
// col, row to calculate x, y
int x = edge & 0xFF, y = edge >> 8;
final boolean edgeNotVertical = ((y % 2) == 0);
x = x * halfdeltaX;
y = y * halfdeltaY + HALF_HEXHEIGHT;
// its center is slightly offset from the grid
if (edgeNotVertical)
x += (halfdeltaX / 2);
x = scaleToActual(x);
y = scaleToActual(y);
drawMarker(g, x, y, mc, -1);
}
}
Aggregations