replaced BlockPlacementHelper in BuildBattle with blocks-and-stuff placement rules
This commit is contained in:
1 parent
7424d6b929
commit
331efa9ffd
4 files changed
+91
-899
No files matched your search
@@ -11,6 +11,7 @@ version '1.0-SNAPSHOT'
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven { url = 'https://mvn.everbuild.org/public' }
|
||||
}
|
||||
|
||||
java {
|
||||
@@ -38,6 +39,9 @@ dependencies {
|
||||
|
||||
//PvP
|
||||
implementation 'io.github.togar2:MinestomPvP:2026.05.30-26.1.1'
|
||||
|
||||
//Block placement
|
||||
implementation 'org.everbuild.blocksandstuff:blocksandstuff-blocks:1.10.2-SNAPSHOT'
|
||||
}
|
||||
|
||||
tasks {
|
||||
|
||||
-896
@@ -1,896 +0,0 @@
|
||||
package eu.mhsl.minenet.minigames.instance.game.stateless.types.buildBattle;
|
||||
|
||||
import net.minestom.server.coordinate.BlockVec;
|
||||
import net.minestom.server.coordinate.Point;
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.event.player.PlayerBlockBreakEvent;
|
||||
import net.minestom.server.event.player.PlayerBlockInteractEvent;
|
||||
import net.minestom.server.event.player.PlayerBlockPlaceEvent;
|
||||
import net.minestom.server.instance.Instance;
|
||||
import net.minestom.server.instance.block.Block;
|
||||
import net.minestom.server.instance.block.BlockFace;
|
||||
import net.minestom.server.utils.Direction;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public final class BlockPlacementHelper {
|
||||
private BlockPlacementHelper() {}
|
||||
|
||||
private static final Set<String> SIX_DIR = Set.of(
|
||||
"observer", "dispenser", "dropper", "piston", "sticky_piston",
|
||||
"amethyst_cluster", "small_amethyst_bud", "medium_amethyst_bud", "large_amethyst_bud",
|
||||
"end_rod", "lightning_rod", "shulker_box"
|
||||
);
|
||||
|
||||
public static void apply(PlayerBlockPlaceEvent event) {
|
||||
Block block = event.getBlock();
|
||||
BlockFace face = event.getBlockFace();
|
||||
BlockVec pos = event.getBlockPosition();
|
||||
Point cursor = event.getCursorPosition();
|
||||
Player player = event.getPlayer();
|
||||
Instance instance = event.getInstance();
|
||||
|
||||
String path = block.key().value();
|
||||
|
||||
Block existing = instance.getBlock(pos);
|
||||
if ((path.endsWith("_candle") || path.equals("candle")) && existing.compare(block)) {
|
||||
int n = parseIntOr(existing.getProperty("candles"), 1);
|
||||
event.setBlock(n < 4 ? existing.withProperty("candles", String.valueOf(n + 1)) : existing);
|
||||
return;
|
||||
}
|
||||
if (path.equals("snow") && existing.compare(block)) {
|
||||
int n = parseIntOr(existing.getProperty("layers"), 1);
|
||||
event.setBlock(n < 8 ? existing.withProperty("layers", String.valueOf(n + 1)) : existing);
|
||||
return;
|
||||
}
|
||||
if (path.equals("sea_pickle") && existing.compare(block)) {
|
||||
int n = parseIntOr(existing.getProperty("pickles"), 1);
|
||||
event.setBlock(n < 4 ? existing.withProperty("pickles", String.valueOf(n + 1)) : existing);
|
||||
return;
|
||||
}
|
||||
if (path.equals("turtle_egg") && existing.compare(block)) {
|
||||
int n = parseIntOr(existing.getProperty("eggs"), 1);
|
||||
event.setBlock(n < 4 ? existing.withProperty("eggs", String.valueOf(n + 1)) : existing);
|
||||
return;
|
||||
}
|
||||
|
||||
Block oriented = orient(block, path, face, cursor, player, instance, pos);
|
||||
if (oriented != block) event.setBlock(oriented);
|
||||
|
||||
Block finalOriented = oriented;
|
||||
String finalPath = finalOriented.key().value();
|
||||
|
||||
if (path.endsWith("_door")) {
|
||||
Block lower = event.getBlock();
|
||||
String facing = lower.getProperty("facing");
|
||||
String hinge = lower.getProperty("hinge");
|
||||
Block upper = lower.withProperty("half", "upper").withProperty("facing", facing).withProperty("hinge", hinge);
|
||||
instance.scheduler().scheduleNextTick(() -> instance.setBlock(pos.add(0, 1, 0), upper));
|
||||
}
|
||||
|
||||
if (path.endsWith("_bed")) {
|
||||
String facing = finalOriented.getProperty("facing");
|
||||
Direction d = facingToDirection(facing);
|
||||
Block head = finalOriented.withProperty("part", "head");
|
||||
BlockVec headPos = new BlockVec(pos.blockX() + d.normalX(), pos.blockY(), pos.blockZ() + d.normalZ());
|
||||
instance.scheduler().scheduleNextTick(() -> instance.setBlock(headPos, head));
|
||||
}
|
||||
|
||||
if (path.equals("big_dripleaf")) {
|
||||
Block upper = finalOriented;
|
||||
Block lower = Block.BIG_DRIPLEAF_STEM.withProperty("facing", finalOriented.getProperty("facing"));
|
||||
instance.scheduler().scheduleNextTick(() -> instance.setBlock(pos.add(0, 1, 0), upper.withProperty("half", "upper")));
|
||||
}
|
||||
|
||||
if (isConnecting(path)) {
|
||||
instance.scheduler().scheduleNextTick(() -> {
|
||||
for (Direction d : Direction.HORIZONTAL) {
|
||||
BlockVec np = new BlockVec(pos.blockX() + d.normalX(), pos.blockY(), pos.blockZ() + d.normalZ());
|
||||
Block nb = instance.getBlock(np);
|
||||
if (isConnecting(nb.key().value())) instance.setBlock(np, computeConnections(nb, nb.key().value(), instance, np));
|
||||
}
|
||||
Block self = instance.getBlock(pos);
|
||||
if (isConnecting(self.key().value())) instance.setBlock(pos, computeConnections(self, self.key().value(), instance, pos));
|
||||
for (Direction d : Direction.HORIZONTAL) {
|
||||
BlockVec np = new BlockVec(pos.blockX() + d.normalX(), pos.blockY(), pos.blockZ() + d.normalZ());
|
||||
Block nb = instance.getBlock(np);
|
||||
if (nb.key().value().endsWith("_fence_gate")) {
|
||||
instance.setBlock(np, updateFenceGateInWall(nb, instance, np));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (path.endsWith("_fence_gate")) {
|
||||
instance.scheduler().scheduleNextTick(() -> instance.setBlock(pos, updateFenceGateInWall(instance.getBlock(pos), instance, pos)));
|
||||
}
|
||||
|
||||
if (path.equals("redstone_wire")) {
|
||||
instance.scheduler().scheduleNextTick(() -> {
|
||||
updateRedstoneWire(instance, pos);
|
||||
for (Direction d : Direction.HORIZONTAL) {
|
||||
BlockVec np = new BlockVec(pos.blockX() + d.normalX(), pos.blockY(), pos.blockZ() + d.normalZ());
|
||||
if (instance.getBlock(np).key().value().equals("redstone_wire")) updateRedstoneWire(instance, np);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (isRail(path)) {
|
||||
instance.scheduler().scheduleNextTick(() -> updateRailShape(instance, pos));
|
||||
}
|
||||
|
||||
if (path.equals("scaffolding")) {
|
||||
instance.scheduler().scheduleNextTick(() -> updateScaffolding(instance, pos));
|
||||
}
|
||||
|
||||
if (finalPath.equals("chest") || finalPath.equals("trapped_chest")) {
|
||||
instance.scheduler().scheduleNextTick(() -> updateChestPair(instance, pos));
|
||||
}
|
||||
}
|
||||
|
||||
private static Block orient(Block block, String path, BlockFace face, Point cursor, Player player,
|
||||
Instance instance, BlockVec pos) {
|
||||
Map<String, String> props = block.properties();
|
||||
Block result = block;
|
||||
|
||||
if (props.containsKey("axis")) {
|
||||
result = result.withProperty("axis", switch (face) {
|
||||
case TOP, BOTTOM -> "y";
|
||||
case NORTH, SOUTH -> "z";
|
||||
case EAST, WEST -> "x";
|
||||
});
|
||||
}
|
||||
|
||||
if (props.containsKey("type") && path.endsWith("_slab")) {
|
||||
Block existing = instance.getBlock(pos);
|
||||
if (existing.compare(block)) {
|
||||
result = result.withProperty("type", "double");
|
||||
} else {
|
||||
boolean top = face == BlockFace.BOTTOM || (face != BlockFace.TOP && cursor.y() > 0.5);
|
||||
result = result.withProperty("type", top ? "top" : "bottom");
|
||||
}
|
||||
}
|
||||
|
||||
if (path.endsWith("_stairs")) {
|
||||
String facing = yawToFacing(player.getPosition().yaw());
|
||||
boolean top = face == BlockFace.BOTTOM || (face != BlockFace.TOP && cursor.y() > 0.5);
|
||||
result = result.withProperty("facing", facing).withProperty("half", top ? "top" : "bottom");
|
||||
result = applyStairShape(result, instance, pos, facing, top);
|
||||
}
|
||||
|
||||
if (path.endsWith("_trapdoor")) {
|
||||
String facing;
|
||||
boolean top;
|
||||
if (face == BlockFace.TOP) { top = false; facing = yawToFacing(player.getPosition().yaw() + 180); }
|
||||
else if (face == BlockFace.BOTTOM) { top = true; facing = yawToFacing(player.getPosition().yaw() + 180); }
|
||||
else { top = cursor.y() > 0.5; facing = oppositeFacing(faceName(face)); }
|
||||
result = result.withProperty("facing", facing).withProperty("half", top ? "top" : "bottom")
|
||||
.withProperty("open", "false").withProperty("powered", "false");
|
||||
}
|
||||
|
||||
if (path.endsWith("_door")) {
|
||||
String facing = yawToFacing(player.getPosition().yaw());
|
||||
String hinge = doorHinge(facing, cursor, instance, pos, path);
|
||||
result = result.withProperty("facing", facing)
|
||||
.withProperty("half", "lower")
|
||||
.withProperty("hinge", hinge)
|
||||
.withProperty("open", "false")
|
||||
.withProperty("powered", "false");
|
||||
}
|
||||
|
||||
if (path.endsWith("_fence_gate")) {
|
||||
String facing = yawToFacing(player.getPosition().yaw());
|
||||
result = result.withProperty("facing", facing).withProperty("open", "false")
|
||||
.withProperty("powered", "false").withProperty("in_wall", "false");
|
||||
}
|
||||
|
||||
if (path.endsWith("_bed")) {
|
||||
String facing = yawToFacing(player.getPosition().yaw());
|
||||
result = result.withProperty("facing", facing).withProperty("part", "foot").withProperty("occupied", "false");
|
||||
}
|
||||
|
||||
if (path.endsWith("_button") || path.equals("lever") || path.equals("grindstone")) {
|
||||
String attachFace; String facing;
|
||||
if (face == BlockFace.TOP) { attachFace = "floor"; facing = yawToFacing(player.getPosition().yaw()); }
|
||||
else if (face == BlockFace.BOTTOM) { attachFace = "ceiling"; facing = yawToFacing(player.getPosition().yaw()); }
|
||||
else { attachFace = "wall"; facing = oppositeFacing(faceName(face)); }
|
||||
result = result.withProperty("face", attachFace).withProperty("facing", facing);
|
||||
}
|
||||
|
||||
if (path.equals("bell")) {
|
||||
String attachment; String facing;
|
||||
if (face == BlockFace.TOP) { attachment = "floor"; facing = yawToFacing(player.getPosition().yaw()); }
|
||||
else if (face == BlockFace.BOTTOM) { attachment = "ceiling"; facing = yawToFacing(player.getPosition().yaw()); }
|
||||
else {
|
||||
attachment = "single_wall";
|
||||
facing = oppositeFacing(faceName(face));
|
||||
}
|
||||
result = result.withProperty("attachment", attachment).withProperty("facing", facing);
|
||||
}
|
||||
|
||||
if (path.equals("lantern") || path.equals("soul_lantern")) {
|
||||
result = result.withProperty("hanging", face == BlockFace.BOTTOM ? "true" : "false");
|
||||
}
|
||||
|
||||
if (path.equals("tripwire_hook")) {
|
||||
String facing = face != BlockFace.TOP && face != BlockFace.BOTTOM
|
||||
? oppositeFacing(faceName(face))
|
||||
: yawToFacing(player.getPosition().yaw());
|
||||
result = result.withProperty("facing", facing).withProperty("attached", "false").withProperty("powered", "false");
|
||||
}
|
||||
|
||||
if (path.equals("hopper")) {
|
||||
String facing = face == BlockFace.TOP ? "down" : (face == BlockFace.BOTTOM ? "down" : oppositeFacing(faceName(face)));
|
||||
result = result.withProperty("facing", facing).withProperty("enabled", "true");
|
||||
}
|
||||
|
||||
if (path.equals("campfire") || path.equals("soul_campfire")) {
|
||||
Block below = instance.getBlock(new BlockVec(pos.blockX(), pos.blockY() - 1, pos.blockZ()));
|
||||
String signalFire = below.key().value().equals("hay_block") ? "true" : "false";
|
||||
result = result.withProperty("facing", yawToFacing(player.getPosition().yaw()))
|
||||
.withProperty("lit", "true").withProperty("signal_fire", signalFire);
|
||||
}
|
||||
|
||||
if (path.equals("pointed_dripstone")) {
|
||||
String dir = face == BlockFace.BOTTOM ? "down" : "up";
|
||||
result = result.withProperty("vertical_direction", dir).withProperty("thickness", "tip");
|
||||
}
|
||||
|
||||
if (path.equals("chorus_flower")) {
|
||||
result = result.withProperty("age", "0");
|
||||
}
|
||||
|
||||
if (path.equals("end_portal_frame") || path.equals("respawn_anchor")) {
|
||||
if (props.containsKey("facing")) {
|
||||
result = result.withProperty("facing", yawToFacing(player.getPosition().yaw()));
|
||||
}
|
||||
if (props.containsKey("eye")) result = result.withProperty("eye", "false");
|
||||
}
|
||||
|
||||
if ((path.equals("torch") || path.equals("soul_torch") || path.equals("redstone_torch") || path.equals("copper_torch"))
|
||||
&& face != BlockFace.TOP && face != BlockFace.BOTTOM) {
|
||||
Block wall = switch (path) {
|
||||
case "torch" -> Block.WALL_TORCH;
|
||||
case "soul_torch" -> Block.SOUL_WALL_TORCH;
|
||||
case "redstone_torch" -> Block.REDSTONE_WALL_TORCH;
|
||||
case "copper_torch" -> Block.COPPER_WALL_TORCH;
|
||||
default -> null;
|
||||
};
|
||||
if (wall != null) result = wall.withProperty("facing", oppositeFacing(faceName(face)));
|
||||
}
|
||||
|
||||
if (path.endsWith("_skull") || path.endsWith("_head")) {
|
||||
if (face != BlockFace.TOP && face != BlockFace.BOTTOM) {
|
||||
String wallName = path.endsWith("_skull") ? path.replace("_skull", "_wall_skull") : path.replace("_head", "_wall_head");
|
||||
Block wall = Block.fromKey("minecraft:" + wallName);
|
||||
if (wall != null) result = wall.withProperty("facing", oppositeFacing(faceName(face)));
|
||||
} else if (face == BlockFace.TOP && result.properties().containsKey("rotation")) {
|
||||
int rot = (int) Math.floor(((player.getPosition().yaw() + 180.0) * 16.0 / 360.0) + 0.5) & 15;
|
||||
result = result.withProperty("rotation", String.valueOf(rot));
|
||||
}
|
||||
}
|
||||
|
||||
if (path.endsWith("_sign") && !path.endsWith("_wall_sign") && !path.contains("hanging")
|
||||
&& face != BlockFace.TOP && face != BlockFace.BOTTOM) {
|
||||
Block wallSign = Block.fromKey("minecraft:" + path.replace("_sign", "_wall_sign"));
|
||||
if (wallSign != null) result = wallSign.withProperty("facing", oppositeFacing(faceName(face)));
|
||||
} else if (path.endsWith("_sign") && !path.endsWith("_wall_sign") && !path.contains("hanging")
|
||||
&& face == BlockFace.TOP) {
|
||||
int rot = (int) Math.floor(((player.getPosition().yaw() + 180.0) * 16.0 / 360.0) + 0.5) & 15;
|
||||
if (result.properties().containsKey("rotation")) result = result.withProperty("rotation", String.valueOf(rot));
|
||||
}
|
||||
|
||||
if (path.endsWith("_hanging_sign") && !path.contains("_wall_")
|
||||
&& face != BlockFace.TOP && face != BlockFace.BOTTOM) {
|
||||
Block wallHang = Block.fromKey("minecraft:" + path.replace("_hanging_sign", "_wall_hanging_sign"));
|
||||
if (wallHang != null) result = wallHang.withProperty("facing", oppositeFacing(faceName(face)));
|
||||
} else if (path.endsWith("_hanging_sign") && !path.contains("_wall_")) {
|
||||
int rot = (int) Math.floor(((player.getPosition().yaw() + 180.0) * 16.0 / 360.0) + 0.5) & 15;
|
||||
if (result.properties().containsKey("rotation")) result = result.withProperty("rotation", String.valueOf(rot));
|
||||
if (result.properties().containsKey("attached")) result = result.withProperty("attached", face == BlockFace.BOTTOM ? "true" : "false");
|
||||
}
|
||||
|
||||
if (isBanner(path)) {
|
||||
if (face != BlockFace.TOP && face != BlockFace.BOTTOM) {
|
||||
Block wallBanner = Block.fromKey("minecraft:" + path.replace("_banner", "_wall_banner"));
|
||||
if (wallBanner != null) result = wallBanner.withProperty("facing", oppositeFacing(faceName(face)));
|
||||
} else if (face == BlockFace.TOP) {
|
||||
int rot = (int) Math.floor(((player.getPosition().yaw() + 180.0) * 16.0 / 360.0) + 0.5) & 15;
|
||||
if (result.properties().containsKey("rotation")) result = result.withProperty("rotation", String.valueOf(rot));
|
||||
}
|
||||
}
|
||||
|
||||
if (path.equals("vine")) {
|
||||
Block existing = instance.getBlock(pos);
|
||||
Block base = existing.compare(block) ? existing : result.withProperty("up", "false")
|
||||
.withProperty("north", "false").withProperty("south", "false")
|
||||
.withProperty("east", "false").withProperty("west", "false");
|
||||
String side = switch (face) {
|
||||
case BOTTOM -> "up";
|
||||
case NORTH -> "south";
|
||||
case SOUTH -> "north";
|
||||
case EAST -> "west";
|
||||
case WEST -> "east";
|
||||
default -> null;
|
||||
};
|
||||
result = side != null ? base.withProperty(side, "true") : base;
|
||||
}
|
||||
|
||||
if (path.equals("glow_lichen") || path.equals("sculk_vein") || path.equals("resin_clump")) {
|
||||
Block existing = instance.getBlock(pos);
|
||||
Block base = existing.compare(block) ? existing : result
|
||||
.withProperty("up", "false").withProperty("down", "false")
|
||||
.withProperty("north", "false").withProperty("south", "false")
|
||||
.withProperty("east", "false").withProperty("west", "false");
|
||||
String side = switch (face) {
|
||||
case TOP -> "down";
|
||||
case BOTTOM -> "up";
|
||||
case NORTH -> "south";
|
||||
case SOUTH -> "north";
|
||||
case EAST -> "west";
|
||||
case WEST -> "east";
|
||||
};
|
||||
result = base.withProperty(side, "true");
|
||||
}
|
||||
|
||||
if (path.equals("red_mushroom_block") || path.equals("brown_mushroom_block") || path.equals("mushroom_stem")) {
|
||||
result = result.withProperty("up", "true").withProperty("down", "true")
|
||||
.withProperty("north", "true").withProperty("south", "true")
|
||||
.withProperty("east", "true").withProperty("west", "true");
|
||||
String hiddenFace = faceName(face);
|
||||
if (result.properties().containsKey(hiddenFace)) result = result.withProperty(hiddenFace, "false");
|
||||
}
|
||||
|
||||
if (props.containsKey("facing") && !path.endsWith("_stairs") && !path.endsWith("_door")
|
||||
&& !path.endsWith("_trapdoor") && !path.endsWith("_fence_gate") && !path.endsWith("_button")
|
||||
&& !path.equals("lever") && !path.equals("grindstone") && !path.equals("bell")
|
||||
&& !path.equals("hopper") && !path.equals("campfire") && !path.equals("soul_campfire")
|
||||
&& !path.equals("tripwire_hook")
|
||||
&& !path.endsWith("wall_torch") && !path.endsWith("_bed") && !path.endsWith("_sign")
|
||||
&& !path.endsWith("_hanging_sign") && !path.endsWith("_banner") && !path.endsWith("_wall_banner")
|
||||
&& !path.endsWith("_skull") && !path.endsWith("_head")
|
||||
&& !path.equals("end_portal_frame") && !path.equals("respawn_anchor")) {
|
||||
Direction fdir = faceDirection(face);
|
||||
String facing;
|
||||
if (fdir != null && SIX_DIR.contains(path)) {
|
||||
facing = fdir.opposite().name().toLowerCase();
|
||||
} else if (path.equals("repeater") || path.equals("comparator")) {
|
||||
facing = oppositeFacing(yawToFacing(player.getPosition().yaw()));
|
||||
} else {
|
||||
facing = yawToFacing(player.getPosition().yaw());
|
||||
}
|
||||
try { result = result.withProperty("facing", facing); } catch (Exception ignored) {}
|
||||
}
|
||||
|
||||
if (isConnecting(path)) result = computeConnections(result, path, instance, pos);
|
||||
|
||||
if (props.containsKey("waterlogged") && Block.WATER.compare(instance.getBlock(pos))) {
|
||||
try { result = result.withProperty("waterlogged", "true"); } catch (Exception ignored) {}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static boolean isBanner(String path) {
|
||||
return path.endsWith("_banner") && !path.endsWith("_wall_banner");
|
||||
}
|
||||
|
||||
private static Block applyStairShape(Block stair, Instance instance, BlockVec pos, String facing, boolean top) {
|
||||
Direction f = facingToDirection(facing);
|
||||
Block front = instance.getBlock(new BlockVec(pos.blockX() + f.normalX(), pos.blockY(), pos.blockZ() + f.normalZ()));
|
||||
if (front.key().value().endsWith("_stairs") && top == isTopStair(front)) {
|
||||
Direction frontFacing = facingToDirection(front.getProperty("facing"));
|
||||
if (frontFacing != f && frontFacing != f.opposite()) {
|
||||
if (frontFacing == rotateCW(f)) return stair.withProperty("shape", "outer_right");
|
||||
else return stair.withProperty("shape", "outer_left");
|
||||
}
|
||||
}
|
||||
Block back = instance.getBlock(new BlockVec(pos.blockX() - f.normalX(), pos.blockY(), pos.blockZ() - f.normalZ()));
|
||||
if (back.key().value().endsWith("_stairs") && top == isTopStair(back)) {
|
||||
Direction backFacing = facingToDirection(back.getProperty("facing"));
|
||||
if (backFacing != f && backFacing != f.opposite()) {
|
||||
if (backFacing == rotateCW(f)) return stair.withProperty("shape", "inner_right");
|
||||
else return stair.withProperty("shape", "inner_left");
|
||||
}
|
||||
}
|
||||
return stair.withProperty("shape", "straight");
|
||||
}
|
||||
|
||||
private static boolean isTopStair(Block b) { return "top".equals(b.getProperty("half")); }
|
||||
|
||||
private static Block computeConnections(Block block, String path, Instance instance, BlockVec pos) {
|
||||
boolean isWall = path.endsWith("_wall") && !path.endsWith("head_wall") && !path.endsWith("_wall_sign") && !path.endsWith("_wall_banner");
|
||||
if (path.endsWith("_fence_gate")) return block;
|
||||
|
||||
Block result = block;
|
||||
for (Direction d : Direction.HORIZONTAL) {
|
||||
BlockVec np = new BlockVec(pos.blockX() + d.normalX(), pos.blockY(), pos.blockZ() + d.normalZ());
|
||||
Block nb = instance.getBlock(np);
|
||||
boolean connect = canConnectTo(nb, path, d);
|
||||
String propName = d.name().toLowerCase();
|
||||
if (isWall) {
|
||||
boolean tall = connect && isSolidAbove(instance, pos);
|
||||
result = result.withProperty(propName, connect ? (tall ? "tall" : "low") : "none");
|
||||
} else {
|
||||
result = result.withProperty(propName, connect ? "true" : "false");
|
||||
}
|
||||
}
|
||||
if (isWall && result.properties().containsKey("up")) {
|
||||
boolean up = computeWallUp(result, instance, pos);
|
||||
result = result.withProperty("up", up ? "true" : "false");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static boolean isSolidAbove(Instance instance, BlockVec pos) {
|
||||
Block above = instance.getBlock(new BlockVec(pos.blockX(), pos.blockY() + 1, pos.blockZ()));
|
||||
return above.isSolid();
|
||||
}
|
||||
|
||||
private static boolean computeWallUp(Block wall, Instance instance, BlockVec pos) {
|
||||
boolean n = !"none".equals(wall.getProperty("north"));
|
||||
boolean s = !"none".equals(wall.getProperty("south"));
|
||||
boolean e = !"none".equals(wall.getProperty("east"));
|
||||
boolean w = !"none".equals(wall.getProperty("west"));
|
||||
boolean straight = (n && s && !e && !w) || (!n && !s && e && w);
|
||||
if (!straight) return true;
|
||||
return isSolidAbove(instance, pos);
|
||||
}
|
||||
|
||||
private static boolean canConnectTo(Block neighbor, String selfPath, Direction toward) {
|
||||
if (neighbor.isAir()) return false;
|
||||
String np = neighbor.key().value();
|
||||
if (np.endsWith("_fence_gate")) {
|
||||
String facing = neighbor.getProperty("facing");
|
||||
if (facing != null) {
|
||||
Direction f = facingToDirection(facing);
|
||||
return toward != f && toward != f.opposite();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (selfPath.endsWith("_fence") && np.endsWith("_fence")) {
|
||||
boolean selfNether = selfPath.contains("nether_brick");
|
||||
boolean nNether = np.contains("nether_brick");
|
||||
return selfNether == nNether;
|
||||
}
|
||||
if (selfPath.endsWith("_wall") && np.endsWith("_wall")) return true;
|
||||
if ((selfPath.equals("glass_pane") || selfPath.endsWith("_stained_glass_pane") || selfPath.equals("iron_bars"))
|
||||
&& (np.equals("glass_pane") || np.endsWith("_stained_glass_pane") || np.equals("iron_bars"))) return true;
|
||||
return neighbor.isSolid();
|
||||
}
|
||||
|
||||
private static boolean isConnecting(String path) {
|
||||
return path.endsWith("_fence") || (path.endsWith("_wall") && !path.endsWith("head_wall")
|
||||
&& !path.endsWith("_wall_sign") && !path.endsWith("_wall_banner") && !path.endsWith("_wall_torch")
|
||||
&& !path.endsWith("_wall_skull") && !path.endsWith("_wall_head") && !path.endsWith("_wall_hanging_sign"))
|
||||
|| path.equals("iron_bars") || path.equals("glass_pane") || path.endsWith("_stained_glass_pane");
|
||||
}
|
||||
|
||||
private static Block updateFenceGateInWall(Block gate, Instance instance, BlockVec pos) {
|
||||
if (!gate.key().value().endsWith("_fence_gate")) return gate;
|
||||
String facing = gate.getProperty("facing");
|
||||
if (facing == null) return gate;
|
||||
Direction f = facingToDirection(facing);
|
||||
Direction left = rotateCCW(f);
|
||||
Direction right = rotateCW(f);
|
||||
Block l = instance.getBlock(new BlockVec(pos.blockX() + left.normalX(), pos.blockY(), pos.blockZ() + left.normalZ()));
|
||||
Block r = instance.getBlock(new BlockVec(pos.blockX() + right.normalX(), pos.blockY(), pos.blockZ() + right.normalZ()));
|
||||
boolean inWall = l.key().value().endsWith("_wall") || r.key().value().endsWith("_wall");
|
||||
return gate.withProperty("in_wall", inWall ? "true" : "false");
|
||||
}
|
||||
|
||||
private static void updateRedstoneWire(Instance instance, BlockVec pos) {
|
||||
Block wire = instance.getBlock(pos);
|
||||
if (!wire.key().value().equals("redstone_wire")) return;
|
||||
Block result = wire;
|
||||
for (Direction d : Direction.HORIZONTAL) {
|
||||
BlockVec side = new BlockVec(pos.blockX() + d.normalX(), pos.blockY(), pos.blockZ() + d.normalZ());
|
||||
Block sideBlock = instance.getBlock(side);
|
||||
Block upBlock = instance.getBlock(new BlockVec(side.blockX(), side.blockY() + 1, side.blockZ()));
|
||||
String state;
|
||||
if (upBlock.key().value().equals("redstone_wire")) state = "up";
|
||||
else if (isRedstoneConnectable(sideBlock)
|
||||
|| instance.getBlock(new BlockVec(side.blockX(), side.blockY() - 1, side.blockZ())).key().value().equals("redstone_wire")) state = "side";
|
||||
else state = "none";
|
||||
result = result.withProperty(d.name().toLowerCase(), state);
|
||||
}
|
||||
instance.setBlock(pos, result);
|
||||
}
|
||||
|
||||
private static boolean isRedstoneConnectable(Block b) {
|
||||
String p = b.key().value();
|
||||
return p.equals("redstone_wire") || p.equals("lever") || p.endsWith("_button")
|
||||
|| p.equals("repeater") || p.equals("comparator") || p.equals("redstone_torch")
|
||||
|| p.equals("redstone_wall_torch") || p.equals("observer") || p.equals("daylight_detector")
|
||||
|| p.endsWith("_pressure_plate") || p.equals("target") || p.equals("redstone_block")
|
||||
|| p.equals("tripwire_hook");
|
||||
}
|
||||
|
||||
private static boolean isRail(String path) {
|
||||
return path.equals("rail") || path.equals("powered_rail") || path.equals("detector_rail") || path.equals("activator_rail");
|
||||
}
|
||||
|
||||
private static void updateRailShape(Instance instance, BlockVec pos) {
|
||||
Block rail = instance.getBlock(pos);
|
||||
String path = rail.key().value();
|
||||
if (!isRail(path)) return;
|
||||
boolean canCurve = path.equals("rail");
|
||||
boolean[] adj = new boolean[4];
|
||||
boolean[] ascAdj = new boolean[4];
|
||||
Direction[] dirs = {Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST};
|
||||
for (int i = 0; i < 4; i++) {
|
||||
BlockVec np = new BlockVec(pos.blockX() + dirs[i].normalX(), pos.blockY(), pos.blockZ() + dirs[i].normalZ());
|
||||
adj[i] = isRail(instance.getBlock(np).key().value());
|
||||
BlockVec upNp = new BlockVec(np.blockX(), np.blockY() + 1, np.blockZ());
|
||||
ascAdj[i] = isRail(instance.getBlock(upNp).key().value());
|
||||
}
|
||||
String shape;
|
||||
if (canCurve) {
|
||||
if (adj[0] && adj[1]) shape = "north_east";
|
||||
else if (adj[1] && adj[2]) shape = "south_east";
|
||||
else if (adj[2] && adj[3]) shape = "south_west";
|
||||
else if (adj[3] && adj[0]) shape = "north_west";
|
||||
else if (ascAdj[0]) shape = "ascending_north";
|
||||
else if (ascAdj[1]) shape = "ascending_east";
|
||||
else if (ascAdj[2]) shape = "ascending_south";
|
||||
else if (ascAdj[3]) shape = "ascending_west";
|
||||
else if (adj[1] || adj[3]) shape = "east_west";
|
||||
else shape = "north_south";
|
||||
} else {
|
||||
if (ascAdj[0]) shape = "ascending_north";
|
||||
else if (ascAdj[1]) shape = "ascending_east";
|
||||
else if (ascAdj[2]) shape = "ascending_south";
|
||||
else if (ascAdj[3]) shape = "ascending_west";
|
||||
else if (adj[1] || adj[3]) shape = "east_west";
|
||||
else shape = "north_south";
|
||||
}
|
||||
instance.setBlock(pos, rail.withProperty("shape", shape));
|
||||
}
|
||||
|
||||
private static void updateScaffolding(Instance instance, BlockVec pos) {
|
||||
Block s = instance.getBlock(pos);
|
||||
if (!s.key().value().equals("scaffolding")) return;
|
||||
Block below = instance.getBlock(new BlockVec(pos.blockX(), pos.blockY() - 1, pos.blockZ()));
|
||||
boolean bottom;
|
||||
int distance;
|
||||
if (below.isSolid() && !below.key().value().equals("scaffolding")) { bottom = false; distance = 0; }
|
||||
else if (below.key().value().equals("scaffolding")) { bottom = false; distance = 0; }
|
||||
else {
|
||||
int min = 7;
|
||||
for (Direction d : Direction.HORIZONTAL) {
|
||||
Block n = instance.getBlock(new BlockVec(pos.blockX() + d.normalX(), pos.blockY(), pos.blockZ() + d.normalZ()));
|
||||
if (n.key().value().equals("scaffolding")) min = Math.min(min, parseIntOr(n.getProperty("distance"), 7) + 1);
|
||||
}
|
||||
bottom = true;
|
||||
distance = min;
|
||||
}
|
||||
instance.setBlock(pos, s.withProperty("bottom", String.valueOf(bottom)).withProperty("distance", String.valueOf(distance)));
|
||||
}
|
||||
|
||||
private static void updateChestPair(Instance instance, BlockVec pos) {
|
||||
Block chest = instance.getBlock(pos);
|
||||
String path = chest.key().value();
|
||||
if (!(path.equals("chest") || path.equals("trapped_chest"))) return;
|
||||
String facing = chest.getProperty("facing");
|
||||
if (facing == null) return;
|
||||
Direction f = facingToDirection(facing);
|
||||
Direction left = rotateCCW(f);
|
||||
Direction right = rotateCW(f);
|
||||
BlockVec leftPos = new BlockVec(pos.blockX() + left.normalX(), pos.blockY(), pos.blockZ() + left.normalZ());
|
||||
BlockVec rightPos = new BlockVec(pos.blockX() + right.normalX(), pos.blockY(), pos.blockZ() + right.normalZ());
|
||||
Block leftBlock = instance.getBlock(leftPos);
|
||||
Block rightBlock = instance.getBlock(rightPos);
|
||||
if (leftBlock.key().value().equals(path) && facing.equals(leftBlock.getProperty("facing"))
|
||||
&& "single".equals(leftBlock.getProperty("type"))) {
|
||||
instance.setBlock(pos, chest.withProperty("type", "right"));
|
||||
instance.setBlock(leftPos, leftBlock.withProperty("type", "left"));
|
||||
return;
|
||||
}
|
||||
if (rightBlock.key().value().equals(path) && facing.equals(rightBlock.getProperty("facing"))
|
||||
&& "single".equals(rightBlock.getProperty("type"))) {
|
||||
instance.setBlock(pos, chest.withProperty("type", "left"));
|
||||
instance.setBlock(rightPos, rightBlock.withProperty("type", "right"));
|
||||
}
|
||||
}
|
||||
|
||||
private static String yawToFacing(float yaw) {
|
||||
float y = ((yaw % 360) + 360) % 360;
|
||||
if (y >= 315 || y < 45) return "south";
|
||||
if (y < 135) return "west";
|
||||
if (y < 225) return "north";
|
||||
return "east";
|
||||
}
|
||||
|
||||
private static String faceName(BlockFace face) {
|
||||
return switch (face) {
|
||||
case NORTH -> "north";
|
||||
case SOUTH -> "south";
|
||||
case EAST -> "east";
|
||||
case WEST -> "west";
|
||||
case TOP -> "up";
|
||||
case BOTTOM -> "down";
|
||||
};
|
||||
}
|
||||
|
||||
private static String oppositeFacing(String f) {
|
||||
return switch (f) {
|
||||
case "north" -> "south";
|
||||
case "south" -> "north";
|
||||
case "east" -> "west";
|
||||
case "west" -> "east";
|
||||
case "up" -> "down";
|
||||
case "down" -> "up";
|
||||
default -> f;
|
||||
};
|
||||
}
|
||||
|
||||
private static Direction faceDirection(BlockFace face) {
|
||||
return switch (face) {
|
||||
case NORTH -> Direction.NORTH;
|
||||
case SOUTH -> Direction.SOUTH;
|
||||
case EAST -> Direction.EAST;
|
||||
case WEST -> Direction.WEST;
|
||||
case TOP -> Direction.UP;
|
||||
case BOTTOM -> Direction.DOWN;
|
||||
};
|
||||
}
|
||||
|
||||
private static Direction facingToDirection(String f) {
|
||||
if (f == null) return Direction.NORTH;
|
||||
return switch (f) {
|
||||
case "north" -> Direction.NORTH;
|
||||
case "south" -> Direction.SOUTH;
|
||||
case "east" -> Direction.EAST;
|
||||
case "west" -> Direction.WEST;
|
||||
case "up" -> Direction.UP;
|
||||
case "down" -> Direction.DOWN;
|
||||
default -> Direction.NORTH;
|
||||
};
|
||||
}
|
||||
|
||||
private static Direction rotateCW(Direction d) {
|
||||
return switch (d) {
|
||||
case NORTH -> Direction.EAST;
|
||||
case EAST -> Direction.SOUTH;
|
||||
case SOUTH -> Direction.WEST;
|
||||
case WEST -> Direction.NORTH;
|
||||
default -> d;
|
||||
};
|
||||
}
|
||||
|
||||
private static Direction rotateCCW(Direction d) {
|
||||
return switch (d) {
|
||||
case NORTH -> Direction.WEST;
|
||||
case WEST -> Direction.SOUTH;
|
||||
case SOUTH -> Direction.EAST;
|
||||
case EAST -> Direction.NORTH;
|
||||
default -> d;
|
||||
};
|
||||
}
|
||||
|
||||
private static String doorHinge(String facing, Point cursor, Instance instance, BlockVec pos, String path) {
|
||||
Direction f = facingToDirection(facing);
|
||||
Direction left = rotateCCW(f);
|
||||
BlockVec leftPos = new BlockVec(pos.blockX() + left.normalX(), pos.blockY(), pos.blockZ() + left.normalZ());
|
||||
Block leftBlock = instance.getBlock(leftPos);
|
||||
if (leftBlock.key().value().equals(path) && facing.equals(leftBlock.getProperty("facing"))) {
|
||||
return "right";
|
||||
}
|
||||
double x = cursor.x() - 0.5;
|
||||
double z = cursor.z() - 0.5;
|
||||
return switch (facing) {
|
||||
case "north" -> x < 0 ? "right" : "left";
|
||||
case "south" -> x > 0 ? "right" : "left";
|
||||
case "west" -> z > 0 ? "right" : "left";
|
||||
case "east" -> z < 0 ? "right" : "left";
|
||||
default -> "left";
|
||||
};
|
||||
}
|
||||
|
||||
public static void onInteract(PlayerBlockInteractEvent event) {
|
||||
Block block = event.getBlock();
|
||||
String path = block.key().value();
|
||||
Instance instance = event.getInstance();
|
||||
BlockVec pos = event.getBlockPosition();
|
||||
|
||||
if (path.endsWith("_door")) {
|
||||
String half = block.getProperty("half");
|
||||
BlockVec lowerPos = "upper".equals(half)
|
||||
? new BlockVec(pos.blockX(), pos.blockY() - 1, pos.blockZ())
|
||||
: pos;
|
||||
BlockVec upperPos = new BlockVec(lowerPos.blockX(), lowerPos.blockY() + 1, lowerPos.blockZ());
|
||||
Block lower = instance.getBlock(lowerPos);
|
||||
Block upper = instance.getBlock(upperPos);
|
||||
if (!lower.key().value().equals(path) || !upper.key().value().equals(path)) return;
|
||||
boolean open = !"true".equals(lower.getProperty("open"));
|
||||
instance.setBlock(lowerPos, lower.withProperty("open", String.valueOf(open)));
|
||||
instance.setBlock(upperPos, upper.withProperty("open", String.valueOf(open)));
|
||||
|
||||
String facing = lower.getProperty("facing");
|
||||
String hinge = lower.getProperty("hinge");
|
||||
if (facing != null && hinge != null) {
|
||||
Direction f = facingToDirection(facing);
|
||||
Direction side = "left".equals(hinge) ? rotateCW(f) : rotateCCW(f);
|
||||
BlockVec partnerPos = new BlockVec(lowerPos.blockX() + side.normalX(), lowerPos.blockY(), lowerPos.blockZ() + side.normalZ());
|
||||
Block partner = instance.getBlock(partnerPos);
|
||||
if (partner.key().value().equals(path) && facing.equals(partner.getProperty("facing"))
|
||||
&& !hinge.equals(partner.getProperty("hinge"))) {
|
||||
Block partnerUpper = instance.getBlock(new BlockVec(partnerPos.blockX(), partnerPos.blockY() + 1, partnerPos.blockZ()));
|
||||
instance.setBlock(partnerPos, partner.withProperty("open", String.valueOf(open)));
|
||||
if (partnerUpper.key().value().equals(path)) {
|
||||
instance.setBlock(new BlockVec(partnerPos.blockX(), partnerPos.blockY() + 1, partnerPos.blockZ()),
|
||||
partnerUpper.withProperty("open", String.valueOf(open)));
|
||||
}
|
||||
}
|
||||
}
|
||||
event.setBlockingItemUse(true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (path.endsWith("_fence_gate")) {
|
||||
boolean open = !"true".equals(block.getProperty("open"));
|
||||
Block updated = block.withProperty("open", String.valueOf(open));
|
||||
if (open) {
|
||||
String facing = block.getProperty("facing");
|
||||
if (facing != null) {
|
||||
Direction f = facingToDirection(facing);
|
||||
Direction playerDir = horizontalFacingToDirection(yawToFacing(event.getPlayer().getPosition().yaw()));
|
||||
if (playerDir == f) updated = updated.withProperty("facing", oppositeFacing(facing));
|
||||
}
|
||||
}
|
||||
instance.setBlock(pos, updated);
|
||||
event.setBlockingItemUse(true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (path.endsWith("_trapdoor")) {
|
||||
boolean open = !"true".equals(block.getProperty("open"));
|
||||
instance.setBlock(pos, block.withProperty("open", String.valueOf(open)));
|
||||
event.setBlockingItemUse(true);
|
||||
}
|
||||
}
|
||||
|
||||
private static Direction horizontalFacingToDirection(String f) {
|
||||
return facingToDirection(f);
|
||||
}
|
||||
|
||||
public static void onBreak(PlayerBlockBreakEvent event) {
|
||||
Instance instance = event.getInstance();
|
||||
BlockVec pos = event.getBlockPosition();
|
||||
Block broken = event.getBlock();
|
||||
String path = broken.key().value();
|
||||
|
||||
if (path.endsWith("_door")) {
|
||||
String half = broken.getProperty("half");
|
||||
BlockVec other = "upper".equals(half)
|
||||
? new BlockVec(pos.blockX(), pos.blockY() - 1, pos.blockZ())
|
||||
: new BlockVec(pos.blockX(), pos.blockY() + 1, pos.blockZ());
|
||||
instance.scheduler().scheduleNextTick(() -> {
|
||||
Block ob = instance.getBlock(other);
|
||||
if (ob.key().value().equals(path)) instance.setBlock(other, Block.AIR);
|
||||
});
|
||||
}
|
||||
|
||||
if (path.endsWith("_bed")) {
|
||||
String part = broken.getProperty("part");
|
||||
String facing = broken.getProperty("facing");
|
||||
if (facing != null) {
|
||||
Direction d = facingToDirection(facing);
|
||||
if ("foot".equals(part)) {
|
||||
BlockVec headPos = new BlockVec(pos.blockX() + d.normalX(), pos.blockY(), pos.blockZ() + d.normalZ());
|
||||
instance.scheduler().scheduleNextTick(() -> {
|
||||
if (instance.getBlock(headPos).key().value().equals(path)) instance.setBlock(headPos, Block.AIR);
|
||||
});
|
||||
} else if ("head".equals(part)) {
|
||||
BlockVec footPos = new BlockVec(pos.blockX() - d.normalX(), pos.blockY(), pos.blockZ() - d.normalZ());
|
||||
instance.scheduler().scheduleNextTick(() -> {
|
||||
if (instance.getBlock(footPos).key().value().equals(path)) instance.setBlock(footPos, Block.AIR);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (path.equals("big_dripleaf") || path.equals("big_dripleaf_stem")) {
|
||||
String half = broken.getProperty("half");
|
||||
BlockVec other = "upper".equals(half)
|
||||
? new BlockVec(pos.blockX(), pos.blockY() - 1, pos.blockZ())
|
||||
: new BlockVec(pos.blockX(), pos.blockY() + 1, pos.blockZ());
|
||||
instance.scheduler().scheduleNextTick(() -> {
|
||||
String op = instance.getBlock(other).key().value();
|
||||
if (op.equals("big_dripleaf") || op.equals("big_dripleaf_stem")) instance.setBlock(other, Block.AIR);
|
||||
});
|
||||
}
|
||||
|
||||
instance.scheduler().scheduleNextTick(() -> {
|
||||
if (isConnecting(path)) {
|
||||
for (Direction d : Direction.HORIZONTAL) {
|
||||
BlockVec np = new BlockVec(pos.blockX() + d.normalX(), pos.blockY(), pos.blockZ() + d.normalZ());
|
||||
Block nb = instance.getBlock(np);
|
||||
if (isConnecting(nb.key().value())) instance.setBlock(np, computeConnections(nb, nb.key().value(), instance, np));
|
||||
if (nb.key().value().endsWith("_fence_gate")) instance.setBlock(np, updateFenceGateInWall(nb, instance, np));
|
||||
}
|
||||
}
|
||||
|
||||
if (path.endsWith("_wall")) {
|
||||
for (Direction d : Direction.HORIZONTAL) {
|
||||
BlockVec np = new BlockVec(pos.blockX() + d.normalX(), pos.blockY(), pos.blockZ() + d.normalZ());
|
||||
Block nb = instance.getBlock(np);
|
||||
if (nb.key().value().endsWith("_fence_gate")) instance.setBlock(np, updateFenceGateInWall(nb, instance, np));
|
||||
}
|
||||
}
|
||||
|
||||
for (Direction d : Direction.HORIZONTAL) {
|
||||
BlockVec np = new BlockVec(pos.blockX() + d.normalX(), pos.blockY(), pos.blockZ() + d.normalZ());
|
||||
Block nb = instance.getBlock(np);
|
||||
String npath = nb.key().value();
|
||||
if (npath.equals("redstone_wire")) updateRedstoneWire(instance, np);
|
||||
if (isRail(npath)) updateRailShape(instance, np);
|
||||
}
|
||||
BlockVec above = new BlockVec(pos.blockX(), pos.blockY() + 1, pos.blockZ());
|
||||
if (instance.getBlock(above).key().value().equals("redstone_wire")) updateRedstoneWire(instance, above);
|
||||
BlockVec belowRail = new BlockVec(pos.blockX(), pos.blockY() - 1, pos.blockZ());
|
||||
if (isRail(instance.getBlock(belowRail).key().value())) updateRailShape(instance, belowRail);
|
||||
|
||||
if (path.equals("scaffolding") || isAnyScaffoldingAround(instance, pos)) {
|
||||
recomputeScaffoldingColumn(instance, pos);
|
||||
for (Direction d : Direction.HORIZONTAL) {
|
||||
BlockVec np = new BlockVec(pos.blockX() + d.normalX(), pos.blockY(), pos.blockZ() + d.normalZ());
|
||||
if (instance.getBlock(np).key().value().equals("scaffolding")) recomputeScaffoldingColumn(instance, np);
|
||||
}
|
||||
}
|
||||
|
||||
if (path.equals("chest") || path.equals("trapped_chest")) {
|
||||
String facing = broken.getProperty("facing");
|
||||
if (facing != null) {
|
||||
Direction f = facingToDirection(facing);
|
||||
for (Direction d : new Direction[]{rotateCW(f), rotateCCW(f)}) {
|
||||
BlockVec np = new BlockVec(pos.blockX() + d.normalX(), pos.blockY(), pos.blockZ() + d.normalZ());
|
||||
Block nb = instance.getBlock(np);
|
||||
if (nb.key().value().equals(path) && facing.equals(nb.getProperty("facing"))) {
|
||||
String t = nb.getProperty("type");
|
||||
if ("left".equals(t) || "right".equals(t)) instance.setBlock(np, nb.withProperty("type", "single"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isStairLike(path)) {
|
||||
for (Direction d : Direction.HORIZONTAL) {
|
||||
BlockVec np = new BlockVec(pos.blockX() + d.normalX(), pos.blockY(), pos.blockZ() + d.normalZ());
|
||||
Block nb = instance.getBlock(np);
|
||||
if (nb.key().value().endsWith("_stairs")) {
|
||||
String nf = nb.getProperty("facing");
|
||||
boolean nt = isTopStair(nb);
|
||||
instance.setBlock(np, applyStairShape(nb, instance, np, nf, nt));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static boolean isStairLike(String path) { return path.endsWith("_stairs"); }
|
||||
|
||||
private static boolean isAnyScaffoldingAround(Instance instance, BlockVec pos) {
|
||||
for (Direction d : Direction.HORIZONTAL) {
|
||||
BlockVec np = new BlockVec(pos.blockX() + d.normalX(), pos.blockY(), pos.blockZ() + d.normalZ());
|
||||
if (instance.getBlock(np).key().value().equals("scaffolding")) return true;
|
||||
}
|
||||
BlockVec above = new BlockVec(pos.blockX(), pos.blockY() + 1, pos.blockZ());
|
||||
return instance.getBlock(above).key().value().equals("scaffolding");
|
||||
}
|
||||
|
||||
private static void recomputeScaffoldingColumn(Instance instance, BlockVec start) {
|
||||
int x = start.blockX(), z = start.blockZ();
|
||||
for (int y = start.blockY(); y < start.blockY() + 32; y++) {
|
||||
BlockVec p = new BlockVec(x, y, z);
|
||||
if (!instance.getBlock(p).key().value().equals("scaffolding")) break;
|
||||
updateScaffolding(instance, p);
|
||||
}
|
||||
}
|
||||
|
||||
private static int parseIntOr(String s, int d) {
|
||||
if (s == null) return d;
|
||||
try { return Integer.parseInt(s); } catch (NumberFormatException e) { return d; }
|
||||
}
|
||||
}
|
||||
+2
-3
@@ -62,10 +62,11 @@ public class BuildBattle extends StatelessGame {
|
||||
super(Dimension.THE_END.key, "BuildBattle", new PointsWinScore());
|
||||
this.seconds = seconds;
|
||||
this.setGenerator(new BuildBattleChunkgenerator(height));
|
||||
BuildBattleBlockRules.register();
|
||||
this.eventNode().addListener(PlayerUseItemEvent.class, this::onRatingItemUse);
|
||||
this.eventNode().addListener(PlayerUseItemOnBlockEvent.class, e -> FluidFlowHelper.onBucketUse(e, p -> this.isInArea(p, e.getPlayer())));
|
||||
this.eventNode().addListener(PlayerBlockInteractEvent.class, e -> {
|
||||
if (this.isInArea(e.getBlockPosition(), e.getPlayer())) BlockPlacementHelper.onInteract(e);
|
||||
if (this.isInArea(e.getBlockPosition(), e.getPlayer())) BuildBattleBlockRules.onInteract(e);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -134,7 +135,6 @@ public class BuildBattle extends StatelessGame {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
BlockPlacementHelper.onBreak(event);
|
||||
FluidFlowHelper.onBreak(event);
|
||||
}
|
||||
|
||||
@@ -144,7 +144,6 @@ public class BuildBattle extends StatelessGame {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
BlockPlacementHelper.apply(event);
|
||||
FluidFlowHelper.onPlace(event);
|
||||
}
|
||||
|
||||
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
package eu.mhsl.minenet.minigames.instance.game.stateless.types.buildBattle;
|
||||
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.event.player.PlayerBlockInteractEvent;
|
||||
import net.minestom.server.instance.block.Block;
|
||||
import net.minestom.server.instance.block.BlockHandler;
|
||||
import net.minestom.server.instance.block.rule.BlockPlacementRule;
|
||||
import org.everbuild.blocksandstuff.blocks.group.VanillaBlockBehaviour;
|
||||
import org.everbuild.blocksandstuff.blocks.group.VanillaPlacementRules;
|
||||
import org.everbuild.blocksandstuff.blocks.group.behaviour.BehaviourGroup;
|
||||
import org.everbuild.blocksandstuff.blocks.group.placement.PlacementGroup;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public final class BuildBattleBlockRules {
|
||||
private BuildBattleBlockRules() {}
|
||||
|
||||
private static final ThreadLocal<Boolean> interactingInBuildBattle = ThreadLocal.withInitial(() -> false);
|
||||
private static final Map<Integer, BlockHandler> behaviours = new HashMap<>();
|
||||
private static boolean registered = false;
|
||||
|
||||
public static synchronized void register() {
|
||||
if (registered) return;
|
||||
registered = true;
|
||||
|
||||
var blockManager = MinecraftServer.getBlockManager();
|
||||
for (PlacementGroup group : VanillaPlacementRules.INSTANCE.getALL()) {
|
||||
for (Block block : group.getBlockGroup().allMatching()) {
|
||||
blockManager.registerBlockPlacementRule(new BuildBattleOnlyRule(group.createRule(block)));
|
||||
}
|
||||
}
|
||||
|
||||
for (BehaviourGroup group : VanillaBlockBehaviour.INSTANCE.getALL()) {
|
||||
for (Block block : group.getBlockGroup().allMatching()) {
|
||||
behaviours.put(block.id(), group.createHandler(block));
|
||||
}
|
||||
}
|
||||
|
||||
MinecraftServer.getGlobalEventHandler().addListener(PlayerBlockInteractEvent.class,
|
||||
e -> interactingInBuildBattle.set(e.getInstance() instanceof BuildBattle));
|
||||
}
|
||||
|
||||
public static void onInteract(PlayerBlockInteractEvent event) {
|
||||
BlockHandler handler = behaviours.get(event.getBlock().id());
|
||||
if (handler == null) return;
|
||||
boolean continueItemUse = handler.onInteract(new BlockHandler.Interaction(
|
||||
event.getBlock(), event.getInstance(), event.getBlockFace(), event.getBlockPosition(),
|
||||
event.getCursorPosition(), event.getPlayer(), event.getHand()
|
||||
));
|
||||
if (!continueItemUse) event.setBlockingItemUse(true);
|
||||
}
|
||||
|
||||
private static final class BuildBattleOnlyRule extends BlockPlacementRule {
|
||||
private final BlockPlacementRule delegate;
|
||||
|
||||
private BuildBattleOnlyRule(BlockPlacementRule delegate) {
|
||||
super(delegate.getBlock());
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Block blockPlace(PlacementState placementState) {
|
||||
if (!(placementState.instance() instanceof BuildBattle)) return placementState.block();
|
||||
return this.delegate.blockPlace(placementState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Block blockUpdate(UpdateState updateState) {
|
||||
if (!(updateState.instance() instanceof BuildBattle)) return updateState.currentBlock();
|
||||
return this.delegate.blockUpdate(updateState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSelfReplaceable(Replacement replacement) {
|
||||
return interactingInBuildBattle.get() && this.delegate.isSelfReplaceable(replacement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int maxUpdateDistance() {
|
||||
return this.delegate.maxUpdateDistance();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user