package me.desht.chesscraft.chess.pieces; import chesspresso.Chess; import me.desht.chesscraft.enums.BoardRotation; import me.desht.dhutils.Debugger; import me.desht.dhutils.block.BlockType; import me.desht.dhutils.block.MassBlockUpdate; import me.desht.dhutils.block.MaterialWithData; import me.desht.dhutils.cuboid.Cuboid; import org.bukkit.Location; import org.bukkit.World; import org.bukkit.block.Block; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; public class BlockChessStone extends ChessStone { private final MaterialWithData[][][] pieceArray; /** * Instantiate a new chess stone * * @param stone the numeric Chesspresso stone ID * @param tmpl the piece template * @param matMap the material map * @param direction the board orientation */ public BlockChessStone(int stone, ChessPieceTemplate tmpl, MaterialMap matMap, BoardRotation direction) { super(stone); int rotation = rotationNeeded(direction, Chess.stoneToColor(stone)); int tmplX = tmpl.getSizeX(); int tmplY = tmpl.getSizeY(); int tmplZ = tmpl.getSizeZ(); if (rotation == 90 || rotation == 270) { // allows for pieces with a non-square footprint setSize(tmplZ, tmplY, tmplX); } else { setSize(tmplX, tmplY, tmplZ); } Debugger.getInstance().debug(3, "ChessStone: tmpl size = " + tmplX + "," + tmplY + "," + tmplZ + ", stone size = " + getSizeX() + "," + getSizeY() + "," + getSizeZ()); pieceArray = new MaterialWithData[getSizeX()][getSizeY()][getSizeZ()]; int sx = getSizeX(); int sz = getSizeZ(); switch (rotation) { case 0: for (int x = 0; x < tmplX; ++x) { for (int y = 0; y < tmplY; ++y) { for (int z = 0; z < tmplZ; ++z) { pieceArray[x][y][z] = matMap.get(tmpl.get(x, y, z)); } } } break; case 90: for (int x = 0; x < tmplX; ++x) { for (int y = 0; y < tmplY; ++y) { for (int z = 0; z < tmplZ; ++z) { pieceArray[sx - z - 1][y][x] = matMap.get(tmpl.get(x, y, z)).rotate(90); } } } break; case 180: for (int x = 0; x < tmplX; ++x) { for (int y = 0; y < tmplY; ++y) { for (int z = 0; z < tmplZ; ++z) { pieceArray[sx - x - 1][y][sz - z - 1] = matMap.get(tmpl.get(x, y, z)).rotate(180); } } } break; case 270: for (int x = 0; x < tmplX; ++x) { for (int y = 0; y < tmplY; ++y) { for (int z = 0; z < tmplZ; ++z) { pieceArray[z][y][sz - x - 1] = matMap.get(tmpl.get(x, y, z)).rotate(270); } } } break; default: throw new IllegalArgumentException("rotation must be 0, 90, 180 or 270"); } Debugger.getInstance().debug(2, "ChessStone: instantiated stone " + stone + ", rotation " + rotation); } @Override public void paint(Cuboid region, MassBlockUpdate mbu) { assert region.getSizeX() >= getSizeX(); assert region.getSizeZ() >= getSizeZ(); int xOff = (region.getSizeX() - getSizeX()) / 2; int zOff = (region.getSizeZ() - getSizeZ()) / 2; Map<Block,MaterialWithData> deferred = new HashMap<Block, MaterialWithData>(); World world = region.getWorld(); for (int x = 0; x < getSizeX(); x++) { for (int y = 0; y < getSizeY(); y++) { for (int z = 0; z < getSizeZ(); z++) { MaterialWithData mat = pieceArray[x][y][z]; if (mat.getId() == 0) { // we expect that the region was pre-cleared, skip placing air a second time continue; } Block b = region.getRelativeBlock(world, x + xOff, y, z + zOff); if (BlockType.shouldPlaceLast(mat.getId())) { deferred.put(b, mat); } else { mat.applyToBlock(b, mbu); } } } } for (Entry<Block,MaterialWithData> e : deferred.entrySet()) { e.getValue().applyToBlock(e.getKey(), mbu); } } @Override public void move(int fromSqi, int toSqi, Location to, ChessStone captured) { // no-op for block sets; they're not animated // System.out.println("moveTo: " + fromSqi + " -> " + toSqi + " to loc = " + to); } private int rotationNeeded(BoardRotation direction, int colour) { int rot; switch (direction) { case NORTH: rot = 0; break; case EAST: rot = 90; break; case SOUTH: rot = 180; break; case WEST: rot = 270; break; default: rot = 0; break; } if (colour == Chess.BLACK){ rot = (rot + 180) % 360; } return rot; } }