Archived
0

Add interactable api

This commit is contained in:
Dico
2018-08-17 10:59:19 +01:00
parent 5bd0970c54
commit 48e1d86fcb
4 changed files with 166 additions and 2 deletions

View 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
}
}

View File

@@ -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()
}

View File

@@ -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
}
}

View File

@@ -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)
)