Skip to content
Open
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
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -114,4 +114,5 @@ buildNumber.properties
# Common working directory
run/
build/
.gradle/
.gradle/
.kotlin/
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class AnimationManager(

private val animations = hashMapOf<Player, TeleportEffect>()

fun register(effect: TeleportEffect, player: Player, to: Location, onComplete: () -> Unit = {}) = effect.run {
fun register(effect: TeleportEffect, player: Player, to: Location, onComplete: () -> Unit = {}): Int = effect.run {
effect.start()
animations[player] = effect
plugin.scheduleRepeatingAutoCancelTask(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,23 @@ class SimpleTeleportEffect(
private val localization: LocalizationManager,
) : TeleportEffect {

companion object {
private const val TICKS_PER_SECOND = 20.0
private const val PARTICLE_MULTIPLIER = 2
private const val BASE_SMOKE_COUNT = 250
private const val END_SMOKE_COUNT = 400
}

private val bar = BossBar.bossBar(
Component.text("Wait Time"),
1f,
BossBar.Color.RED,
BossBar.Overlay.PROGRESS
)
private val bossBarColors = listOf(
BossBar.Color.GREEN,
BossBar.Color.RED,
BossBar.Color.RED,
)
private val textColors = listOf(
NamedTextColor.GREEN,
NamedTextColor.RED,
NamedTextColor.DARK_RED,
private val colorPairs = listOf(
BossBar.Color.GREEN to NamedTextColor.GREEN,
BossBar.Color.RED to NamedTextColor.RED,
BossBar.Color.RED to NamedTextColor.DARK_RED,
)

override fun start() {
Expand All @@ -48,27 +50,27 @@ class SimpleTeleportEffect(

override fun animation(timer: Long, max: Long) {
val player = warp.player
val seconds = ceil(timer / 20.0).toInt()
val seconds = ceil(timer / TICKS_PER_SECOND).toInt()
val progress = timer.toFloat() / waitTime.value().toFloat()
val color = (progress * bossBarColors.size)
val colorIndex = (progress * colorPairs.size)
.toInt()
.coerceIn(0, bossBarColors.size - 1)
.coerceIn(0, colorPairs.size - 1)
val (barColor, textColor) = colorPairs[colorIndex]
val waitMessage = localization["warp-wait", warp.name, seconds]
.format(player)
.let(Component::text)
.color(textColors[color])
.color(textColor)

bar
.name(waitMessage)
.progress(progress)
.color(bossBarColors[color])
// Play warp animation if enabled
.color(barColor)
if (!warpAnimations.value()) {
return
}

val amp = waitTime.value() - timer + 0.1
val ratio = timer * 2 + 1
val ratio = timer * PARTICLE_MULTIPLIER + 1
val period = (System.currentTimeMillis() / 3).toDouble()
val world = player.world

Expand All @@ -80,7 +82,7 @@ class SimpleTeleportEffect(
world.forceParticle(
particle = Particle.LARGE_SMOKE,
location = player.location,
count = 250 / ratio.toInt(),
count = BASE_SMOKE_COUNT / ratio.toInt(),
offsetX = 0.2,
offsetY = 0.5,
offsetZ = 0.2,
Expand All @@ -97,13 +99,12 @@ class SimpleTeleportEffect(
warp.player.world.forceParticle(
particle = Particle.LARGE_SMOKE,
location = location.UP.center,
count = 400,
count = END_SMOKE_COUNT,
offsetX = 0.2,
offsetY = 0.5,
offsetZ = 0.2,
extra = 0.1
)
// Warp sound effects
location.playSound(Sound.ENTITY_STRAY_DEATH, 0.5f, 0f)
location.playSound(Sound.BLOCK_BELL_RESONATE, 1f, 0f)
location.playSound(Sound.BLOCK_RESPAWN_ANCHOR_DEPLETE)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,21 @@ import org.bukkit.Bukkit
import org.bukkit.World
import org.bukkit.command.CommandSender
import org.bukkit.entity.Player
import org.koin.core.annotation.Provided
import org.koin.core.annotation.Single
import xyz.atrius.waystones.dao.WaystoneInfo
import xyz.atrius.waystones.internal.KotlinPlugin
import xyz.atrius.waystones.manager.LocalizationManager
import xyz.atrius.waystones.repository.WaystoneInfoRepository
import xyz.atrius.waystones.utility.center
import xyz.atrius.waystones.utility.message
import xyz.atrius.waystones.utility.runOnMainThread
import xyz.atrius.waystones.utility.translateColors
import java.util.UUID
import kotlin.math.ceil

@Single
class ListCommand(
@Provided private val plugin: KotlinPlugin,
private val waystoneInfoRepository: WaystoneInfoRepository,
private val localization: LocalizationManager,
) : WaystoneSubcommand {
Expand All @@ -47,7 +50,7 @@ class ListCommand(

override fun build(base: ArgumentBuilder<CommandSourceStack, *>): ArgumentBuilder<CommandSourceStack, *> = base
.then(
argument("page", IntegerArgumentType.integer(1, pageCount()))
argument("page", IntegerArgumentType.integer(1, Int.MAX_VALUE))
.executes {
val page = it.getArgument("page", Int::class.java)

Expand All @@ -58,39 +61,48 @@ class ListCommand(

private fun listEntries(sender: CommandSender, page: Int = 1): Int {
val offset = (page - 1) * PAGE_SIZE
val waystones = waystoneInfoRepository

waystoneInfoRepository
.getAll(PAGE_SIZE, offset)
.get()
val unnamedWaystone = localization["unnamed-waystone"]
.format(sender as? Player)
.thenAccept { waystones ->
renderEntries(sender, waystones, page)
}

if (waystones.isEmpty()) {
emptyWaystoneList(sender, page)
return Command.SINGLE_SUCCESS
}
return Command.SINGLE_SUCCESS
}

private fun renderEntries(sender: CommandSender, waystones: List<WaystoneInfo>, page: Int) {
plugin.runOnMainThread {
val unnamedWaystone = localization["unnamed-waystone"]
.format(sender as? Player)

sender.message(localization["plugin-header"])
if (waystones.isEmpty()) {
emptyWaystoneList(sender, page)
return@runOnMainThread
}

val worlds = mutableMapOf<UUID, World?>()
val hover = localization["waystone-list-hover"]
.format(sender as? Player)
.let(Component::text)
sender.message(localization["plugin-header"])

for (info in waystones) {
val world = worlds
.computeIfAbsent(info.worldUid) { Bukkit.getWorld(info.worldUid) }
?: continue
val entry = getTeleportComponent(world.name, info, hover) {
click(sender, world, info)
val worlds = mutableMapOf<UUID, World?>()
val hover = localization["waystone-list-hover"]
.format(sender as? Player)
.let(Component::text)

for (info in waystones) {
val world = worlds
.computeIfAbsent(info.worldUid) { Bukkit.getWorld(info.worldUid) }
?: continue
val entry = getTeleportComponent(world.name, info, hover) {
click(sender, world, info)
}
.appendSpace()
.append(getNameComponent(info, unnamedWaystone))

sender.sendMessage(entry)
}
.appendSpace()
.append(getNameComponent(info, unnamedWaystone))

sender.sendMessage(entry)
sender.message(localization["plugin-footer"])
}

sender.message(localization["plugin-footer"])
return Command.SINGLE_SUCCESS
}

fun click(sender: CommandSender, world: World, info: WaystoneInfo) {
Expand All @@ -106,12 +118,6 @@ class ListCommand(
sender.playSound(teleportSound)
}

private fun pageCount(): Int = waystoneInfoRepository
.entries()
.thenApplyAsync { ceil(it.toDouble() / PAGE_SIZE).toInt() }
.get()
.coerceAtLeast(1)

private fun emptyWaystoneList(sender: CommandSender, page: Int) = when (page) {
1 -> sender.message(localization["waystone-list-empty"])
else -> sender.message(localization["waystone-list-no-entries", page])
Expand Down
4 changes: 3 additions & 1 deletion src/main/kotlin/xyz/atrius/waystones/data/JsonFile.kt
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ open class JsonFile<T : Any>(
logger.error("Failed to load configuration file: ${e.message}")
}

data = gson.fromJson(FileReader(file), type.java)
data = FileReader(file).use { reader ->
gson.fromJson(reader, type.java)
}
logger.info("Loaded ${file.name} successfully!")
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ object MaterialTypeAdapter : JsonSerializer<Material>, JsonDeserializer<Material
val key = json.asString

return entries.firstOrNull {
it.key.asString().equals(key, true)
it.key.asString().equals(key, ignoreCase = true)
}
}
}
13 changes: 8 additions & 5 deletions src/main/kotlin/xyz/atrius/waystones/data/struct/StackSet.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,13 @@ class StackSet<E>(initialData: List<E>) : HashMap<E, Int>() {
}

override fun remove(key: E): Int? {
this[key] = this[key]
?.minus(1)
?: 0

return this[key]
val current = this[key] ?: return null
return if (current <= 1) {
super.remove(key)
0
} else {
this[key] = current - 1
current - 1
}
}
}
18 changes: 11 additions & 7 deletions src/main/kotlin/xyz/atrius/waystones/event/InfoEvent.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,20 @@ import org.bukkit.event.EventHandler
import org.bukkit.event.Listener
import org.bukkit.event.block.Action
import org.bukkit.event.player.PlayerInteractEvent
import org.koin.core.annotation.Provided
import org.koin.core.annotation.Single
import xyz.atrius.waystones.internal.KotlinPlugin
import xyz.atrius.waystones.manager.LocalizationManager
import xyz.atrius.waystones.repository.WaystoneInfoRepository
import xyz.atrius.waystones.service.KeyService
import xyz.atrius.waystones.service.WaystoneService
import xyz.atrius.waystones.utility.cancel
import xyz.atrius.waystones.utility.runOnMainThread
import xyz.atrius.waystones.utility.sendActionMessage

@Single
class InfoEvent(
@Provided private val plugin: KotlinPlugin,
private val localization: LocalizationManager,
private val keyService: KeyService,
private val waystoneService: WaystoneService,
Expand All @@ -23,7 +27,6 @@ class InfoEvent(

@EventHandler(ignoreCancelled = true)
fun onClick(event: PlayerInteractEvent) {
// Filter non left-click events
if (event.action != Action.LEFT_CLICK_BLOCK) {
return
}
Expand All @@ -32,22 +35,23 @@ class InfoEvent(
val player = event.player
val item = event.item
?: return
// Make sure the correct block/item pair is used
if (block?.type != Material.LODESTONE || !keyService.isWarpKey(item)) {
return
}

val name = waystoneInfoRepository
.getWaystone(block.location)
.thenApplyAsync { it?.name ?: localization["unnamed-waystone"].format(player) }
// Skip any non-warp blocks
val state = waystoneService
.getWarpState(player, block)
?.message()
?.format(player)
?: return

player.sendActionMessage(localization["waystone-info", name.get(), state])
waystoneInfoRepository
.getWaystone(block.location)
.thenApplyAsync { it?.name ?: localization["unnamed-waystone"].format(player) }
.runOnMainThread(plugin) { name ->
player.sendActionMessage(localization["waystone-info", name, state])
}

event.cancel()
}
}
4 changes: 2 additions & 2 deletions src/main/kotlin/xyz/atrius/waystones/event/LinkEvent.kt
Original file line number Diff line number Diff line change
Expand Up @@ -40,17 +40,17 @@ class LinkEvent(
}

player.sendActionError(it.message())
event.cancel()
}
// Check if an entry exists already before saving the waystone again
waystoneInfoRepository
.existsByLocation(block.location)
.thenApplyAsync { exists ->
.thenAccept { exists ->
// If the location isn't present in the database, it should be safe to write
if (!exists) {
waystoneInfoRepository.save(WaystoneInfo.fromLocation(block.location))
}
}

advancementManager.awardAdvancement(player, waystonesAdvancement)
event.cancel()
// This is silly but due to https://github.com/PaperMC/Paper/issues/12954 the inventory is getting
Expand Down
4 changes: 2 additions & 2 deletions src/main/kotlin/xyz/atrius/waystones/event/NameEvent.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import xyz.atrius.waystones.advancement.QuantumDomesticationAdvancement
import xyz.atrius.waystones.manager.AdvancementManager
import xyz.atrius.waystones.manager.LocalizationManager
import xyz.atrius.waystones.service.NameService
import arrow.core.getOrElse
import xyz.atrius.waystones.utility.cancel
import xyz.atrius.waystones.utility.foldResult
import xyz.atrius.waystones.utility.sendActionMessage

@Single
Expand All @@ -33,7 +33,7 @@ class NameEvent(
val block = event.clickedBlock
val name = nameService
.process(player, item, block ?: return)
.foldResult { return }
.getOrElse { return }

player.sendActionMessage(localization["waystone-set-name", name])
player.playSound(player.location, Sound.BLOCK_RESPAWN_ANCHOR_SET_SPAWN, 1f, 2f)
Expand Down
Loading
Loading