Work on RegionTraverser (wasted a lotta time but we'll get there)
This commit is contained in:
@@ -17,8 +17,11 @@ plugins {
|
||||
id("com.github.johnrengelman.plugin-shadow") version "2.0.3"
|
||||
}
|
||||
|
||||
|
||||
|
||||
allprojects {
|
||||
apply<JavaPlugin>()
|
||||
apply(plugin = "idea")
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
@@ -68,7 +71,7 @@ dependencies {
|
||||
|
||||
// not on sk89q maven repo yet
|
||||
compileClasspath(files("$rootDir/debug/plugins/worldedit-bukkit-7.0.0-beta-01.jar"))
|
||||
compileClasspath(files("$rootDir/debug/lib/spigot-1.13.1.jar"))
|
||||
//compileClasspath(files("$rootDir/debug/lib/spigot-1.13.1.jar"))
|
||||
|
||||
compile("org.jetbrains.exposed:exposed:0.10.5") { isTransitive = false }
|
||||
compile("joda-time:joda-time:2.10")
|
||||
@@ -91,7 +94,7 @@ tasks {
|
||||
javaParameters = true
|
||||
suppressWarnings = true
|
||||
jvmTarget = "1.8"
|
||||
//freeCompilerArgs = listOf("-XXLanguage:+InlineClasses", "-Xuse-experimental=kotlin.Experimental")
|
||||
freeCompilerArgs = listOf("-XXLanguage:+InlineClasses", "-Xuse-experimental=kotlin.Experimental")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,67 +1,61 @@
|
||||
package io.dico.parcels2.blockvisitor
|
||||
|
||||
import io.dico.parcels2.util.Vec3i
|
||||
import io.dico.parcels2.util.ext.getMaterialsWithWoodTypePrefix
|
||||
import io.dico.parcels2.util.ext.getMaterialsWithWoolColorPrefix
|
||||
import org.bukkit.Material
|
||||
import org.bukkit.Material.*
|
||||
import org.bukkit.block.BlockFace
|
||||
import org.bukkit.block.data.BlockData
|
||||
import org.bukkit.block.data.Directional
|
||||
import java.util.EnumSet
|
||||
|
||||
val attachables: Set<Material> = EnumSet.of(
|
||||
ACACIA_DOOR,
|
||||
ACTIVATOR_RAIL,
|
||||
BIRCH_DOOR,
|
||||
BROWN_MUSHROOM,
|
||||
CACTUS,
|
||||
CAKE,
|
||||
WHITE_CARPET, ORANGE_CARPET, MAGENTA_CARPET, LIGHT_BLUE_CARPET, YELLOW_CARPET, LIME_CARPET, PINK_CARPET, GRAY_CARPET, LIGHT_GRAY_CARPET, CYAN_CARPET, PURPLE_CARPET, BLUE_CARPET, BROWN_CARPET, GREEN_CARPET, RED_CARPET, BLACK_CARPET,
|
||||
CARROT,
|
||||
COCOA,
|
||||
WHEAT,
|
||||
DARK_OAK_DOOR,
|
||||
DEAD_BUSH,
|
||||
DETECTOR_RAIL,
|
||||
REPEATER,
|
||||
TALL_GRASS, TALL_SEAGRASS,
|
||||
DRAGON_EGG,
|
||||
FIRE,
|
||||
FLOWER_POT,
|
||||
OAK_PRESSURE_PLATE, BIRCH_PRESSURE_PLATE, SPRUCE_PRESSURE_PLATE, JUNGLE_PRESSURE_PLATE, ACACIA_PRESSURE_PLATE, DARK_OAK_PRESSURE_PLATE,
|
||||
private val attachables = EnumSet.of(
|
||||
REPEATER, COMPARATOR,
|
||||
*getMaterialsWithWoodTypePrefix("PRESSURE_PLATE"),
|
||||
STONE_PRESSURE_PLATE, LIGHT_WEIGHTED_PRESSURE_PLATE, HEAVY_WEIGHTED_PRESSURE_PLATE,
|
||||
IRON_DOOR,
|
||||
OAK_DOOR, BIRCH_DOOR, SPRUCE_DOOR, JUNGLE_DOOR, ACACIA_DOOR, DARK_OAK_DOOR,
|
||||
OAK_BUTTON, BIRCH_BUTTON, SPRUCE_BUTTON, JUNGLE_BUTTON, ACACIA_BUTTON, DARK_OAK_BUTTON,
|
||||
STONE_BUTTON,
|
||||
OAK_TRAPDOOR, BIRCH_TRAPDOOR, SPRUCE_TRAPDOOR, JUNGLE_TRAPDOOR, ACACIA_TRAPDOOR, DARK_OAK_TRAPDOOR,
|
||||
IRON_TRAPDOOR,
|
||||
LADDER,
|
||||
LEVER,
|
||||
MELON_STEM,
|
||||
NETHER_WART,
|
||||
PISTON,
|
||||
STICKY_PISTON,
|
||||
NETHER_PORTAL,
|
||||
POTATO,
|
||||
POWERED_RAIL,
|
||||
PUMPKIN_STEM,
|
||||
RAIL,
|
||||
COMPARATOR,
|
||||
REDSTONE_TORCH,
|
||||
REDSTONE_WIRE,
|
||||
RED_MUSHROOM,
|
||||
SUNFLOWER,
|
||||
*getMaterialsWithWoodTypePrefix("BUTTON"),
|
||||
STONE_BUTTON, LEVER,
|
||||
*getMaterialsWithWoodTypePrefix("DOOR"), IRON_DOOR,
|
||||
ACTIVATOR_RAIL, POWERED_RAIL, DETECTOR_RAIL, RAIL,
|
||||
PISTON, STICKY_PISTON,
|
||||
REDSTONE_TORCH, REDSTONE_WALL_TORCH, REDSTONE_WIRE,
|
||||
TRIPWIRE, TRIPWIRE_HOOK,
|
||||
|
||||
BROWN_MUSHROOM, RED_MUSHROOM, CACTUS, CARROT, COCOA,
|
||||
WHEAT, DEAD_BUSH, CHORUS_FLOWER, DANDELION, SUGAR_CANE,
|
||||
TALL_GRASS, TALL_SEAGRASS, NETHER_WART, MELON_STEM,
|
||||
PUMPKIN_STEM, SUNFLOWER, POTATO, LILY_PAD, VINE,
|
||||
*getMaterialsWithWoodTypePrefix("SAPLING"),
|
||||
|
||||
SAND, RED_SAND, DRAGON_EGG, ANVIL,
|
||||
*getMaterialsWithWoolColorPrefix("CONCRETE_POWDER"),
|
||||
|
||||
*getMaterialsWithWoolColorPrefix("CARPET"),
|
||||
CAKE, FIRE,
|
||||
FLOWER_POT,
|
||||
LADDER,
|
||||
// NETHER_PORTAL, fuck nether portals
|
||||
FLOWER_POT,
|
||||
CHORUS_FLOWER,
|
||||
OAK_SAPLING, BIRCH_SAPLING, SPRUCE_SAPLING, JUNGLE_SAPLING, ACACIA_SAPLING, DARK_OAK_SAPLING,
|
||||
SIGN,
|
||||
SNOW,
|
||||
SPRUCE_DOOR,
|
||||
STONE_BUTTON,
|
||||
SUGAR_CANE,
|
||||
TORCH,
|
||||
TRIPWIRE,
|
||||
TRIPWIRE_HOOK,
|
||||
VINE,
|
||||
WHITE_BANNER, ORANGE_BANNER, MAGENTA_BANNER, LIGHT_BLUE_BANNER, YELLOW_BANNER, LIME_BANNER, PINK_BANNER, GRAY_BANNER, LIGHT_GRAY_BANNER, CYAN_BANNER, PURPLE_BANNER, BLUE_BANNER, BROWN_BANNER, GREEN_BANNER, RED_BANNER, BLACK_BANNER,
|
||||
WHITE_WALL_BANNER, ORANGE_WALL_BANNER, MAGENTA_WALL_BANNER, LIGHT_BLUE_WALL_BANNER, YELLOW_WALL_BANNER, LIME_WALL_BANNER, PINK_WALL_BANNER, GRAY_WALL_BANNER, LIGHT_GRAY_WALL_BANNER, CYAN_WALL_BANNER, PURPLE_WALL_BANNER, BLUE_WALL_BANNER, BROWN_WALL_BANNER, GREEN_WALL_BANNER, RED_WALL_BANNER, BLACK_WALL_BANNER,
|
||||
WALL_SIGN,
|
||||
LILY_PAD,
|
||||
DANDELION
|
||||
)
|
||||
TORCH, WALL_TORCH,
|
||||
*getMaterialsWithWoolColorPrefix("BANNER"),
|
||||
*getMaterialsWithWoolColorPrefix("WALL_BANNER"),
|
||||
SIGN, WALL_SIGN
|
||||
)
|
||||
|
||||
fun isAttachable(type: Material) = attachables.contains(type)
|
||||
|
||||
fun supportingBlock(data: BlockData): Vec3i = when (data) {
|
||||
//is MultipleFacing -> // fuck it xD this is good enough
|
||||
|
||||
is Directional -> Vec3i.convert(when (data.material) {
|
||||
// exceptions
|
||||
COCOA -> data.facing
|
||||
OAK_DOOR, BIRCH_DOOR, SPRUCE_DOOR, JUNGLE_DOOR, ACACIA_DOOR, DARK_OAK_DOOR, IRON_DOOR -> BlockFace.DOWN
|
||||
|
||||
else -> data.facing.oppositeFace
|
||||
})
|
||||
|
||||
else -> Vec3i.down
|
||||
}
|
||||
|
||||
@@ -2,64 +2,291 @@ package io.dico.parcels2.blockvisitor
|
||||
|
||||
import io.dico.parcels2.util.Region
|
||||
import io.dico.parcels2.util.Vec3i
|
||||
import io.dico.parcels2.util.ext.clampMax
|
||||
|
||||
abstract class RegionTraverser {
|
||||
fun traverseRegion(region: Region): Iterable<Vec3i> = Iterable { iterator<Vec3i> { build(region) } }
|
||||
private typealias Scope = SequenceScope<Vec3i>
|
||||
|
||||
protected abstract suspend fun SequenceScope<Vec3i>.build(region: Region)
|
||||
sealed class RegionTraverser {
|
||||
fun traverseRegion(region: Region, worldHeight: Int = 256): Iterable<Vec3i> =
|
||||
Iterable { iterator<Vec3i> { build(validify(region, worldHeight)) } }
|
||||
|
||||
private fun validify(region: Region, worldHeight: Int): Region {
|
||||
if (region.origin.y < 0) {
|
||||
val origin = region.origin withY 0
|
||||
val size = region.size.withY((region.size.y + region.origin.y).clampMax(worldHeight))
|
||||
return Region(origin, size)
|
||||
}
|
||||
|
||||
if (region.origin.y + region.size.y > worldHeight) {
|
||||
val size = region.size.withY(worldHeight - region.origin.y)
|
||||
return Region(region.origin, size)
|
||||
}
|
||||
|
||||
return region
|
||||
}
|
||||
|
||||
protected abstract suspend fun Scope.build(region: Region)
|
||||
|
||||
companion object {
|
||||
val upward = create { traverseUpward(it) }
|
||||
val downward = create { traverseDownward(it) }
|
||||
val forClearing get() = downward
|
||||
val forFilling get() = upward
|
||||
val upward = Directional(TraverseDirection(1, 1, 1), TraverseOrder(Dimension.Y, Dimension.X))
|
||||
val downward = Directional(TraverseDirection(1, -1, 1), TraverseOrder(Dimension.Y, Dimension.X))
|
||||
val toClear get() = downward
|
||||
val toFill get() = upward
|
||||
|
||||
inline fun create(crossinline builder: suspend SequenceScope<Vec3i>.(Region) -> Unit) = object : RegionTraverser() {
|
||||
override suspend fun SequenceScope<Vec3i>.build(region: Region) {
|
||||
builder(region)
|
||||
}
|
||||
fun convergingTo(y: Int) = Slicing(y, upward, downward, true)
|
||||
|
||||
fun separatingFrom(y: Int) = Slicing(y, downward, upward, false)
|
||||
}
|
||||
|
||||
class Directional(
|
||||
val direction: TraverseDirection,
|
||||
val order: TraverseOrder
|
||||
) : RegionTraverser() {
|
||||
override suspend fun Scope.build(region: Region) {
|
||||
//traverserLogic(region, order, direction)
|
||||
}
|
||||
|
||||
private suspend fun SequenceScope<Vec3i>.traverseDownward(region: Region) {
|
||||
val origin = region.origin
|
||||
val size = region.size
|
||||
repeat(size.y) { y ->
|
||||
repeat(size.z) { z ->
|
||||
repeat(size.x) { x ->
|
||||
yield(origin.add(x, size.y - y - 1, z))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun SequenceScope<Vec3i>.traverseUpward(region: Region) {
|
||||
val origin = region.origin
|
||||
val size = region.size
|
||||
repeat(size.y) { y ->
|
||||
repeat(size.z) { z ->
|
||||
repeat(size.x) { x ->
|
||||
yield(origin.add(x, size.y - y - 1, z))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
class Slicing(
|
||||
val bottomSectionMaxY: Int,
|
||||
val bottomTraverser: RegionTraverser,
|
||||
val topTraverser: RegionTraverser,
|
||||
val bottomFirst: Boolean = true
|
||||
) : RegionTraverser() {
|
||||
|
||||
private fun slice(region: Region, atY: Int): Pair<Region, Region?> {
|
||||
if (atY < region.size.y + 1) {
|
||||
val first = Region(region.origin, region.size.withY(atY + 1))
|
||||
val second = Region(region.origin.withY(atY), region.size.addY(-atY-1))
|
||||
val second = Region(region.origin.withY(atY), region.size.addY(-atY - 1))
|
||||
return first to second
|
||||
}
|
||||
return region to null
|
||||
}
|
||||
|
||||
fun upToAndDownUntil(y: Int) = create { region ->
|
||||
val (bottom, top) = slice(region, y)
|
||||
traverseUpward(bottom)
|
||||
top?.let { traverseDownward(it) }
|
||||
override suspend fun Scope.build(region: Region) {
|
||||
val (bottom, top) = slice(region, bottomSectionMaxY)
|
||||
|
||||
if (bottomFirst) {
|
||||
with(bottomTraverser) { build(bottom) }
|
||||
top?.let { with(topTraverser) { build(it) } }
|
||||
} else {
|
||||
top?.let { with(topTraverser) { build(it) } }
|
||||
with(bottomTraverser) { build(bottom) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
enum class Dimension {
|
||||
X,
|
||||
Y,
|
||||
Z;
|
||||
|
||||
fun extract(block: Vec3i) =
|
||||
when (this) {
|
||||
X -> block.x
|
||||
Y -> block.y
|
||||
Z -> block.z
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val values = values()
|
||||
operator fun get(ordinal: Int) = values[ordinal]
|
||||
}
|
||||
}
|
||||
|
||||
inline class TraverseOrder(val orderNum: Int) {
|
||||
private constructor(first: Dimension, swap: Boolean)
|
||||
: this(if (swap) first.ordinal + 3 else first.ordinal)
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
private inline fun element(index: Int) = Dimension[(orderNum + index) % 3]
|
||||
|
||||
private val swap inline get() = orderNum >= 3
|
||||
|
||||
/**
|
||||
* The slowest changing dimension
|
||||
*/
|
||||
val primary: Dimension get() = element(0)
|
||||
|
||||
/**
|
||||
* Second slowest changing dimension
|
||||
*/
|
||||
val secondary: Dimension get() = element(if (swap) 2 else 1)
|
||||
|
||||
/**
|
||||
* Dimension that changes every block
|
||||
*/
|
||||
val tertiary: Dimension get() = element(if (swap) 1 else 2)
|
||||
|
||||
/**
|
||||
* All 3 dimensions in this order
|
||||
*/
|
||||
fun toArray() = arrayOf(primary, secondary, tertiary)
|
||||
|
||||
companion object {
|
||||
private fun isSwap(primary: Dimension, secondary: Dimension) = secondary.ordinal != (primary.ordinal + 1) % 3
|
||||
|
||||
operator fun invoke(primary: Dimension, secondary: Dimension): TraverseOrder {
|
||||
// tertiary is implicit
|
||||
if (primary == secondary) throw IllegalArgumentException()
|
||||
return TraverseOrder(primary, isSwap(primary, secondary))
|
||||
}
|
||||
}
|
||||
|
||||
fun add(vec: Vec3i, dp: Int, ds: Int, dt: Int): Vec3i =
|
||||
// optimize this, will be called lots
|
||||
when (orderNum) {
|
||||
0 -> vec.add(dp, ds, dt) // xyz
|
||||
1 -> vec.add(dt, dp, ds) // yzx
|
||||
2 -> vec.add(ds, dt, dp) // zxy
|
||||
3 -> vec.add(dp, dt, ds) // xzy
|
||||
4 -> vec.add(ds, dp, dt) // yxz
|
||||
5 -> vec.add(dt, ds, dp) // zyx
|
||||
else -> error("Invalid orderNum $orderNum")
|
||||
}
|
||||
}
|
||||
|
||||
class AltTraverser(val size: Vec3i,
|
||||
val order: TraverseOrder,
|
||||
val direction: TraverseDirection) {
|
||||
|
||||
|
||||
suspend fun Scope.build() {
|
||||
doPrimary()
|
||||
}
|
||||
|
||||
private suspend fun Scope.doPrimary() {
|
||||
val dimension = order.primary
|
||||
direction.directionOf(dimension).traverse(dimension.extract(size)) { value ->
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private fun Dimension.setValue(value: Int) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
enum class Increment(val offset: Int) {
|
||||
UP(1),
|
||||
DOWN(-1);
|
||||
|
||||
companion object {
|
||||
fun convert(bool: Boolean) = if (bool) UP else DOWN
|
||||
}
|
||||
|
||||
inline fun traverse(size: Int, op: (Int) -> Unit) {
|
||||
when (this) {
|
||||
UP -> repeat(size, op)
|
||||
DOWN -> repeat(size) { op(size - it - 1) }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
inline class TraverseDirection(val bits: Int) {
|
||||
|
||||
fun directionOf(dimension: Dimension) = Increment.convert((1 shl dimension.ordinal) and bits != 0)
|
||||
|
||||
companion object {
|
||||
operator fun invoke(x: Int, y: Int, z: Int) = invoke(Vec3i(x, y, z))
|
||||
|
||||
operator fun invoke(block: Vec3i): TraverseDirection {
|
||||
if (block.x == 0 || block.y == 0 || block.z == 0) throw IllegalArgumentException()
|
||||
var bits = 0
|
||||
if (block.x > 0) bits = bits or 1
|
||||
if (block.y > 0) bits = bits or 2
|
||||
if (block.z > 0) bits = bits or 3
|
||||
return TraverseDirection(bits)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
private typealias Scope = SequenceScope<Vec3i>
|
||||
private typealias ScopeAction = suspend Scope.(Int, Int, Int) -> Unit
|
||||
|
||||
@Suppress("NON_EXHAUSTIVE_WHEN")
|
||||
suspend fun Scope.traverserLogic(
|
||||
region: Region,
|
||||
order: TraverseOrder,
|
||||
direction: TraverseDirection
|
||||
) = with(direction) {
|
||||
val (primary, secondary, tertiary) = order.toArray()
|
||||
val (origin, size) = region
|
||||
|
||||
when (order.primary) {
|
||||
Dimension.X ->
|
||||
when (order.secondary) {
|
||||
Dimension.Y -> {
|
||||
directionOf(primary).traverse(primary.extract(size)) { p ->
|
||||
directionOf(secondary).traverse(secondary.extract(size)) { s ->
|
||||
directionOf(tertiary).traverse(tertiary.extract(size)) { t ->
|
||||
yield(origin.add(p, s, t))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Dimension.Z -> {
|
||||
directionOf(primary).traverse(primary.extract(size)) { p ->
|
||||
directionOf(secondary).traverse(secondary.extract(size)) { s ->
|
||||
directionOf(tertiary).traverse(tertiary.extract(size)) { t ->
|
||||
yield(origin.add(p, t, s))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Dimension.Y ->
|
||||
when (order.secondary) {
|
||||
Dimension.X -> {
|
||||
directionOf(primary).traverse(primary.extract(size)) { p ->
|
||||
directionOf(secondary).traverse(secondary.extract(size)) { s ->
|
||||
directionOf(tertiary).traverse(tertiary.extract(size)) { t ->
|
||||
yield(origin.add(s, p, t))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Dimension.Z -> {
|
||||
directionOf(primary).traverse(primary.extract(size)) { p ->
|
||||
directionOf(secondary).traverse(secondary.extract(size)) { s ->
|
||||
directionOf(tertiary).traverse(tertiary.extract(size)) { t ->
|
||||
yield(origin.add(t, p, s))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Dimension.Z ->
|
||||
when (order.secondary) {
|
||||
Dimension.X -> {
|
||||
directionOf(primary).traverse(primary.extract(size)) { p ->
|
||||
directionOf(secondary).traverse(secondary.extract(size)) { s ->
|
||||
directionOf(tertiary).traverse(tertiary.extract(size)) { t ->
|
||||
yield(origin.add(s, t, p))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Dimension.Y -> {
|
||||
directionOf(primary).traverse(primary.extract(size)) { p ->
|
||||
directionOf(secondary).traverse(secondary.extract(size)) { s ->
|
||||
directionOf(tertiary).traverse(tertiary.extract(size)) { t ->
|
||||
yield(origin.add(t, s, p))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
@@ -3,9 +3,13 @@ package io.dico.parcels2.blockvisitor
|
||||
import io.dico.parcels2.util.Region
|
||||
import io.dico.parcels2.util.Vec3i
|
||||
import io.dico.parcels2.util.get
|
||||
import org.bukkit.Bukkit
|
||||
import org.bukkit.Material
|
||||
import org.bukkit.World
|
||||
import org.bukkit.block.data.BlockData
|
||||
|
||||
private val air = Bukkit.createBlockData(Material.AIR)
|
||||
|
||||
// TODO order paste such that attachables are placed after the block they depend on
|
||||
class Schematic {
|
||||
val size: Vec3i get() = _size!!
|
||||
@@ -15,15 +19,17 @@ class Schematic {
|
||||
field = value
|
||||
}
|
||||
|
||||
private var _data: Array<BlockData?>? = null
|
||||
private var blockDatas: Array<BlockData?>? = null
|
||||
//private var extra: Map<Vec3i, (Block) -> Unit>? = null
|
||||
private var isLoaded = false; private set
|
||||
private val traverser: RegionTraverser = RegionTraverser.upward
|
||||
|
||||
fun getLoadTask(world: World, region: Region): TimeLimitedTask = {
|
||||
val size = region.size.also { _size = it }
|
||||
val data = arrayOfNulls<BlockData>(region.blockCount).also { _data = it }
|
||||
_size = region.size
|
||||
|
||||
val data = arrayOfNulls<BlockData>(region.blockCount).also { blockDatas = it }
|
||||
//val extra = mutableMapOf<Vec3i, (Block) -> Unit>().also { extra = it }
|
||||
val blocks = RegionTraverser.downward.traverseRegion(region)
|
||||
val blocks = traverser.traverseRegion(region)
|
||||
|
||||
for ((index, vec) in blocks.withIndex()) {
|
||||
markSuspensionPoint()
|
||||
@@ -39,14 +45,26 @@ class Schematic {
|
||||
fun getPasteTask(world: World, position: Vec3i): TimeLimitedTask = {
|
||||
if (!isLoaded) throw IllegalStateException()
|
||||
val region = Region(position, _size!!)
|
||||
val blocks = RegionTraverser.downward.traverseRegion(region)
|
||||
val data = _data!!
|
||||
val blocks = traverser.traverseRegion(region, worldHeight = world.maxHeight)
|
||||
val blockDatas = blockDatas!!
|
||||
|
||||
val postponed = mutableListOf<Pair<Vec3i, BlockData>>()
|
||||
|
||||
for ((index, vec) in blocks.withIndex()) {
|
||||
markSuspensionPoint()
|
||||
val block = world[vec]
|
||||
if (block.y > 255) continue
|
||||
data[index]?.let { block.blockData = it }
|
||||
val type = blockDatas[index] ?: air
|
||||
if (type !== air && isAttachable(type.material)) {
|
||||
|
||||
|
||||
postponed += vec to type
|
||||
} else {
|
||||
block.blockData = type
|
||||
}
|
||||
}
|
||||
|
||||
for ((vec, data) in postponed) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,8 @@ import io.dico.parcels2.blockvisitor.RegionTraverser
|
||||
import io.dico.parcels2.doBlockOperation
|
||||
import org.bukkit.Bukkit
|
||||
import org.bukkit.Material
|
||||
import org.bukkit.block.BlockFace
|
||||
import org.bukkit.block.data.Directional
|
||||
import org.bukkit.entity.Player
|
||||
import java.util.Random
|
||||
|
||||
@@ -55,4 +57,19 @@ class CommandsDebug(plugin: ParcelsPlugin) : AbstractParcelCommands(plugin) {
|
||||
}
|
||||
}
|
||||
|
||||
@Cmd("directionality", aliases = ["dir"])
|
||||
fun cmdDirectionality(sender: Player, context: ExecutionContext, material: Material): Any? {
|
||||
val senderLoc = sender.location
|
||||
val block = senderLoc.add(senderLoc.direction.setY(0).normalize().multiply(2).toLocation(sender.world)).block
|
||||
|
||||
val blockData = Bukkit.createBlockData(material)
|
||||
if (blockData is Directional) {
|
||||
blockData.facing = BlockFace.SOUTH
|
||||
}
|
||||
|
||||
block.blockData = blockData
|
||||
return if (blockData is Directional) "The block is facing south" else "The block is not directional, however it implements " +
|
||||
blockData.javaClass.interfaces!!.contentToString()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -162,7 +162,7 @@ class DefaultParcelGenerator(
|
||||
override val worktimeLimiter: WorktimeLimiter
|
||||
) : ParcelBlockManagerBase(), CoroutineScope by coroutineScope {
|
||||
override val world: World = this@DefaultParcelGenerator.world
|
||||
override val parcelTraverser: RegionTraverser = RegionTraverser.upToAndDownUntil(o.floorHeight)
|
||||
override val parcelTraverser: RegionTraverser = RegionTraverser.convergingTo(o.floorHeight)
|
||||
|
||||
/*override*/ fun getBottomBlock(parcel: ParcelId): Vec2i = Vec2i(
|
||||
sectionSize * (parcel.x - 1) + pathOffset + o.offsetX,
|
||||
|
||||
@@ -33,7 +33,7 @@ class ParcelEntityTracker(val parcelProvider: ParcelProvider) {
|
||||
remove()
|
||||
|
||||
val newParcel = parcelProvider.getParcelAt(entity.location)
|
||||
if (newParcel !== parcel && !(newParcel != null && newParcel.hasBlockVisitors)) {
|
||||
if (newParcel !== parcel && (newParcel == null || !newParcel.hasBlockVisitors)) {
|
||||
entity.remove()
|
||||
}
|
||||
|
||||
@@ -41,14 +41,13 @@ class ParcelEntityTracker(val parcelProvider: ParcelProvider) {
|
||||
}
|
||||
|
||||
val newParcel = parcelProvider.getParcelAt(entity.location)
|
||||
if (newParcel !== parcel && !(newParcel != null && newParcel.hasBlockVisitors)) {
|
||||
if (newParcel !== parcel && (newParcel == null || !newParcel.hasBlockVisitors)) {
|
||||
remove()
|
||||
entity.remove()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("RedundantLambdaArrow")
|
||||
fun swapParcels(parcel1: Parcel, parcel2: Parcel) {
|
||||
map.editLoop { ->
|
||||
if (value === parcel1) {
|
||||
|
||||
@@ -196,11 +196,10 @@ class ParcelListeners(
|
||||
when (event.action) {
|
||||
Action.RIGHT_CLICK_BLOCK -> run {
|
||||
val type = clickedBlock.type
|
||||
val interactable = Interactables.listedMaterials.containsKey(type)
|
||||
&& (parcel.effectiveInteractableConfig.isInteractable(type) || (parcel != null && parcel.canBuild(user)))
|
||||
if (!interactable) {
|
||||
val interactableClassName = Interactables[type]!!.name
|
||||
user.sendParcelMessage(nopermit = true, message = "You cannot interact with $interactableClassName in this parcel")
|
||||
|
||||
val interactableClass = Interactables[type]
|
||||
if (interactableClass != null && (parcel.effectiveInteractableConfig.isInteractable(type) || (parcel != null && parcel.canBuild(user)))) {
|
||||
user.sendParcelMessage(nopermit = true, message = "You cannot interact with ${interactableClass.name} in this parcel")
|
||||
event.isCancelled = true
|
||||
return@l
|
||||
}
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
package io.dico.parcels2.util
|
||||
|
||||
import kotlinx.coroutines.CancellableContinuation
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.Delay
|
||||
import kotlinx.coroutines.Runnable
|
||||
import kotlinx.coroutines.timeunit.TimeUnit
|
||||
import org.bukkit.plugin.Plugin
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
abstract class MainThreadDispatcher : CoroutineDispatcher() {
|
||||
abstract class MainThreadDispatcher : CoroutineDispatcher(), Delay {
|
||||
abstract val mainThread: Thread
|
||||
abstract fun runOnMainThread(task: Runnable)
|
||||
}
|
||||
@@ -27,5 +30,14 @@ fun MainThreadDispatcher(plugin: Plugin): MainThreadDispatcher {
|
||||
if (Thread.currentThread() === mainThread) task.run()
|
||||
else plugin.server.scheduler.runTaskLater(plugin, task, 0)
|
||||
}
|
||||
|
||||
override fun scheduleResumeAfterDelay(time: Long, unit: TimeUnit, continuation: CancellableContinuation<Unit>) {
|
||||
val task = Runnable {
|
||||
with (continuation) { resumeUndispatched(Unit) }
|
||||
}
|
||||
|
||||
val millis = TimeUnit.MILLISECONDS.convert(time, unit)
|
||||
plugin.server.scheduler.runTaskLater(plugin, task, (millis + 25) / 50 - 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package io.dico.parcels2.util
|
||||
|
||||
import org.bukkit.World
|
||||
import org.bukkit.block.Block
|
||||
import org.bukkit.block.BlockFace
|
||||
|
||||
data class Vec3d(
|
||||
val x: Double,
|
||||
@@ -32,6 +33,27 @@ data class Vec3i(
|
||||
infix fun withY(o: Int) = Vec3i(x, o, z)
|
||||
infix fun withZ(o: Int) = Vec3i(x, y, o)
|
||||
fun add(ox: Int, oy: Int, oz: Int) = Vec3i(x + ox, y + oy, z + oz)
|
||||
fun neg() = Vec3i(-x, -y, -z)
|
||||
|
||||
companion object {
|
||||
private operator fun invoke(face: BlockFace) = Vec3i(face.modX, face.modY, face.modZ)
|
||||
val down = Vec3i(BlockFace.DOWN)
|
||||
val up = Vec3i(BlockFace.UP)
|
||||
val north = Vec3i(BlockFace.NORTH)
|
||||
val east = Vec3i(BlockFace.EAST)
|
||||
val south = Vec3i(BlockFace.SOUTH)
|
||||
val west = Vec3i(BlockFace.WEST)
|
||||
|
||||
fun convert(face: BlockFace) = when (face) {
|
||||
BlockFace.DOWN -> down
|
||||
BlockFace.UP -> up
|
||||
BlockFace.NORTH -> north
|
||||
BlockFace.EAST -> east
|
||||
BlockFace.SOUTH -> south
|
||||
BlockFace.WEST -> west
|
||||
else -> Vec3i(face)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
|
||||
Reference in New Issue
Block a user