Add interactable api
This commit is contained in:
106
src/main/kotlin/io/dico/parcels2/Interactable.kt
Normal file
106
src/main/kotlin/io/dico/parcels2/Interactable.kt
Normal file
@@ -0,0 +1,106 @@
|
||||
package io.dico.parcels2
|
||||
|
||||
import io.dico.parcels2.util.findWoodKindPrefixedMaterials
|
||||
import org.bukkit.Material
|
||||
import java.util.EnumMap
|
||||
|
||||
class Interactables
|
||||
private constructor(val id: Int,
|
||||
val name: String,
|
||||
val interactableByDefault: Boolean,
|
||||
vararg val materials: Material) {
|
||||
|
||||
companion object {
|
||||
val classesById: List<Interactables>
|
||||
val classesByName: Map<String, Interactables>
|
||||
val listedMaterials: Map<Material, Int>
|
||||
|
||||
init {
|
||||
val array = getClassesArray()
|
||||
classesById = array.asList()
|
||||
classesByName = mapOf(*array.map { it.name to it }.toTypedArray())
|
||||
listedMaterials = EnumMap(mapOf(*array.flatMap { clazz -> clazz.materials.map { it to clazz.id } }.toTypedArray()))
|
||||
}
|
||||
|
||||
private fun getClassesArray() = run {
|
||||
var id = 0
|
||||
@Suppress("UNUSED_CHANGED_VALUE")
|
||||
arrayOf(
|
||||
Interactables(id++, "button", true,
|
||||
Material.STONE_BUTTON,
|
||||
*findWoodKindPrefixedMaterials("BUTTON")),
|
||||
|
||||
Interactables(id++, "lever", true,
|
||||
Material.LEVER),
|
||||
|
||||
Interactables(id++, "pressure_plate", true,
|
||||
Material.STONE_PRESSURE_PLATE,
|
||||
*findWoodKindPrefixedMaterials("PRESSURE_PLATE"),
|
||||
Material.HEAVY_WEIGHTED_PRESSURE_PLATE,
|
||||
Material.LIGHT_WEIGHTED_PRESSURE_PLATE),
|
||||
|
||||
Interactables(id++, "redstone_components", false,
|
||||
Material.COMPARATOR,
|
||||
Material.REPEATER),
|
||||
|
||||
Interactables(id++, "containers", false,
|
||||
Material.CHEST,
|
||||
Material.TRAPPED_CHEST,
|
||||
Material.DISPENSER,
|
||||
Material.DROPPER,
|
||||
Material.HOPPER,
|
||||
Material.FURNACE)
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
interface InteractableConfiguration {
|
||||
val interactableClasses: List<Interactables> get() = Interactables.classesById.filter { isInteractable(it) }
|
||||
fun isInteractable(material: Material): Boolean
|
||||
fun isInteractable(clazz: Interactables): Boolean
|
||||
fun setInteractable(clazz: Interactables, interactable: Boolean): Boolean
|
||||
fun clear(): Boolean
|
||||
fun copyFrom(other: InteractableConfiguration) {
|
||||
Interactables.classesById.forEach { setInteractable(it, other.isInteractable(it)) }
|
||||
}
|
||||
}
|
||||
|
||||
class BitmaskInteractableConfiguration : InteractableConfiguration {
|
||||
val bitmaskArray = IntArray((Interactables.classesById.size + 31) / 32)
|
||||
|
||||
private fun isBitSet(classId: Int): Boolean {
|
||||
val idx = classId.ushr(5)
|
||||
return idx < bitmaskArray.size && bitmaskArray[idx].and(0x1.shl(classId.and(0x1F))) != 0
|
||||
}
|
||||
|
||||
override fun isInteractable(material: Material): Boolean {
|
||||
val classId = Interactables.listedMaterials[material] ?: return false
|
||||
return isBitSet(classId) != Interactables.classesById[classId].interactableByDefault
|
||||
}
|
||||
|
||||
override fun isInteractable(clazz: Interactables): Boolean {
|
||||
return isBitSet(clazz.id) != clazz.interactableByDefault
|
||||
}
|
||||
|
||||
override fun setInteractable(clazz: Interactables, interactable: Boolean): Boolean {
|
||||
val idx = clazz.id.ushr(5)
|
||||
if (idx >= bitmaskArray.size) return false
|
||||
val bit = 0x1.shl(clazz.id.and(0x1F))
|
||||
val oldBitmask = bitmaskArray[idx]
|
||||
bitmaskArray[idx] = if (interactable != clazz.interactableByDefault) oldBitmask.or(bit) else oldBitmask.and(bit.inv())
|
||||
return bitmaskArray[idx] != oldBitmask
|
||||
}
|
||||
|
||||
override fun clear(): Boolean {
|
||||
var change = false
|
||||
for (i in bitmaskArray.indices) {
|
||||
change = change || bitmaskArray[i] != 0
|
||||
bitmaskArray[i] = 0
|
||||
}
|
||||
return change
|
||||
}
|
||||
|
||||
}
|
||||
@@ -39,6 +39,7 @@ interface ParcelData : AddedData {
|
||||
var owner: PlayerProfile?
|
||||
val lastClaimTime: DateTime?
|
||||
var ownerSignOutdated: Boolean
|
||||
var interactableConfig: InteractableConfiguration
|
||||
|
||||
fun canBuild(player: OfflinePlayer, checkAdmin: Boolean = true, checkGlobal: Boolean = true): Boolean
|
||||
|
||||
@@ -54,8 +55,8 @@ interface ParcelData : AddedData {
|
||||
}
|
||||
}
|
||||
|
||||
class ParcelDataHolder(addedMap: MutableAddedDataMap = mutableMapOf()) : AddedDataHolder(addedMap), ParcelData {
|
||||
|
||||
class ParcelDataHolder(addedMap: MutableAddedDataMap = mutableMapOf())
|
||||
: ParcelData, AddedDataHolder(addedMap) {
|
||||
override var owner: PlayerProfile? = null
|
||||
override var lastClaimTime: DateTime? = null
|
||||
override var ownerSignOutdated = false
|
||||
@@ -65,5 +66,6 @@ class ParcelDataHolder(addedMap: MutableAddedDataMap = mutableMapOf()) : AddedDa
|
||||
|
||||
override var allowInteractInputs = true
|
||||
override var allowInteractInventory = true
|
||||
override var interactableConfig: InteractableConfiguration = BitmaskInteractableConfiguration()
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import io.dico.dicore.Formatting
|
||||
import io.dico.parcels2.*
|
||||
import io.dico.parcels2.util.Vec2i
|
||||
import io.dico.parcels2.util.alsoIfTrue
|
||||
import org.bukkit.Material
|
||||
import org.bukkit.OfflinePlayer
|
||||
import org.joda.time.DateTime
|
||||
import kotlin.reflect.KProperty
|
||||
@@ -90,6 +91,29 @@ class ParcelImpl(override val world: ParcelWorld,
|
||||
data.allowInteractInventory = value
|
||||
}
|
||||
|
||||
private var _interactableConfig: InteractableConfiguration? = null
|
||||
override var interactableConfig: InteractableConfiguration
|
||||
get() {
|
||||
if (_interactableConfig == null) {
|
||||
_interactableConfig = object : InteractableConfiguration {
|
||||
override fun isInteractable(material: Material): Boolean = data.interactableConfig.isInteractable(material)
|
||||
override fun isInteractable(clazz: Interactables): Boolean = data.interactableConfig.isInteractable(clazz)
|
||||
|
||||
override fun setInteractable(clazz: Interactables, interactable: Boolean): Boolean = data.interactableConfig.setInteractable(clazz, interactable).alsoIfTrue {
|
||||
// TODO update storage
|
||||
}
|
||||
|
||||
override fun clear(): Boolean = data.interactableConfig.clear().alsoIfTrue {
|
||||
// TODO update storage
|
||||
}
|
||||
}
|
||||
}
|
||||
return _interactableConfig!!
|
||||
}
|
||||
set(value) {
|
||||
data.interactableConfig.copyFrom(value)
|
||||
// TODO update storage
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -74,3 +74,35 @@ val Material.isWoodButton
|
||||
DARK_OAK_BUTTON -> true
|
||||
else -> false
|
||||
}
|
||||
|
||||
private fun getMaterialPrefixed(prefix: String, name: String): Material {
|
||||
return Material.getMaterial("${prefix}_$name") ?: throw IllegalArgumentException("Material ${prefix}_$name doesn't exist")
|
||||
}
|
||||
|
||||
fun findWoodKindPrefixedMaterials(name: String) = arrayOf(
|
||||
getMaterialPrefixed("OAK", name),
|
||||
getMaterialPrefixed("BIRCH", name),
|
||||
getMaterialPrefixed("SPRUCE", name),
|
||||
getMaterialPrefixed("JUNGLE", name),
|
||||
getMaterialPrefixed("ACACIA", name),
|
||||
getMaterialPrefixed("DARK_OAK", name)
|
||||
)
|
||||
|
||||
fun findColorPrefixedMaterials(name: String) = arrayOf(
|
||||
getMaterialPrefixed("WHITE", name),
|
||||
getMaterialPrefixed("ORANGE", name),
|
||||
getMaterialPrefixed("MAGENTA", name),
|
||||
getMaterialPrefixed("LIGHT_BLUE", name),
|
||||
getMaterialPrefixed("YELLOW", name),
|
||||
getMaterialPrefixed("LIME", name),
|
||||
getMaterialPrefixed("PINK", name),
|
||||
getMaterialPrefixed("GRAY", name),
|
||||
getMaterialPrefixed("LIGHT_GRAY", name),
|
||||
getMaterialPrefixed("CYAN", name),
|
||||
getMaterialPrefixed("PURPLE", name),
|
||||
getMaterialPrefixed("BLUE", name),
|
||||
getMaterialPrefixed("BROWN", name),
|
||||
getMaterialPrefixed("GREEN", name),
|
||||
getMaterialPrefixed("RED", name),
|
||||
getMaterialPrefixed("BLACK", name)
|
||||
)
|
||||
Reference in New Issue
Block a user