diff --git a/build.sbt b/build.sbt index 162ee35e1d..58838bfced 100644 --- a/build.sbt +++ b/build.sbt @@ -6,7 +6,7 @@ import java.io._ ThisBuild / scalaVersion := "2.13.1" // ThisBuild / version はGitHub Actionsによって自動更新される。 // 次の行は ThisBuild / version := "(\d*)" の形式でなければならない。 -ThisBuild / version := "8" +ThisBuild / version := "10" ThisBuild / organization := "click.seichi" ThisBuild / description := "ギガンティック☆整地鯖の独自要素を司るプラグイン" diff --git a/docker/spigot/serverfiles/start-server.sh b/docker/spigot/serverfiles/start-server.sh index 22ac887a55..c9a23c140c 100644 --- a/docker/spigot/serverfiles/start-server.sh +++ b/docker/spigot/serverfiles/start-server.sh @@ -10,7 +10,7 @@ mkdir -p /spigot/plugins/SeichiAssist/ cd /spigot/plugins/SeichiAssist rm config.yml || true -jar xf ../SeichiAssist-*.jar config.yml +jar xf ../SeichiAssist.jar config.yml cd /spigot/plugins/SeichiAssist diff --git a/src/main/scala/com/github/unchama/seichiassist/listener/PlayerBlockBreakListener.scala b/src/main/scala/com/github/unchama/seichiassist/listener/PlayerBlockBreakListener.scala index bbd762268c..adcfd64d45 100644 --- a/src/main/scala/com/github/unchama/seichiassist/listener/PlayerBlockBreakListener.scala +++ b/src/main/scala/com/github/unchama/seichiassist/listener/PlayerBlockBreakListener.scala @@ -187,7 +187,7 @@ class PlayerBlockBreakListener(implicit effectEnvironment: EffectEnvironment, val effectPrograms = for { ((blocks, lavas), chunkIndex) <- multiBreakList.zip(multiLavaList).zipWithIndex - blockChunk = BukkitResources.vanishingBlockSetResource(blocks) + blockChunk = BukkitResources.vanishingBlockSetResource[IO, BlockBreakableBySkill](blocks) } yield { SeichiAssist.instance.lockedBlockChunkScope.useTracked(blockChunk) { blocks => for { diff --git a/src/main/scala/com/github/unchama/seichiassist/listener/PlayerClickListener.scala b/src/main/scala/com/github/unchama/seichiassist/listener/PlayerClickListener.scala index beed9d979e..fb26df2a40 100644 --- a/src/main/scala/com/github/unchama/seichiassist/listener/PlayerClickListener.scala +++ b/src/main/scala/com/github/unchama/seichiassist/listener/PlayerClickListener.scala @@ -104,10 +104,10 @@ class PlayerClickListener(implicit effectEnvironment: EffectEnvironment, activeSkillAvailability(player).set(true).coerceTo[IO] >> soundEffectAfterCoolDown - val arrowEffect = playerData.skillEffectState.selection.arrowEffect(player) + val arrowEffect = playerData.skillEffectState.selection.arrowEffect effectEnvironment.unsafeRunEffectAsync("スキルのクールダウンの状態を戻す", controlSkillAvailability) - effectEnvironment.unsafeRunEffectAsync("ArrowEffectを非同期で実行する", arrowEffect) + effectEnvironment.unsafeRunEffectAsync("ArrowEffectを非同期で実行する", arrowEffect.run(player)) case _ => } } diff --git a/src/main/scala/com/github/unchama/seichiassist/seichiskill/effect/ActiveSkillEffect.scala b/src/main/scala/com/github/unchama/seichiassist/seichiskill/effect/ActiveSkillEffect.scala index 106e558639..7d67046830 100644 --- a/src/main/scala/com/github/unchama/seichiassist/seichiskill/effect/ActiveSkillEffect.scala +++ b/src/main/scala/com/github/unchama/seichiassist/seichiskill/effect/ActiveSkillEffect.scala @@ -25,7 +25,7 @@ import scala.util.Random sealed trait ActiveSkillEffect { val nameOnUI: String - val arrowEffect: TargetedEffect[Player] + def arrowEffect(implicit ioOnMainThread: OnMinecraftServerThread[IO]): TargetedEffect[Player] def runBreakEffect(player: Player, usedSkill: ActiveSkill, @@ -39,7 +39,8 @@ object ActiveSkillEffect { object NoEffect extends ActiveSkillEffect { override val nameOnUI: String = "未設定" - override val arrowEffect: TargetedEffect[Player] = ArrowEffects.normalArrowEffect + override def arrowEffect(implicit ioOnMainThread: OnMinecraftServerThread[IO]): TargetedEffect[Player] = + ArrowEffects.normalArrowEffect override def runBreakEffect(player: Player, usedSkill: ActiveSkill, @@ -171,7 +172,7 @@ sealed abstract class ActiveSkillNormalEffect(stringId: String, /** * エフェクト選択時の遠距離エフェクト */ - lazy val arrowEffect: TargetedEffect[Player] = + override def arrowEffect(implicit ioOnMainThread: OnMinecraftServerThread[IO]): TargetedEffect[Player] = this match { case Explosion => ArrowEffects.singleArrowExplosionEffect case Blizzard => ArrowEffects.singleArrowBlizzardEffect @@ -246,7 +247,7 @@ sealed abstract class ActiveSkillPremiumEffect(stringId: String, _ <- IO.sleep(period.ticks) _ <- SeichiAssist.instance.magicEffectEntityScope - .useTrackedForSome(BukkitResources.vanishingEntityResource(centerBreak, classOf[Chicken])) { e => + .useTrackedForSome(BukkitResources.vanishingEntityResource[IO, Chicken](centerBreak, classOf[Chicken])) { e => for { _ <- IO { e.playEffect(EntityEffect.WITCH_MAGIC) @@ -270,7 +271,7 @@ sealed abstract class ActiveSkillPremiumEffect(stringId: String, /** * エフェクト選択時の遠距離エフェクト */ - lazy val arrowEffect: TargetedEffect[Player] = + override def arrowEffect(implicit ioOnMainThread: OnMinecraftServerThread[IO]): TargetedEffect[Player] = this match { case ActiveSkillPremiumEffect.MAGIC => ArrowEffects.singleArrowMagicEffect } diff --git a/src/main/scala/com/github/unchama/seichiassist/seichiskill/effect/arrow/ArrowEffects.scala b/src/main/scala/com/github/unchama/seichiassist/seichiskill/effect/arrow/ArrowEffects.scala index 311893ab6f..f685b006f2 100644 --- a/src/main/scala/com/github/unchama/seichiassist/seichiskill/effect/arrow/ArrowEffects.scala +++ b/src/main/scala/com/github/unchama/seichiassist/seichiskill/effect/arrow/ArrowEffects.scala @@ -2,6 +2,7 @@ package com.github.unchama.seichiassist.seichiskill.effect.arrow import cats.data.Kleisli import cats.effect.{IO, SyncIO} +import com.github.unchama.minecraft.actions.OnMinecraftServerThread import com.github.unchama.seichiassist.SeichiAssist import com.github.unchama.seichiassist.concurrent.PluginExecutionContexts import com.github.unchama.targetedeffect.player.FocusedSoundEffect @@ -24,22 +25,25 @@ object ArrowEffects { implicit val plugin: JavaPlugin = SeichiAssist.instance - val normalArrowEffect: TargetedEffect[Player] = arrowEffect[Arrow]( - ProjectileSpawnConfiguration( - 1.0, - (0.0, 1.6, 0.0) - ), - Some(Sound.ENTITY_ARROW_SHOOT) - ) - - val singleArrowBlizzardEffect: TargetedEffect[Player] = arrowEffect[Snowball]( - ProjectileSpawnConfiguration( - 1.0, - (0.0, 1.6, 0.0) - ), - Some(Sound.ENTITY_SNOWBALL_THROW) - ) - val singleArrowMagicEffect: TargetedEffect[Player] = { + def normalArrowEffect(implicit mainThread: OnMinecraftServerThread[IO]) : TargetedEffect[Player] = + arrowEffect[Arrow]( + ProjectileSpawnConfiguration( + 1.0, + (0.0, 1.6, 0.0) + ), + Some(Sound.ENTITY_ARROW_SHOOT) + ) + + def singleArrowBlizzardEffect(implicit mainThread: OnMinecraftServerThread[IO]): TargetedEffect[Player] = + arrowEffect[Snowball]( + ProjectileSpawnConfiguration( + 1.0, + (0.0, 1.6, 0.0) + ), + Some(Sound.ENTITY_SNOWBALL_THROW) + ) + + def singleArrowMagicEffect(implicit mainThread: OnMinecraftServerThread[IO]): TargetedEffect[Player] = { import scala.util.chaining._ val thrownPotionItem = new ItemStack(Material.SPLASH_POTION).tap { itemStack => itemStack.setItemMeta { @@ -60,7 +64,7 @@ object ArrowEffects { ) } - val singleArrowMeteoEffect: TargetedEffect[Player] = + def singleArrowMeteoEffect(implicit mainThread: OnMinecraftServerThread[IO]): TargetedEffect[Player] = arrowEffect[Arrow]( ProjectileSpawnConfiguration( 1.0, @@ -70,7 +74,7 @@ object ArrowEffects { _.setGlowing(true) ) - val singleArrowExplosionEffect: TargetedEffect[Player] = + def singleArrowExplosionEffect(implicit mainThread: OnMinecraftServerThread[IO]): TargetedEffect[Player] = arrowEffect[SmallFireball]( ProjectileSpawnConfiguration( 0.4, @@ -79,9 +83,12 @@ object ArrowEffects { Some(Sound.ENTITY_GHAST_SHOOT) ) - def arrowEffect[P <: Projectile : ClassTag](spawnConfiguration: ProjectileSpawnConfiguration, - sound: Option[Sound] = None, - projectileModifier: P => Unit = (_: P) => ()): TargetedEffect[Player] = { + def arrowEffect[ + P <: Projectile : ClassTag + ](spawnConfiguration: ProjectileSpawnConfiguration, + sound: Option[Sound] = None, + projectileModifier: P => Unit = (_: P) => ()) + (implicit mainThread: OnMinecraftServerThread[IO]): TargetedEffect[Player] = { val runtimeClass = implicitly[ClassTag[P]].runtimeClass.asInstanceOf[Class[P]] @@ -117,7 +124,7 @@ object ArrowEffects { * サーバーが停止したときにも開放するためである。 */ _ <- SeichiAssist.instance.arrowSkillProjectileScope - .useTracked(BukkitResources.vanishingEntityResource(spawnLocation, runtimeClass)) { projectile => + .useTracked(BukkitResources.vanishingEntityResource[IO, P](spawnLocation, runtimeClass)) { projectile => modifyProjectile(projectile) >> waitForCollision } } yield () diff --git a/src/main/scala/com/github/unchama/util/effect/BukkitResources.scala b/src/main/scala/com/github/unchama/util/effect/BukkitResources.scala index 337ea92252..07ff01f68b 100644 --- a/src/main/scala/com/github/unchama/util/effect/BukkitResources.scala +++ b/src/main/scala/com/github/unchama/util/effect/BukkitResources.scala @@ -1,6 +1,7 @@ package com.github.unchama.util.effect -import cats.effect.{IO, Resource} +import cats.effect.{Resource, Sync, SyncIO} +import com.github.unchama.minecraft.actions.OnMinecraftServerThread import org.bukkit.block.Block import org.bukkit.entity.Entity import org.bukkit.{Location, Material} @@ -9,21 +10,39 @@ object BukkitResources { /** * 参照された`Block`達が開放時に空気ブロックに書き換えられるような`Resource`としての`Block` */ - def vanishingBlockSetResource[B <: Block](reference: Set[B]): Resource[IO, Set[B]] = + def vanishingBlockSetResource[ + F[_] : Sync : OnMinecraftServerThread, + B <: Block + ](referenceSet: Set[B]): Resource[F, Set[B]] = Resource.make( - IO(reference) + Sync[F].delay(referenceSet) )(block => - IO { block.foreach(_.setType(Material.AIR)) } + OnMinecraftServerThread[F].runAction[SyncIO, Unit] { + SyncIO { + block.foreach(_.setType(Material.AIR)) + } + } ) /** * 確保された`Entity`が開放時に除去されるような`Resource`としての`Entity` */ - def vanishingEntityResource[E <: Entity](spawnLocation: Location, tag: Class[E]): Resource[IO, E] = { + def vanishingEntityResource[ + F[_] : Sync : OnMinecraftServerThread, + E <: Entity + ](spawnLocation: Location, tag: Class[E]): Resource[F, E] = { Resource.make( - IO(spawnLocation.getWorld.spawn(spawnLocation, tag)) + OnMinecraftServerThread[F].runAction[SyncIO, E] { + SyncIO { + spawnLocation.getWorld.spawn(spawnLocation, tag) + } + } )(e => - IO(e.remove()) + OnMinecraftServerThread[F].runAction[SyncIO, Unit] { + SyncIO { + e.remove() + } + } ) } }