You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
161 lines
6.2 KiB
161 lines
6.2 KiB
package net.deliciousreya.minecraftportal
|
|
|
|
import com.google.common.collect.ImmutableList
|
|
import com.google.common.collect.ImmutableMap
|
|
import com.google.common.collect.ImmutableSet
|
|
import org.bukkit.Location
|
|
import org.bukkit.block.Block
|
|
import org.bukkit.util.Vector
|
|
import net.deliciousreya.minecraftportal.extensions.*
|
|
import org.bukkit.Material
|
|
import org.bukkit.Material.*
|
|
import org.bukkit.block.BlockFace
|
|
import org.bukkit.material.Directional
|
|
|
|
val MINERAL_TYPES: ImmutableMap<Material, Material> = ImmutableMap.Builder<Material, Material>()
|
|
.put(COAL_BLOCK, BLACK_STAINED_GLASS)
|
|
.put(REDSTONE_BLOCK, RED_STAINED_GLASS)
|
|
.put(LAPIS_BLOCK, BLUE_STAINED_GLASS)
|
|
.put(GOLD_BLOCK, YELLOW_STAINED_GLASS)
|
|
.put(DIAMOND_BLOCK, CYAN_STAINED_GLASS)
|
|
.put(EMERALD_BLOCK, GREEN_STAINED_GLASS)
|
|
.put(IRON_BLOCK, GRAY_STAINED_GLASS)
|
|
.put(QUARTZ_BLOCK, WHITE_STAINED_GLASS)
|
|
.build()
|
|
|
|
val DOOR_TYPES: ImmutableSet<Material> = ImmutableSet.of(ACACIA_DOOR, BIRCH_DOOR, DARK_OAK_DOOR, IRON_DOOR, JUNGLE_DOOR, OAK_DOOR, SPRUCE_DOOR)
|
|
|
|
fun findPortalFrameConnectedTo(block:Block, state:PortalFrame.State): PortalFrame? {
|
|
when {
|
|
block.type in state.glassBlocks -> for (direction in PortalFrame.EntranceDirection.values()) {
|
|
for (vector in direction.glassOffsets) {
|
|
val scanResult = checkPortalFrameAt(block.location.subtract(vector), direction, state)
|
|
if (scanResult != null) {
|
|
return scanResult
|
|
}
|
|
}
|
|
}
|
|
block.type in state.doorBlocks -> for (direction in PortalFrame.EntranceDirection.values()) {
|
|
for (vector in direction.doorOffsets) {
|
|
val scanResult = checkPortalFrameAt(block.location.subtract(vector), direction, state)
|
|
if (scanResult != null) {
|
|
return scanResult
|
|
}
|
|
}
|
|
}
|
|
block.type in state.mineralBlocks -> for (direction in PortalFrame.EntranceDirection.values()) {
|
|
val scanResult = checkPortalFrameAt(block.location.subtract(direction.mineralOffset), direction, state)
|
|
if (scanResult != null) {
|
|
return scanResult
|
|
}
|
|
}
|
|
}
|
|
return null
|
|
}
|
|
|
|
/** Detects whether there is a portal frame in the given state at the given location, extending in the given direction. */
|
|
fun checkPortalFrameAt(location:Location, direction:PortalFrame.EntranceDirection, state:PortalFrame.State): PortalFrame? {
|
|
val mineral = (location + direction.mineralOffset).block
|
|
if (mineral.type !in state.mineralBlocks) {
|
|
return null
|
|
}
|
|
for (vector in direction.glassOffsets) {
|
|
val block = (location + vector).block
|
|
if (block.type !in state.glassBlocks) {
|
|
return null
|
|
}
|
|
}
|
|
for (vector in direction.doorOffsets) {
|
|
val block = (location + vector).block
|
|
if (block.type !in state.doorBlocks || (block.blockData is Directional && (block.blockData as Directional).facing != direction.doorDirection)) {
|
|
return null
|
|
}
|
|
}
|
|
return PortalFrame(location, direction)
|
|
}
|
|
|
|
/** Information about a portal frame. */
|
|
data class PortalFrame(val lowerLeftFrontCorner: Location, val direction: EntranceDirection) {
|
|
enum class State(val glassBlocks: ImmutableSet<Material>, val doorBlocks: ImmutableSet<Material>, val mineralBlocks: ImmutableSet<Material>) {
|
|
ACTIVE(ImmutableSet.copyOf(MINERAL_TYPES.values), DOOR_TYPES, ImmutableSet.copyOf(MINERAL_TYPES.keys)),
|
|
INACTIVE(ImmutableSet.of(GLASS), DOOR_TYPES, ImmutableSet.copyOf(MINERAL_TYPES.keys));
|
|
|
|
val allValidBlocks = ImmutableSet.Builder<Material>().addAll(glassBlocks).addAll(doorBlocks).addAll(mineralBlocks).build()
|
|
}
|
|
/** The direction along which a portal frame extends. */
|
|
enum class EntranceDirection(toRight: Vector, toBack: Vector, val doorDirection: BlockFace) {
|
|
NORTH(Vector(1, 0, 0), Vector(0, 0, 1), BlockFace.NORTH),
|
|
SOUTH(Vector(1, 0, 0), Vector(0, 0, -1), BlockFace.SOUTH),
|
|
EAST(Vector(0, 0, 1), Vector(-1, 0, 0), BlockFace.EAST),
|
|
WEST(Vector(0, 0, 1), Vector(1, 0, 0), BlockFace.WEST);
|
|
|
|
val glassOffsets: ImmutableList<Vector> = ImmutableList.of(
|
|
// check corners first:
|
|
// bottom left, front
|
|
ZERO,
|
|
// top right, back
|
|
UP * 3 + toBack + toRight * 2,
|
|
// bottom right, front
|
|
toRight * 2,
|
|
// top right, front
|
|
UP * 3 + toRight * 2,
|
|
// top left, front
|
|
UP * 3,
|
|
// bottom left, back
|
|
toBack,
|
|
// top left, back
|
|
UP * 3 + toBack,
|
|
// bottom right, back
|
|
toBack + toRight * 2,
|
|
|
|
// then do front walls
|
|
// left front wall
|
|
UP,
|
|
UP * 2,
|
|
// top front wall
|
|
UP * 3 + toRight,
|
|
// right front wall
|
|
UP + toRight * 2,
|
|
UP * 2 + toRight * 2,
|
|
|
|
// now do the rest of the back
|
|
// left back wall
|
|
UP + toBack,
|
|
UP * 2 + toBack,
|
|
// center back wall
|
|
toBack + toRight,
|
|
UP + toBack + toRight,
|
|
UP * 2 + toBack + toRight,
|
|
UP * 3 + toBack + toRight,
|
|
// right back wall
|
|
UP + toBack + toRight * 2,
|
|
UP * 2 + toBack + toRight * 2
|
|
)
|
|
|
|
val mineralOffset: Vector = toRight
|
|
|
|
val doorOffsets: ImmutableList<Vector> = ImmutableList.of(
|
|
Vector(0, 1, 0) + toRight,
|
|
Vector(0, 2, 0) + toRight
|
|
)
|
|
}
|
|
|
|
val portalCenter = lowerLeftFrontCorner + direction.doorOffsets[0]
|
|
|
|
fun isStandingInPortal(location: Location): Boolean {
|
|
return direction.doorOffsets.any { offset -> location.block.location - offset == lowerLeftFrontCorner }
|
|
}
|
|
|
|
fun color() {
|
|
val mineral = (lowerLeftFrontCorner + direction.mineralOffset).block
|
|
for (offset in direction.glassOffsets) {
|
|
(lowerLeftFrontCorner + offset).block.type = MINERAL_TYPES.getOrDefault(mineral.type, BROWN_STAINED_GLASS)
|
|
}
|
|
}
|
|
|
|
fun uncolor() {
|
|
for (offset in direction.glassOffsets) {
|
|
(lowerLeftFrontCorner + offset).block.type = GLASS
|
|
}
|
|
}
|
|
} |