Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions src/main/kotlin/xyz/atrius/waystones/service/KeyService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import org.bukkit.event.player.PlayerInteractEvent
import org.bukkit.inventory.EquipmentSlot
import org.bukkit.inventory.ItemStack
import org.bukkit.inventory.meta.CompassMeta
import org.bukkit.persistence.PersistentDataType
import org.koin.core.annotation.Single
import xyz.atrius.waystones.data.config.property.EnableKeyItemsProperty
import xyz.atrius.waystones.data.config.property.PortalSicknessWarpingProperty
Expand Down Expand Up @@ -41,10 +42,8 @@ class KeyService(
}

fun isWarpKey(key: ItemStack) = when (enableKeyItems.value()) {
true -> key.itemMeta?.get("is_warp_key") == 1
else ->
key.type == Material.COMPASS &&
(key.itemMeta as? CompassMeta)?.lodestone != null
true -> key.itemMeta?.get("is_warp_key", PersistentDataType.INTEGER) == 1
else -> key.type == Material.COMPASS && (key.itemMeta as? CompassMeta)?.lodestone != null
}

private fun validateKey(player: Player, key: ItemStack): Either<KeyServiceError, Location> = either {
Expand Down
63 changes: 57 additions & 6 deletions src/main/kotlin/xyz/atrius/waystones/service/LinkService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,18 @@ import org.bukkit.block.Block
import org.bukkit.entity.Player
import org.bukkit.inventory.ItemStack
import org.bukkit.inventory.meta.CompassMeta
import org.bukkit.persistence.PersistentDataType
import org.koin.core.annotation.Single
import xyz.atrius.waystones.data.config.property.RelinkableKeysProperty
import xyz.atrius.waystones.manager.LocalizationManager
import xyz.atrius.waystones.manager.LocalizedString
import xyz.atrius.waystones.provider.DefaultKeyProvider
import xyz.atrius.waystones.repository.WaystoneInfoRepository
import xyz.atrius.waystones.utility.addItemNaturally
import xyz.atrius.waystones.utility.get
import xyz.atrius.waystones.utility.locationCode
import xyz.atrius.waystones.utility.playSound
import xyz.atrius.waystones.utility.toKey
import xyz.atrius.waystones.utility.update

@Single
Expand All @@ -39,7 +42,42 @@ class LinkService(
val meta = ensureNotNull(item.itemMeta as? CompassMeta) {
LinkServiceError.Ignore
}
val info = waystoneInfoRepository
.getWaystone(block.location)
.get()
val metaName = meta["waystone_name", PersistentDataType.STRING]
val name = info?.name
// Determine if the key is being relinked to a different waystone
val isDifferentName = name != null && metaName != name
val isSameLocation = block.location == meta.lodestone
// A warp key having an existing waystone name in its metadata implies that the key was already
// linked once before. If this field is present and differs from the name of the waystone present
// on the database, and the location is the same, we can allow the key to be relinked to the waystone.
when (isSameLocation && isDifferentName) {
true -> updateWarpKey(player, item, block, name)
else -> linkNewWarpKey(player, item, block, name, meta).bind()
}
}

private fun updateWarpKey(
player: Player,
item: ItemStack,
block: Block,
name: String?,
) {
item.link(player, block, name)
player.playSound(Sound.ITEM_LODESTONE_COMPASS_LOCK)
}

private fun linkNewWarpKey(
player: Player,
item: ItemStack,
block: Block,
name: String?,
meta: CompassMeta,
): Either<LinkServiceError, Unit> = either {
// Check if the key already has a linked location. If relinking is
// disabled, we should not allow the user to relink the key.
if (!relinkableKeys.value()) {
ensure(!meta.hasLodestone()) {
LinkServiceError.NotRelinkable(localization)
Expand All @@ -52,20 +90,33 @@ class LinkService(
// Add item to players inventory
val key = defaultKeyProvider
.getKey(player)
.link(player, block)
.link(player, block, name)
// Add item and play sound
player.inventory.addItemNaturally(item, key)
player.playSound(Sound.ITEM_LODESTONE_COMPASS_LOCK)
}

private fun ItemStack.link(player: Player, block: Block) = update<CompassMeta> {
private fun ItemStack.link(player: Player, block: Block, name: String?) = update<CompassMeta> {
lodestone = block.location
isLodestoneTracked = true

val name = waystoneInfoRepository
.getWaystone(block.location)
.thenApplyAsync { it?.name ?: localization["unnamed-waystone"].format(player) }
val lore = localization["link-key-lore", name.get(), lodestone?.locationCode]
if (!name.isNullOrEmpty()) {
val displayName = localization["key-name"]
.format(player)
.let { "$it: ($name)" }
.let(Component::text)
this.displayName(displayName)
// Ensure the item has the waystone name set in its PDC
// We will need this later for verification if the user attempts to relink the key
persistentDataContainer.set(
"waystone_name".toKey(),
PersistentDataType.STRING,
name,
)
}

val name = name ?: localization["unnamed-waystone"].format(player)
val lore = localization["link-key-lore", name, lodestone?.locationCode]
.format(player)
.let(Component::text)

Expand Down
22 changes: 19 additions & 3 deletions src/main/kotlin/xyz/atrius/waystones/service/NameService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ import org.bukkit.block.Block
import org.bukkit.entity.Player
import org.bukkit.inventory.ItemStack
import org.koin.core.annotation.Single
import org.slf4j.LoggerFactory
import xyz.atrius.waystones.dao.WaystoneInfo
import xyz.atrius.waystones.repository.WaystoneInfoRepository
import xyz.atrius.waystones.utility.locationCode

@Single
class NameService(
Expand Down Expand Up @@ -45,10 +47,18 @@ class NameService(
val name = PlainTextComponentSerializer
.plainText()
.serialize(displayName)
val info = WaystoneInfo
.fromLocation(block.location, name)
val info = waystoneInfoRepository
.getWaystone(block.location)
.get()

ensure(name != info?.name) {
logger.debug("Waystone at ${block.location.locationCode} already has name '$name'! Skipping rename.")
NameServiceError.Ignore
}

waystoneInfoRepository.save(info)
val newInfo = WaystoneInfo
.fromLocation(block.location, name)
waystoneInfoRepository.save(newInfo)

if (player.gameMode != GameMode.CREATIVE) {
item.amount--
Expand All @@ -61,4 +71,10 @@ class NameService(

object Ignore : NameServiceError()
}

companion object {

private val logger = LoggerFactory
.getLogger(NameService::class.java.name)
}
}
13 changes: 4 additions & 9 deletions src/main/kotlin/xyz/atrius/waystones/utility/Item.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,14 @@ import org.bukkit.inventory.ItemStack
import org.bukkit.inventory.PlayerInventory
import org.bukkit.inventory.meta.ItemMeta
import org.bukkit.persistence.PersistentDataType
import org.bukkit.persistence.PersistentDataType.INTEGER

operator fun ItemMeta.get(key: String) =
persistentDataContainer.get(key.toKey(), INTEGER)
operator fun <T : Any> ItemMeta.get(key: String, type: PersistentDataType<T, T>) =
persistentDataContainer
.get(key.toKey(), type)

operator fun <T> ItemMeta.set(key: String, type: PersistentDataType<T, T>, value: T) =
persistentDataContainer
.set(
key.toKey(),
type,
value
?: error("Value must be provided!")
)
.set(key.toKey(), type, value ?: error("Value must be provided!"))

fun PlayerInventory.addItemNaturally(original: ItemStack, new: ItemStack) {
val player = holder as Player
Expand Down