Skip to content

Commit

Permalink
Initial implementation of board scaling
Browse files Browse the repository at this point in the history
Only properly supported by the display entity PieceHandler
  • Loading branch information
jpenilla committed Mar 16, 2023
1 parent 1334a3b commit bd5abaf
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 42 deletions.
20 changes: 15 additions & 5 deletions src/main/java/xyz/jpenilla/chesscraft/BoardManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,8 @@ public Collection<ChessBoard> activeBoards() {
return this.boards().stream().filter(ChessBoard::hasGame).toList();
}

public void createBoard(final String name, final World world, final Vec3 pos, final CardinalDirection facing) {
final ChessBoard board = new ChessBoard(this.plugin, name, pos, facing, world.getKey(), this.stockfishPath);
public void createBoard(final String name, final World world, final Vec3 pos, final CardinalDirection facing, final int scale) {
final ChessBoard board = new ChessBoard(this.plugin, name, pos, facing, scale, world.getKey(), this.stockfishPath);
this.boards.put(name, board);
this.saveBoards();
}
Expand Down Expand Up @@ -135,7 +135,15 @@ public void load() {

private void loadBoards() {
final Map<String, BoardData> read = ConfigHelper.loadConfig(new TypeToken<Map<String, BoardData>>() {}, this.file, HashMap::new);
read.forEach((key, data) -> this.boards.put(key, new ChessBoard(this.plugin, key, data.position, data.facing, data.dimension, this.stockfishPath)));
read.forEach((key, data) -> this.boards.put(key, new ChessBoard(
this.plugin,
key,
data.position,
data.facing,
data.scale,
data.dimension,
this.stockfishPath
)));
}

public void close() {
Expand All @@ -153,7 +161,7 @@ public void close() {

private void saveBoards() {
final Map<String, BoardData> collect = this.boards.values().stream()
.map(b -> Map.entry(b.name(), new BoardData(b.worldKey(), b.loc(), b.facing())))
.map(b -> Map.entry(b.name(), new BoardData(b.worldKey(), b.loc(), b.facing(), b.scale())))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
ConfigHelper.saveConfig(this.file, new TypeToken<>() {}, collect);
}
Expand Down Expand Up @@ -247,15 +255,17 @@ public static final class BoardData {
private NamespacedKey dimension = NamespacedKey.minecraft("overworld");
private Vec3 position = new Vec3(0, 0, 0);
private CardinalDirection facing = CardinalDirection.NORTH;
private int scale = 1;

@SuppressWarnings("unused")
BoardData() {
}

BoardData(final NamespacedKey dimension, final Vec3 position, final CardinalDirection facing) {
BoardData(final NamespacedKey dimension, final Vec3 position, final CardinalDirection facing, final int scale) {
this.dimension = dimension;
this.position = position;
this.facing = facing;
this.scale = scale;
}
}
}
51 changes: 37 additions & 14 deletions src/main/java/xyz/jpenilla/chesscraft/ChessBoard.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.nio.file.Path;
import java.util.Objects;
import java.util.function.Consumer;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.World;
Expand All @@ -37,6 +38,7 @@ public final class ChessBoard {
// southwest corner pos
private final Vec3 loc;
private final CardinalDirection facing;
private final int scale;
private final String name;
private final ChessCraft plugin;
private final NamespacedKey worldKey;
Expand All @@ -49,13 +51,15 @@ public ChessBoard(
final String name,
final Vec3 loc,
final CardinalDirection facing,
final int scale,
final NamespacedKey world,
final Path stockfishPath
) {
this.plugin = plugin;
this.name = name;
this.loc = loc;
this.facing = facing;
this.scale = scale;
this.worldKey = world;
this.stockfishPath = stockfishPath;
this.pieceHandler = plugin.config().pieces().createHandler();
Expand All @@ -81,15 +85,19 @@ public CardinalDirection facing() {
return this.facing;
}

public int scale() {
return this.scale;
}

public Vec3 toWorld(final BoardPosition boardPosition) {
return this.toWorld0(rotate(boardPosition, this.facing.radians()));
}

private Vec3 toWorld0(final BoardPosition boardPosition) {
return new Vec3(
this.loc.x() + boardPosition.file(),
this.loc.x() + boardPosition.file() * this.scale,
this.loc.y(),
this.loc.z() + boardPosition.rank() - 7
this.loc.z() + (boardPosition.rank() - 7) * this.scale
);
}

Expand All @@ -100,8 +108,8 @@ private BoardPosition toBoard(final int worldX, final int worldZ) {

private BoardPosition toBoard0(final int worldX, final int worldZ) {
return new BoardPosition(
7 + worldZ - this.loc.z(),
worldX - this.loc.x()
(7 * this.scale + worldZ - this.loc.z()) / this.scale,
(worldX - this.loc.x()) / this.scale
);
}

Expand Down Expand Up @@ -145,9 +153,9 @@ public boolean handleInteract(final Player player, final int x, final int y, fin
}

private boolean contains(final int x, final int y, final int z) {
return x <= this.loc.x() + 7 && x >= this.loc.x()
&& z >= this.loc.z() - 7 && z <= this.loc.z()
&& y >= this.loc.y() - 1 && y <= this.loc.y() + 1;
return x <= this.loc.x() + 7 * this.scale + this.scale - 1 && x >= this.loc.x()
&& z >= this.loc.z() - 7 * this.scale && z <= this.loc.z() + this.scale - 1
&& y >= this.loc.y() - 1 && y <= this.loc.y() + this.scale * 2 - 1;
}

public NamespacedKey worldKey() {
Expand Down Expand Up @@ -207,17 +215,32 @@ public void applyCheckerboard(
this.forEachPosition(pos -> {
final Vec3 loc = this.toWorld(pos);
final Material material = (pos.rank() * 7 + pos.file()) % 2 == 0 ? white : black;
world.setType(loc.x(), loc.y() - 1, loc.z(), material);
for (int i = 0; i < this.scale; i++) {
for (int h = 0; h < this.scale; h++) {
world.setType(loc.x() + i, loc.y() - 1, loc.z() + h, material);
}
}
});
if (border == null) {
return;
}
for (int dx = -1; dx <= 8; dx++) {
for (int dz = -1; dz <= 8; dz++) {
if (dx == -1 || dz == -1 || dx == 8 || dz == 8) {
world.setType(this.loc.x() + dx, this.loc.y() - 1, this.loc.z() - dz, border);
}
}

this.applyBorder(world, border);
}

private void applyBorder(final World world, final Material border) {
final int minX = this.loc.x() - 1;
final int maxZ = this.loc.z() + this.scale;
final int minZ = this.loc.z() - this.scale * 7 - 1;
final int maxX = this.loc.x() + this.scale * 8;

for (int x = minX; x <= maxX; x++) {
world.setType(new Location(world, x, this.loc.y() - 1, minZ), border);
world.setType(new Location(world, x, this.loc.y() - 1, maxZ), border);
}
for (int z = minZ; z <= maxZ; z++) {
world.setType(new Location(world, minX, this.loc.y() - 1, z), border);
world.setType(new Location(world, maxX, this.loc.y() - 1, z), border);
}
}

Expand Down
47 changes: 36 additions & 11 deletions src/main/java/xyz/jpenilla/chesscraft/ChessGame.java
Original file line number Diff line number Diff line change
Expand Up @@ -164,19 +164,44 @@ public void displayParticles() {
}

private void blockParticles(final Player player, final Vec3 block, final Color particleColor) {
for (double dx = 0.2; dx <= 0.8; dx += 0.2) {
for (double dz = 0.2; dz <= 0.8; dz += 0.2) {
if (dx == 0.2 || dz == 0.2 || dx == 0.8 || dz == 0.8) {
new ParticleBuilder(Particle.REDSTONE)
.count(1)
.color(particleColor)
.offset(0, 0, 0)
.location(player.getWorld(), block.x() + dx, block.y(), block.z() + dz)
.receivers(player)
.spawn();
}
// 0.02 buffer around pieces
final double min = 0.18D * this.board.scale();
final double max = 0.82D * this.board.scale();
final double minX = block.x() + min;
final double minZ = block.z() + min;
final double maxX = block.x() + max;
final double maxZ = block.z() + max;

boolean handledMaxCorner = false;
for (double x = minX; x <= maxX; x += 0.2) {
particle(player, particleColor, x, block.y(), minZ);
particle(player, particleColor, x, block.y(), maxZ);
if (x == maxX) {
handledMaxCorner = true;
}
}

// handle maximum corners if we didn't before (distance indivisible by increment)
if (!handledMaxCorner) {
particle(player, particleColor, maxX, block.y(), minZ);
particle(player, particleColor, maxX, block.y(), maxZ);
}

// skip corners this time
for (double z = minZ + 0.2; z <= maxZ - 0.2; z += 0.2) {
particle(player, particleColor, minX, block.y(), z);
particle(player, particleColor, maxX, block.y(), z);
}
}

private static void particle(final Player player, final Color particleColor, final double x, final double y, final double z) {
new ParticleBuilder(Particle.REDSTONE)
.count(1)
.color(particleColor)
.offset(0, 0, 0)
.location(player.getWorld(), x, y, z)
.receivers(player)
.spawn();
}

@Override
Expand Down
22 changes: 11 additions & 11 deletions src/main/java/xyz/jpenilla/chesscraft/PieceHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -63,34 +63,34 @@ public DisplayEntity(final PieceOptions.DisplayEntity options) {
public void applyToWorld(final ChessBoard board, final BoardStateHolder game, final World world) {
board.forEachPosition(boardPosition -> {
final Vec3 pos = board.toWorld(boardPosition);
removePieceAt(world, pos);
removePieceAt(world, board, pos);
final Piece piece = game.piece(boardPosition);

if (piece == null) {
return;
}
world.spawn(pos.toLocation(world), ItemDisplay.class, itemDisplay -> {
itemDisplay.setTransformation(new Transformation(
// center on block
new Vector3f(0.5f, 0, 0.5f),
// center
new Vector3f(0.5f * board.scale(), 0, 0.5f * board.scale()),
// flip upwards
new AxisAngle4f((float) Math.toRadians(90.0D), 1, 0, 0),
// scale
new Vector3f(0.5f),
// piece rotation
new Vector3f(0.5f * board.scale()),
// rotate
new AxisAngle4f((float) Math.toRadians(rotation(board.facing(), piece)), 0, 0, 1)
));
itemDisplay.setItemDisplayTransform(ItemDisplay.ItemDisplayTransform.FIXED);
itemDisplay.setItemStack(this.options.item(piece));
itemDisplay.setInvulnerable(true);
itemDisplay.getPersistentDataContainer().set(BoardManager.PIECE_KEY, PersistentDataType.STRING, board.name());
});
world.spawn(new Location(world, pos.x() + 0.5, pos.y(), pos.z() + 0.5), Interaction.class, interaction -> {
world.spawn(new Location(world, pos.x() + 0.5 * board.scale(), pos.y(), pos.z() + 0.5 * board.scale()), Interaction.class, interaction -> {
interaction.setInvulnerable(true);
interaction.getPersistentDataContainer().set(BoardManager.PIECE_KEY, PersistentDataType.STRING, board.name());
interaction.setResponsive(true);
interaction.setInteractionHeight((float) this.options.height(piece.type()));
interaction.setInteractionWidth(0.5f);
interaction.setInteractionHeight((float) this.options.height(piece.type()) * board.scale());
interaction.setInteractionWidth(0.5f * board.scale());
});
});
}
Expand All @@ -105,10 +105,10 @@ private static float rotation(final CardinalDirection facing, final Piece piece)

@Override
public void removeFromWorld(final ChessBoard board, final World world) {
board.forEachPosition(pos -> removePieceAt(world, board.toWorld(pos)));
board.forEachPosition(pos -> removePieceAt(world, board, board.toWorld(pos)));
}

private static void removePieceAt(final World world, final Vec3 pos) {
private static void removePieceAt(final World world, final ChessBoard board, final Vec3 pos) {
final List<Entity> entities = new ArrayList<>();
entities.addAll(world.getNearbyEntities(
pos.toLocation(world),
Expand All @@ -118,7 +118,7 @@ private static void removePieceAt(final World world, final Vec3 pos) {
e -> e instanceof Display
));
entities.addAll(world.getNearbyEntities(
new Location(world, pos.x() + 0.5, pos.y(), pos.z() + 0.5),
new Location(world, pos.x() + 0.5 * board.scale(), pos.y(), pos.z() + 0.5 * board.scale()),
0.25,
0.5,
0.25,
Expand Down
4 changes: 3 additions & 1 deletion src/main/java/xyz/jpenilla/chesscraft/command/Commands.java
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ public void register() {
this.mgr.command(chess.literal("create_board")
.argument(StringArgument.single("name"))
.argument(EnumArgument.of(CardinalDirection.class, "facing"))
.argument(IntegerArgument.optional("scale", 1))
.senderType(Player.class)
.permission("chesscraft.command.create_board")
.handler(this::createBoard));
Expand Down Expand Up @@ -207,7 +208,8 @@ private void createBoard(final CommandContext<CommandSender> ctx) {
name,
sender.getWorld(),
Vec3.fromLocation(sender.getLocation()),
ctx.get("facing")
ctx.get("facing"),
ctx.get("scale")
);
sender.sendMessage(this.messages().boardCreated(name));
}
Expand Down

0 comments on commit bd5abaf

Please sign in to comment.