Skip to content

Commit

Permalink
Merge pull request #27 from AtriusX/dev/custom-key-recipe
Browse files Browse the repository at this point in the history
  • Loading branch information
AtriusX authored Jun 28, 2021
2 parents c0ab38c + 301b549 commit b874cbb
Show file tree
Hide file tree
Showing 10 changed files with 84 additions and 32 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ Please note that this recipe is only used if **enable-key-items** is set to `tru
- **portal-sickness-damage *[default: 5.0]***: The amount of damage (in heart pieces) taken by the user if warping while sick and DAMAGE_ON_TELEPORT is set.
- **relinkable-keys *[default: true]***: Whether or not warp keys can be relinked after they are linked to a waystone.
- **enable-key-items *[default: true]***: Whether or not to use a custom item for warp keys. This enables a custom crafting recipe for the item, and prevents normal compasses from being used as warp keys. If this setting is enabled later, compass warp keys *should* hopefully still work as warp keys.
- **key-recipe *[default: shown above]***: The crafting recipe used for custom key items if custom keys are enabled.

### Commands
- **/waystones**: Provides info about the plugin
Expand Down
11 changes: 8 additions & 3 deletions src/main/kotlin/xyz/atrius/waystones/data/Property.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import org.bukkit.configuration.file.FileConfiguration
import xyz.atrius.waystones.data.config.ArgumentParser
import xyz.atrius.waystones.data.config.ConfigManager
import xyz.atrius.waystones.plugin
import java.util.*
import kotlin.properties.Delegates.observable
import kotlin.reflect.KProperty

Expand All @@ -17,7 +18,7 @@ class Property<T>(
get() = plugin.config

private var value: T by observable(
parser.parse(config.getString(property))
parser.parse(config.get(property))
?: default.also { update(property, it) },
observe(property)
)
Expand All @@ -28,7 +29,7 @@ class Property<T>(

operator fun invoke(): T = value

operator fun invoke(input: String?): Boolean {
operator fun invoke(input: Any?): Boolean {
value = parser.parse(input) ?: return false
onUpdate()
return true
Expand All @@ -39,7 +40,11 @@ class Property<T>(
}

private fun <T> update(property: String, new: T) {
config.set(property, new.toString())
config.set(property, when (new) {
is Enum<*> -> new.name
is Locale -> new.toString()
else -> new
})
plugin.saveConfig()
}

Expand Down
7 changes: 7 additions & 0 deletions src/main/kotlin/xyz/atrius/waystones/data/config/Config.kt
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,13 @@ class Config(plugin: KotlinPlugin) {
val keyItems: Property<Boolean> =
Property("enable-key-items", true, BooleanParser)

val keyRecipe: Property<List<String>> =
Property("key-recipe", listOf(
"AIR", "IRON_INGOT", "AIR",
"IRON_INGOT", "REDSTONE_BLOCK", "IRON_INGOT",
"AIR", "IRON_INGOT", "AIR"
), ListParser(StringParser))

// Netherite grants the max amount of boost per block
fun netheriteBoost(): Int = maxBoost()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ object ConfigManager {
fun reload() {
plugin.reloadConfig()
for ((prop, option) in options) {
option(plugin.config.getString(prop))
option(plugin.config.get(prop))
}
}
}
39 changes: 23 additions & 16 deletions src/main/kotlin/xyz/atrius/waystones/data/config/Parsers.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package xyz.atrius.waystones.data.config

import java.util.Locale
import java.util.*
import kotlin.reflect.KClass

interface ArgumentParser<T> {
Expand All @@ -14,25 +14,25 @@ interface ArgumentParser<T> {
* @property T The parser return type. Null if error occurs.
* @return The parsed data, or null if an error occurred.
*/
fun parse(input: String?): T?
fun parse(input: Any?): T?

fun toString(value: T): String =
value.toString()
}

object StringParser : ArgumentParser<String> {
override fun parse(input: String?) = input
override fun parse(input: Any?) = input.toString()
}

sealed class IntParser : ArgumentParser<Int> {
override fun parse(input: String?): Int? = input?.toIntOrNull()
override fun parse(input: Any?): Int? = input?.toString()?.toIntOrNull()

companion object : IntParser()
}

object PositiveValueParser : IntParser() {

override fun parse(input: String?): Int? {
override fun parse(input: Any?): Int? {
val num = super.parse(input) ?: return null
return if (isValid(num)) num else null
}
Expand All @@ -41,33 +41,37 @@ object PositiveValueParser : IntParser() {
}

object DoubleParser : ArgumentParser<Double> {
override fun parse(input: String?): Double? = input?.toDoubleOrNull()
override fun parse(input: Any?): Double? = input?.toString()?.toDoubleOrNull()
}

object PercentageParser : ArgumentParser<Double> {
private val regex = "^[0-9]+(.[0-9]+)?%$".toRegex()

override fun parse(input: String?): Double? =
if (input?.matches(regex) == true)
input.dropLast(1).toDouble() / 100 else null
override fun parse(input: Any?): Double? {
val str = input?.toString()
return if (str?.matches(regex) == true)
str.dropLast(1).toDouble() / 100 else null
}

override fun toString(value: Double): String =
"${value * 100}%"
}

object BooleanParser : ArgumentParser<Boolean> {
override fun parse(input: String?): Boolean? =
if (input?.toLowerCase() in arrayOf("true", "false")) input.toBoolean() else null
override fun parse(input: Any?): Boolean? {
val str = input?.toString()
return if (str?.toLowerCase() in arrayOf("true", "false")) str?.toBoolean() else null
}
}

object LocaleParser : ArgumentParser<Locale> {
override fun parse(input: String?): Locale? = input?.let { Locale.forLanguageTag(input) }
override fun parse(input: Any?): Locale? = input?.let { Locale.forLanguageTag(input.toString()) }

override fun toString(value: Locale): String = value.toLanguageTag()
}

class EnumParser<E : Enum<E>>(private val enum: KClass<E>) : ArgumentParser<E> {
override fun parse(input: String?): E? {
override fun parse(input: Any?): E? {
input ?: return null
val values = enum.java.enumConstants
return values.firstOrNull { it.name == input }
Expand All @@ -76,10 +80,13 @@ class EnumParser<E : Enum<E>>(private val enum: KClass<E>) : ArgumentParser<E> {

class ListParser<T>(private val parser: ArgumentParser<T>) : ArgumentParser<List<T>> {
@Suppress("UNCHECKED_CAST")
override fun parse(input: String?): List<T>? {
override fun parse(input: Any?): List<T>? {
if (input is List<*>)
return input as List<T>?
val str = input?.toString()
// Parse data in either list or vararg form
val data = input?.removeSurrounding("[", "]")
?.split(" |, *".toRegex()) ?: return null
val data = str?.removeSurrounding("[", "]")
?.split("[ ,] *".toRegex()) ?: return null
val arr = mutableListOf<Any>()
// Populate the array
for (item in data)
Expand Down
31 changes: 20 additions & 11 deletions src/main/kotlin/xyz/atrius/waystones/data/crafting/CompassRecipe.kt
Original file line number Diff line number Diff line change
@@ -1,19 +1,28 @@
package xyz.atrius.waystones.data.crafting

import org.bukkit.Material
import xyz.atrius.waystones.utility.defaultWarpKey
import xyz.atrius.waystones.utility.toKey
import xyz.atrius.waystones.configuration
import xyz.atrius.waystones.utility.*

object CompassRecipe : CraftingRecipe("is_warp_key".toKey(), defaultWarpKey()) {

override val recipe = """
| *
|*x*
| *
""".trimMargin()
private val keyRecipe = configuration.keyRecipe()

override val items = hashMapOf(
'*' to Material.IRON_INGOT,
'x' to Material.REDSTONE_BLOCK
)
override val recipe = run {
// Pull recipe from config and determine grid size (list can be size 1, 4, or 9)
val size = sqrt(keyRecipe.size)
keyRecipe
// Map each item to it's hash char
.map(String::hashChar)
// Chunk the list by its square size
.chunked(size)
// Glue each list into a string and join each by a newline
.joinToString("\n", transform = List<Char>::glue)
}

override val items = hashMapOf<Char, Material>().apply {
// For each item in the recipe, map it's material to it's hashcode
for (item in keyRecipe.toHashSet())
this[item.hashChar()] = Material.valueOf(item)
}
}
1 change: 0 additions & 1 deletion src/main/kotlin/xyz/atrius/waystones/utility/Data.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import org.bukkit.block.Block
import org.bukkit.block.data.BlockData
import org.bukkit.inventory.ItemStack
import org.bukkit.inventory.meta.ItemMeta
import xyz.atrius.waystones.plugin

inline fun <reified T : BlockData> Block.update(scope: T.() -> Unit) = also {
val data = this.blockData as T
Expand Down
11 changes: 11 additions & 0 deletions src/main/kotlin/xyz/atrius/waystones/utility/Number.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package xyz.atrius.waystones.utility

import kotlin.math.sqrt as ktSqrt

// Helper function since kotlin doesn't have a native fixed-point square root
fun sqrt(value: Int): Int =
ktSqrt(value.toFloat()).toInt()

// Calculates the character representation of an object based on its hashcode
fun Any.hashChar(): Char =
hashCode().toChar()
3 changes: 3 additions & 0 deletions src/main/kotlin/xyz/atrius/waystones/utility/String.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,6 @@ fun String.toKey() = NamespacedKey(plugin, this)
// Split a multiline string into a spreadable array
fun String.splitMultiline() =
split("\n").toTypedArray()

// Glues a list together into a single string
fun <T> List<T>.glue(): String = joinToString("")
10 changes: 10 additions & 0 deletions src/main/resources/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,13 @@ portal-sickness-warping: DAMAGE_ON_TELEPORT
portal-sickness-damage: 5.0
relinkable-keys: true
enable-key-items: true
key-recipe:
- AIR
- IRON_INGOT
- AIR
- IRON_INGOT
- REDSTONE_BLOCK
- IRON_INGOT
- AIR
- IRON_INGOT
- AIR

0 comments on commit b874cbb

Please sign in to comment.