From 34387d9779dc3d662fab25ef2773efdc26f5da6f Mon Sep 17 00:00:00 2001 From: KisaragiEffective <kisaragi.effective@gmail.com> Date: Thu, 1 Apr 2021 18:15:56 +0900 Subject: [PATCH 01/73] =?UTF-8?q?[update]=20subhome=E3=82=92=E3=82=B5?= =?UTF-8?q?=E3=83=96=E3=82=B7=E3=82=B9=E3=83=86=E3=83=A0=E3=81=A8=E3=81=97?= =?UTF-8?q?=E3=81=A6=E5=88=87=E3=82=8A=E5=87=BA=E3=81=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../unchama/seichiassist/SeichiAssist.scala | 12 ++- .../seichiassist/data/player/PlayerData.scala | 34 +------- .../seichiassist/data/subhome/SubHome.java | 24 ------ .../unchama/seichiassist/menus/HomeMenu.scala | 78 +++++++++-------- .../seichiassist/menus/TopLevelRouter.scala | 4 +- .../subsystems/subhome/System.scala | 32 +++++++ .../bukkit/command}/SubHomeCommand.scala | 76 ++++++++++++----- .../subsystems/subhome/domain/SubHome.scala | 12 +++ .../infrastructure/SubHomePersistence.scala | 84 +++++++++++++++++++ .../seichiassist/task/PlayerDataLoading.scala | 29 ------- .../task/PlayerDataSaveTask.scala | 32 ------- 11 files changed, 243 insertions(+), 174 deletions(-) delete mode 100644 src/main/scala/com/github/unchama/seichiassist/data/subhome/SubHome.java create mode 100644 src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/System.scala rename src/main/scala/com/github/unchama/seichiassist/{commands => subsystems/subhome/bukkit/command}/SubHomeCommand.scala (60%) create mode 100644 src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/domain/SubHome.scala create mode 100644 src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/SubHomePersistence.scala diff --git a/src/main/scala/com/github/unchama/seichiassist/SeichiAssist.scala b/src/main/scala/com/github/unchama/seichiassist/SeichiAssist.scala index cdd40dfcc2..11439b3144 100644 --- a/src/main/scala/com/github/unchama/seichiassist/SeichiAssist.scala +++ b/src/main/scala/com/github/unchama/seichiassist/SeichiAssist.scala @@ -54,6 +54,8 @@ import com.github.unchama.seichiassist.subsystems.mana.{ManaApi, ManaReadApi} import com.github.unchama.seichiassist.subsystems.managedfly.ManagedFlyApi import com.github.unchama.seichiassist.subsystems.present.infrastructure.GlobalPlayerAccessor import com.github.unchama.seichiassist.subsystems.seasonalevents.api.SeasonalEventsAPI +import com.github.unchama.seichiassist.subsystems.subhome.bukkit.command.SubHomeCommand +import com.github.unchama.seichiassist.subsystems.subhome.infrastructure.SubHomeReadAPI import com.github.unchama.seichiassist.task.PlayerDataSaveTask import com.github.unchama.seichiassist.task.global._ import com.github.unchama.util.{ActionStatus, ClassUtils} @@ -357,6 +359,14 @@ class SeichiAssist extends JavaPlugin() { subsystems.present.System.wired } + lazy val subhomeSystem: subhome.System[IO] = { + import PluginExecutionContexts.{asyncShift, onMainThread} + + implicit val effectEnvironment: EffectEnvironment = DefaultEffectEnvironment + implicit val concurrentEffect: ConcurrentEffect[IO] = IO.ioConcurrentEffect(asyncShift) + subhome.System.wired + } + //endregion private implicit val _akkaSystem: ActorSystem = ConfiguredActorSystemProvider("reference.conf").provide() @@ -457,6 +467,7 @@ class SeichiAssist extends JavaPlugin() { implicit val fourDimensionalPocketApi: FourDimensionalPocketApi[IO, Player] = fourDimensionalPocketSystem.api implicit val gachaPointApi: GachaPointApi[IO, SyncIO, Player] = gachaPointSystem.api implicit val manaApi: ManaApi[IO, SyncIO, Player] = manaSystem.manaApi + implicit val subHomeReadApi: SubHomeReadAPI[IO] = subhomeSystem.api val menuRouter = TopLevelRouter.apply import menuRouter.canOpenStickMenu @@ -486,7 +497,6 @@ class SeichiAssist extends JavaPlugin() { "rmp" -> RmpCommand.executor, "shareinv" -> ShareInvCommand.executor, "halfguard" -> HalfBlockProtectCommand.executor, - "subhome" -> SubHomeCommand.executor, "gtfever" -> GiganticFeverCommand.executor, "minehead" -> new MineHeadCommand().executor, "x-transfer" -> RegionOwnerTransferCommand.executor, diff --git a/src/main/scala/com/github/unchama/seichiassist/data/player/PlayerData.scala b/src/main/scala/com/github/unchama/seichiassist/data/player/PlayerData.scala index 378c364a49..353810b834 100644 --- a/src/main/scala/com/github/unchama/seichiassist/data/player/PlayerData.scala +++ b/src/main/scala/com/github/unchama/seichiassist/data/player/PlayerData.scala @@ -7,9 +7,9 @@ import com.github.unchama.seichiassist._ import com.github.unchama.seichiassist.achievement.Nicknames import com.github.unchama.seichiassist.data.GridTemplate import com.github.unchama.seichiassist.data.player.settings.PlayerSettings -import com.github.unchama.seichiassist.data.subhome.SubHome import com.github.unchama.seichiassist.minestack.MineStackUsageHistory import com.github.unchama.seichiassist.subsystems.breakcount.domain.level.SeichiStarLevel +import com.github.unchama.seichiassist.subsystems.subhome.domain.SubHome import com.github.unchama.seichiassist.task.VotingFairyTask import com.github.unchama.seichiassist.util.Util import com.github.unchama.seichiassist.util.Util.DirectionType @@ -146,8 +146,6 @@ class PlayerData( //グリッド式保護関連 private var claimUnit = ClaimUnit(0, 0, 0, 0) - def subHomeEntries: Set[(Int, SubHome)] = subHomeMap.toSet - def gridChunkAmount: Int = (claimUnit.ahead + claimUnit.behind + 1) * (claimUnit.right + claimUnit.left + 1) //オフラインかどうか @@ -384,36 +382,6 @@ class PlayerData( else SeichiAssist.seichiAssistConfig.getDropExplevel(10) } - //サブホームの位置をセットする - def setSubHomeLocation(location: Location, subHomeIndex: Int): Unit = { - if (subHomeIndex >= 0 && subHomeIndex < SeichiAssist.seichiAssistConfig.getSubHomeMax) { - val currentSubHome = this.subHomeMap.get(subHomeIndex) - val currentSubHomeName = currentSubHome.map(_.name).orNull - - this.subHomeMap(subHomeIndex) = new SubHome(location, currentSubHomeName) - } - } - - def setSubHomeName(name: String, subHomeIndex: Int): Unit = { - if (subHomeIndex >= 0 && subHomeIndex < SeichiAssist.seichiAssistConfig.getSubHomeMax) { - val currentSubHome = this.subHomeMap.getOrElse(subHomeIndex, return) - - this.subHomeMap(subHomeIndex) = new SubHome(currentSubHome.getLocation, name) - } - } - - // サブホームの位置を読み込む - def getSubHomeLocation(subHomeIndex: Int): Option[Location] = { - val subHome = this.subHomeMap.get(subHomeIndex) - subHome.map(_.getLocation) - } - - def getSubHomeName(subHomeIndex: Int): String = { - val subHome = this.subHomeMap.get(subHomeIndex) - val subHomeName = subHome.map(_.name) - subHomeName.getOrElse(s"サブホームポイント${subHomeIndex + 1}") - } - def canBreakHalfBlock: Boolean = this.allowBreakingHalfBlocks def canGridExtend(directionType: DirectionType, world: String): Boolean = { diff --git a/src/main/scala/com/github/unchama/seichiassist/data/subhome/SubHome.java b/src/main/scala/com/github/unchama/seichiassist/data/subhome/SubHome.java deleted file mode 100644 index 290c6d1c46..0000000000 --- a/src/main/scala/com/github/unchama/seichiassist/data/subhome/SubHome.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.github.unchama.seichiassist.data.subhome; - -import org.bukkit.Location; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -/** - * サブホームオブジェクトのクラス - */ -// TODO Scalaize and make this case class -public class SubHome { - public final @Nullable String name; - private final @NotNull Location location; - - public SubHome(@NotNull Location location, @Nullable String name) { - this.location = location; - this.name = name; - } - - public Location getLocation() { - // BukkitのLocationはミュータブルなのでコピーして返す必要がある - return location.clone(); - } -} diff --git a/src/main/scala/com/github/unchama/seichiassist/menus/HomeMenu.scala b/src/main/scala/com/github/unchama/seichiassist/menus/HomeMenu.scala index 155b19787e..e5b1bf3985 100644 --- a/src/main/scala/com/github/unchama/seichiassist/menus/HomeMenu.scala +++ b/src/main/scala/com/github/unchama/seichiassist/menus/HomeMenu.scala @@ -1,11 +1,13 @@ package com.github.unchama.seichiassist.menus -import cats.effect.IO +import cats.effect.{ConcurrentEffect, IO} import com.github.unchama.itemstackbuilder.IconItemStackBuilder import com.github.unchama.menuinventory.router.CanOpen import com.github.unchama.menuinventory.slot.button.Button import com.github.unchama.menuinventory.slot.button.action.LeftClickButtonEffect import com.github.unchama.menuinventory.{ChestSlotRef, Menu, MenuFrame, MenuSlotLayout} +import com.github.unchama.seichiassist.subsystems.subhome.domain.SubHome +import com.github.unchama.seichiassist.subsystems.subhome.infrastructure.SubHomeReadAPI import com.github.unchama.seichiassist.{ManagedWorld, SeichiAssist} import com.github.unchama.targetedeffect._ import com.github.unchama.targetedeffect.player.PlayerEffects._ @@ -25,7 +27,8 @@ object HomeMenu extends Menu { import com.github.unchama.seichiassist.concurrent.PluginExecutionContexts.onMainThread import eu.timepit.refined.auto._ - class Environment(implicit val ioCanOpenConfirmationMenu: IO CanOpen ConfirmationMenu) + class Environment(implicit val ioCanOpenConfirmationMenu: IO CanOpen ConfirmationMenu, + val ioCanReadSubHome: SubHomeReadAPI[IO]) /** * メニューのサイズとタイトルに関する情報 @@ -62,13 +65,14 @@ object HomeMenu extends Menu { } import cats.implicits._ - + import com.github.unchama.seichiassist.concurrent.PluginExecutionContexts.asyncShift val dynamicPartComputation = (for { subHomeNumber <- 1 to SeichiAssist.seichiAssistConfig.getSubHomeMax } yield { val column = refineV[Interval.ClosedOpen[0, 9]](subHomeNumber + 1) + implicit val ioCanReadSubHome: SubHomeReadAPI[IO] = environment.ioCanReadSubHome column match { - case Right(value) => ChestSlotRef(1, value) -> setSubHomeNameButton(subHomeNumber) + case Right(value) => ChestSlotRef(1, value) -> setSubHomeNameButton[IO](subHomeNumber) case Left(_) => throw new RuntimeException("This branch should not be reached.") } }.sequence) @@ -154,40 +158,44 @@ object HomeMenu extends Menu { } private case class ButtonComputations(player: Player) { + def setSubHomeNameButton[F[_] : SubHomeReadAPI : ConcurrentEffect](subHomeNumber: Int): IO[Button] = { + import cats.implicits._ + val program = for { + subhomeOpt <- SubHomeReadAPI[F].get(player.getUniqueId, subHomeNumber - 1) + } yield { + val lore = subhomeOpt match { + case None => List(s"${GRAY}サブホームポイント$subHomeNumber", s"${GRAY}ポイント未設定") + case Some(SubHome(location, name)) => + val worldName = ManagedWorld.fromBukkitWorld(location.getWorld).map(_.japaneseName) + .getOrElse(location.getWorld.getName) + List( + s"${GRAY}サブホームポイント${subHomeNumber}は", + s"$GRAY$name", + s"${GRAY}と名付けられています", + s"$DARK_RED${UNDERLINE}クリックで名称変更", + s"${DARK_GRAY}command->[/subhome name $subHomeNumber]", + s"$GRAY$worldName x:${location.getBlockX} y:${location.getBlockY} z:${location.getBlockZ}" + ) + } - import player._ - - def setSubHomeNameButton(subHomeNumber: Int): IO[Button] = IO { - val openerData = SeichiAssist.playermap(getUniqueId) - val maybeLocation = openerData.getSubHomeLocation(subHomeNumber - 1) - val lore = maybeLocation match { - case None => List(s"${GRAY}サブホームポイント$subHomeNumber", s"${GRAY}ポイント未設定") - case Some(location) => - val worldName = ManagedWorld.fromBukkitWorld(location.getWorld).map(_.japaneseName) - .getOrElse(location.getWorld.getName) - List( - s"${GRAY}サブホームポイント${subHomeNumber}は", - s"$GRAY${openerData.getSubHomeName(subHomeNumber - 1)}", - s"${GRAY}と名付けられています", - s"$DARK_RED${UNDERLINE}クリックで名称変更", - s"${DARK_GRAY}command->[/subhome name $subHomeNumber]", - s"$GRAY$worldName x:${location.getBlockX} y:${location.getBlockY} z:${location.getBlockZ}" - ) + Button( + new IconItemStackBuilder(Material.PAPER) + .title(s"$YELLOW$UNDERLINE${BOLD}サブホームポイント${subHomeNumber}の情報") + .lore(lore) + .build(), + LeftClickButtonEffect { + SequentialEffect( + FocusedSoundEffect(Sound.BLOCK_STONE_BUTTON_CLICK_ON, 1f, 1f), + CommandEffect(s"subhome name $subHomeNumber"), + closeInventoryEffect + ) + } + ) } - Button( - new IconItemStackBuilder(Material.PAPER) - .title(s"$YELLOW$UNDERLINE${BOLD}サブホームポイント${subHomeNumber}の情報") - .lore(lore) - .build(), - LeftClickButtonEffect { - SequentialEffect( - FocusedSoundEffect(Sound.BLOCK_STONE_BUTTON_CLICK_ON, 1f, 1f), - CommandEffect(s"subhome name $subHomeNumber"), - closeInventoryEffect - ) - } - ) + import cats.effect.implicits._ + + program.toIO } } diff --git a/src/main/scala/com/github/unchama/seichiassist/menus/TopLevelRouter.scala b/src/main/scala/com/github/unchama/seichiassist/menus/TopLevelRouter.scala index c91694e359..f0f19c915d 100644 --- a/src/main/scala/com/github/unchama/seichiassist/menus/TopLevelRouter.scala +++ b/src/main/scala/com/github/unchama/seichiassist/menus/TopLevelRouter.scala @@ -18,6 +18,7 @@ import com.github.unchama.seichiassist.subsystems.fourdimensionalpocket.FourDime import com.github.unchama.seichiassist.subsystems.gachapoint.GachaPointApi import com.github.unchama.seichiassist.subsystems.mana.ManaApi import com.github.unchama.seichiassist.subsystems.ranking.RankingApi +import com.github.unchama.seichiassist.subsystems.subhome.infrastructure.{SubHomeAPI, SubHomeReadAPI} import io.chrisdavenport.cats.effect.time.JavaTime import org.bukkit.entity.Player @@ -40,7 +41,8 @@ object TopLevelRouter { gachaPointApi: GachaPointApi[IO, SyncIO, Player], fastDiggingEffectApi: FastDiggingEffectApi[IO, Player], fastDiggingSettingsApi: FastDiggingSettingsApi[IO, Player], - fourDimensionalPocketApi: FourDimensionalPocketApi[IO, Player]): TopLevelRouter[IO] = new TopLevelRouter[IO] { + fourDimensionalPocketApi: FourDimensionalPocketApi[IO, Player], + subHomeReadApi: SubHomeReadAPI[IO]): TopLevelRouter[IO] = new TopLevelRouter[IO] { implicit lazy val seichiRankingMenuEnv: SeichiRankingMenu.Environment = new SeichiRankingMenu.Environment implicit lazy val secondPageEnv: SecondPage.Environment = new SecondPage.Environment implicit lazy val mineStackMainMenuEnv: MineStackMainMenu.Environment = new MineStackMainMenu.Environment diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/System.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/System.scala new file mode 100644 index 0000000000..4e5a4d7c52 --- /dev/null +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/System.scala @@ -0,0 +1,32 @@ +package com.github.unchama.seichiassist.subsystems.subhome + +import cats.effect.ConcurrentEffect +import com.github.unchama.concurrent.NonServerThreadContextShift +import com.github.unchama.seichiassist.SeichiAssist.Scopes.globalChatInterceptionScope +import com.github.unchama.seichiassist.meta.subsystem.Subsystem +import com.github.unchama.seichiassist.subsystems.subhome.bukkit.command.SubHomeCommand +import com.github.unchama.seichiassist.subsystems.subhome.infrastructure.{SubHomeAPI, SubHomePersistence, SubHomeReadAPI, SubHomeWriteAPI} +import org.bukkit.command.TabExecutor + +trait System[F[_]] extends Subsystem[F] { + def api: SubHomeAPI[F] +} + +object System { + def wired[ + F[_] + : ConcurrentEffect + : NonServerThreadContextShift + ]: System[F] = new System[F] { + val persistence = new SubHomePersistence[F]() + override def api: SubHomeAPI[F] = persistence + + private implicit val writer: SubHomeWriteAPI[F] = api + private implicit val reader: SubHomeReadAPI[F] = api + + override val commands: Map[String, TabExecutor] = + Map( + "subhome" -> SubHomeCommand.executor + ) + } +} diff --git a/src/main/scala/com/github/unchama/seichiassist/commands/SubHomeCommand.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/bukkit/command/SubHomeCommand.scala similarity index 60% rename from src/main/scala/com/github/unchama/seichiassist/commands/SubHomeCommand.scala rename to src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/bukkit/command/SubHomeCommand.scala index a36260dc2d..34b195e264 100644 --- a/src/main/scala/com/github/unchama/seichiassist/commands/SubHomeCommand.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/bukkit/command/SubHomeCommand.scala @@ -1,13 +1,19 @@ -package com.github.unchama.seichiassist.commands +package com.github.unchama.seichiassist.subsystems.subhome.bukkit.command import cats.data.Kleisli -import cats.effect.IO +import cats.effect.{ConcurrentEffect, IO} +import cats.implicits._ +import cats.effect.implicits._ + import com.github.unchama.chatinterceptor.CancellationReason.Overridden import com.github.unchama.chatinterceptor.ChatInterceptionScope +import com.github.unchama.concurrent.NonServerThreadContextShift import com.github.unchama.contextualexecutor.builder.Parsers import com.github.unchama.contextualexecutor.executors.{BranchedExecutor, EchoExecutor} import com.github.unchama.seichiassist.SeichiAssist import com.github.unchama.seichiassist.commands.contextual.builder.BuilderTemplates.playerCommandBuilder +import com.github.unchama.seichiassist.subsystems.subhome.domain.SubHome +import com.github.unchama.seichiassist.subsystems.subhome.infrastructure.{SubHomeReadAPI, SubHomeWriteAPI} import com.github.unchama.targetedeffect.commandsender.MessageEffect import org.bukkit.ChatColor._ import org.bukkit.command.TabExecutor @@ -36,34 +42,58 @@ object SubHomeCommand { ), onMissingArguments = printDescriptionExecutor ) - private val warpExecutor = argsAndSenderConfiguredBuilder + private def warpExecutor[ + F[_] + : ConcurrentEffect + : NonServerThreadContextShift + : SubHomeReadAPI + ] = argsAndSenderConfiguredBuilder .execution { context => val subHomeId = context.args.parsed.head.asInstanceOf[Int] val player = context.sender - val subHomeLocation = SeichiAssist.playermap(player.getUniqueId).getSubHomeLocation(subHomeId - 1) - subHomeLocation match { - case None => IO(MessageEffect(s"サブホームポイント${subHomeId}が設定されてません")) - case Some(location) => IO { - player.teleport(location) - MessageEffect(s"サブホームポイント${subHomeId}にワープしました") + val eff = for { + _ <- NonServerThreadContextShift[F].shift + subHomeLocation <- SubHomeReadAPI[F].get(player.getUniqueId, subHomeId - 1) + } yield { + subHomeLocation match { + case None => MessageEffect(s"サブホームポイント${subHomeId}が設定されてません") + case Some(SubHome(location, _)) => + player.teleport(location) + MessageEffect(s"サブホームポイント${subHomeId}にワープしました") } } + + eff.toIO } .build() - private val setExecutor = argsAndSenderConfiguredBuilder + private def setExecutor[ + F[_] + : ConcurrentEffect + : NonServerThreadContextShift + : SubHomeWriteAPI + ] = argsAndSenderConfiguredBuilder .execution { context => val subHomeId = context.args.parsed.head.asInstanceOf[Int] val player = context.sender - val playerData = SeichiAssist.playermap(player.getUniqueId) - playerData.setSubHomeLocation(player.getLocation, subHomeId - 1) + val eff = for { + _ <- NonServerThreadContextShift[F].shift + _ <- SubHomeWriteAPI[F].updateLocation(player.getUniqueId, subHomeId - 1, player.getLocation) + } yield { + MessageEffect(s"現在位置をサブホームポイント${subHomeId}に設定しました") + } - IO(MessageEffect(s"現在位置をサブホームポイント${subHomeId}に設定しました")) + eff.toIO } .build() - private def nameExecutor(implicit scope: ChatInterceptionScope) = argsAndSenderConfiguredBuilder + private def nameExecutor[ + F[_] + : ConcurrentEffect + : NonServerThreadContextShift + : SubHomeWriteAPI + ](implicit scope: ChatInterceptionScope) = argsAndSenderConfiguredBuilder .execution { context => val subHomeId = context.args.parsed.head.asInstanceOf[Int] @@ -87,15 +117,17 @@ object SubHomeCommand { ) ) - import cats.implicits._ import com.github.unchama.generic.syntax._ sendInterceptionMessage.followedBy(Kleisli { player => - val playerData = SeichiAssist.playermap(player.getUniqueId) + val uuid = player.getUniqueId - scope.interceptFrom(player.getUniqueId).flatMap { + scope.interceptFrom(uuid).flatMap { case Left(newName) => - IO { playerData.setSubHomeName(newName, subHomeId - 1) } *> + val eff = for { + _ <- SubHomeWriteAPI[F].updateName(uuid, subHomeId - 1, newName) + } yield {} + eff.toIO *> sendCompletionMessage(newName)(player) case Right(Overridden) => sendCancellationMessage(player) case Right(_) => IO.pure(()) @@ -105,7 +137,13 @@ object SubHomeCommand { } .build() - def executor(implicit scope: ChatInterceptionScope): TabExecutor = BranchedExecutor( + def executor[ + F[_] + : SubHomeReadAPI + : SubHomeWriteAPI + : ConcurrentEffect + : NonServerThreadContextShift + ](implicit scope: ChatInterceptionScope): TabExecutor = BranchedExecutor( Map( "warp" -> warpExecutor, "set" -> setExecutor, diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/domain/SubHome.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/domain/SubHome.scala new file mode 100644 index 0000000000..368f919948 --- /dev/null +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/domain/SubHome.scala @@ -0,0 +1,12 @@ +package com.github.unchama.seichiassist.subsystems.subhome.domain + +import org.bukkit.Location + +/** + * サブホームオブジェクトのクラス + */ +case class SubHome(location: Location, name: String) { + def getLocation = { // BukkitのLocationはミュータブルなのでコピーして返す必要がある + location.clone + } +} \ No newline at end of file diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/SubHomePersistence.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/SubHomePersistence.scala new file mode 100644 index 0000000000..27a5236bdb --- /dev/null +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/SubHomePersistence.scala @@ -0,0 +1,84 @@ +package com.github.unchama.seichiassist.subsystems.subhome.infrastructure + +import cats.effect.Sync +import com.github.unchama.seichiassist.SeichiAssist +import com.github.unchama.seichiassist.subsystems.subhome.domain.SubHome +import com.github.unchama.seichiassist.subsystems.subhome.infrastructure.SubHomeAPI.{PlayerIdentifier, SubHomeNumber} +import org.bukkit.{Bukkit, Location} +import scalikejdbc._ + +class SubHomePersistence[F[_]: Sync] extends SubHomeAPI[F] { + final val table = "seichiassist.sub_home" + val serverId = SeichiAssist.seichiAssistConfig.getServerNum + override def get(player: PlayerIdentifier, number: SubHomeNumber): F[Option[SubHome]] = { + Sync[F].delay { + DB.readOnly { implicit session => + sql"""SELECT id, name, location_x, location_y, location_z, world_name FROM $table + WHERE player = ${player.toString} AND server_id = $serverId AND id = $number""" + .map(extractSubHome) + // もしかすると見つからないかもしれない + .first() + .apply() + } + } + } + + override def list(player: PlayerIdentifier): F[Map[SubHomeNumber, SubHome]] = Sync[F].delay { + DB.readOnly { implicit session => + sql"""SELECT id, name, location_x, location_y, location_z, world_name FROM $table""" + .map(rs => { + ( + rs.int("id"), + extractSubHome(rs) + ) + }) + .list() + .apply() + }.toMap + } + + override def updateLocation(player: PlayerIdentifier, number: SubHomeNumber, location: Location): F[Unit] = + Sync[F].delay { + val x = location.getX.toInt + val y = location.getY.toInt + val z = location.getZ.toInt + val worldName = location.getWorld.getName + DB.localTx { implicit session => + // 重複したとき、もとのエントリを残す必要はないので黙って上書きする + sql"""insert into $table + |(player_uuid,server_id,id,location_x,location_y,location_z,world_name) values + |(${player.toString},$serverId,$number,$x,$y,$z,$worldName) + |on duplicate key update + |location_x = values(location_x), + |location_y = values(location_y), + |location_z = values(location_z), + |world_name = values(world_name)""" + .stripMargin('|') + .execute() + .apply() + } + } + + override def updateName(player: PlayerIdentifier, number: SubHomeNumber, name: String): F[Unit] = + Sync[F].delay { + DB.localTx { implicit session => + sql"""insert into $table + |(player_uuid,server_id,id,name) values + |(${player.toString},$serverId,$number,$name) + |on duplicate key update + |name = values(name)""" + .stripMargin('|') + .execute() + .apply() + } + } + + private def extractSubHome(rs: WrappedResultSet): SubHome = { + val x = rs.int("location_x") + val y = rs.int("location_y") + val z = rs.int("location_z") + val world = Bukkit.getWorld(rs.string("world_name")) + val homeName = rs.string("name") + new SubHome(new Location(world, x, y, z), homeName) + } +} diff --git a/src/main/scala/com/github/unchama/seichiassist/task/PlayerDataLoading.scala b/src/main/scala/com/github/unchama/seichiassist/task/PlayerDataLoading.scala index c6bc2e4886..d31c62cd64 100644 --- a/src/main/scala/com/github/unchama/seichiassist/task/PlayerDataLoading.scala +++ b/src/main/scala/com/github/unchama/seichiassist/task/PlayerDataLoading.scala @@ -51,34 +51,6 @@ object PlayerDataLoading { stmt.executeUpdate(loginInfoUpdateCommand) } - def loadSubHomeData(stmt: Statement): Unit = { - val subHomeDataQuery = ("select * from " - + db + "." + DatabaseConstants.SUB_HOME_TABLENAME + " where " - + s"player_uuid = '$stringUuid' and " - + "server_id = " + config.getServerNum) - - stmt.executeQuery(subHomeDataQuery).recordIteration { lrs: ResultSet => - import lrs._ - val subHomeId = getInt("id") - val subHomeName = getString("name") - val locationX = getInt("location_x") - val locationY = getInt("location_y") - val locationZ = getInt("location_z") - val worldName = getString("world_name") - - val world = Bukkit.getWorld(worldName) - - if (world != null) { - val location = new Location(world, locationX.toDouble, locationY.toDouble, locationZ.toDouble) - - playerData.setSubHomeLocation(location, subHomeId) - playerData.setSubHomeName(subHomeName, subHomeId) - } else { - println(s"Resetting $playerName's subhome $subHomeName($subHomeId) in $worldName - world name not found.") - } - } - } - def loadMineStack(stmt: Statement): Unit = { val mineStackDataQuery = ("select * from " + db + "." + DatabaseConstants.MINESTACK_TABLENAME + " where " @@ -340,7 +312,6 @@ object PlayerDataLoading { updateLoginInfo(newStmt) loadGridTemplate(newStmt) loadMineStack(newStmt) - loadSubHomeData(newStmt) } timer.sendLapTimeMessage(s"$GREEN${playerName}のプレイヤーデータ読込完了") diff --git a/src/main/scala/com/github/unchama/seichiassist/task/PlayerDataSaveTask.scala b/src/main/scala/com/github/unchama/seichiassist/task/PlayerDataSaveTask.scala index c90c62a7ef..10dd09854b 100644 --- a/src/main/scala/com/github/unchama/seichiassist/task/PlayerDataSaveTask.scala +++ b/src/main/scala/com/github/unchama/seichiassist/task/PlayerDataSaveTask.scala @@ -22,7 +22,6 @@ object PlayerDataSaveTask { */ def savePlayerData[F[_] : Sync](player: Player, playerdata: PlayerData): F[Unit] = { val databaseGateway = SeichiAssist.databaseGateway - val serverId = SeichiAssist.seichiAssistConfig.getServerNum def updatePlayerMineStack(stmt: Statement): Unit = { val playerUuid = playerdata.uuid.toString @@ -39,36 +38,6 @@ object PlayerDataSaveTask { } } - def updateSubHome(): Unit = { - val playerUuid = playerdata.uuid.toString - playerdata.subHomeEntries.foreach { case (subHomeId, subHome) => - val subHomeLocation = subHome.getLocation - - val template = ("insert into seichiassist.sub_home" - + "(player_uuid,server_id,id,name,location_x,location_y,location_z,world_name) values " - + "(?,?,?,?,?,?,?,?) " - + "on duplicate key update " - + "name = values(name), " - + "location_x = values(location_x), " - + "location_y = values(location_y), " - + "location_z = values(location_z), " - + "world_name = values(world_name)") - - Using(databaseGateway.con.prepareStatement(template)) { statement => - statement.setString(1, playerUuid) - statement.setInt(2, serverId) - statement.setInt(3, subHomeId) - statement.setString(4, subHome.name) - statement.setInt(5, subHomeLocation.getX.toInt) - statement.setInt(6, subHomeLocation.getY.toInt) - statement.setInt(7, subHomeLocation.getZ.toInt) - statement.setString(8, subHomeLocation.getWorld.getName) - - statement.executeUpdate() - } - } - } - def updateGridTemplate(stmt: Statement): Unit = { val playerUuid = playerdata.uuid.toString @@ -209,7 +178,6 @@ object PlayerDataSaveTask { updatePlayerDataColumns(localStatement) updatePlayerMineStack(localStatement) updateGridTemplate(localStatement) - updateSubHome() ActionStatus.Ok } catch { case exception: SQLException => From 1826c808f92ef3f7ec837c5f896b506786c42a30 Mon Sep 17 00:00:00 2001 From: KisaragiEffective <kisaragi.effective@gmail.com> Date: Mon, 19 Apr 2021 20:46:20 +0900 Subject: [PATCH 02/73] [fix] compile error --- .../seichiassist/menus/TopLevelRouter.scala | 2 +- .../subsystems/subhome/System.scala | 6 +++--- .../subsystems/subhome/domain/SubHome.scala | 4 ++++ .../infrastructure/SubHomePersistence.scala | 19 ++++++++++--------- .../infrastructure/SubHomeReadAPI.scala | 12 ++++++++++++ .../infrastructure/SubHomeWriteAPI.scala | 13 +++++++++++++ 6 files changed, 43 insertions(+), 13 deletions(-) create mode 100644 src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/SubHomeReadAPI.scala create mode 100644 src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/SubHomeWriteAPI.scala diff --git a/src/main/scala/com/github/unchama/seichiassist/menus/TopLevelRouter.scala b/src/main/scala/com/github/unchama/seichiassist/menus/TopLevelRouter.scala index f0f19c915d..53bccd6436 100644 --- a/src/main/scala/com/github/unchama/seichiassist/menus/TopLevelRouter.scala +++ b/src/main/scala/com/github/unchama/seichiassist/menus/TopLevelRouter.scala @@ -18,7 +18,7 @@ import com.github.unchama.seichiassist.subsystems.fourdimensionalpocket.FourDime import com.github.unchama.seichiassist.subsystems.gachapoint.GachaPointApi import com.github.unchama.seichiassist.subsystems.mana.ManaApi import com.github.unchama.seichiassist.subsystems.ranking.RankingApi -import com.github.unchama.seichiassist.subsystems.subhome.infrastructure.{SubHomeAPI, SubHomeReadAPI} +import com.github.unchama.seichiassist.subsystems.subhome.infrastructure.SubHomeReadAPI import io.chrisdavenport.cats.effect.time.JavaTime import org.bukkit.entity.Player diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/System.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/System.scala index 4e5a4d7c52..b3e43289b0 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/System.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/System.scala @@ -5,11 +5,11 @@ import com.github.unchama.concurrent.NonServerThreadContextShift import com.github.unchama.seichiassist.SeichiAssist.Scopes.globalChatInterceptionScope import com.github.unchama.seichiassist.meta.subsystem.Subsystem import com.github.unchama.seichiassist.subsystems.subhome.bukkit.command.SubHomeCommand -import com.github.unchama.seichiassist.subsystems.subhome.infrastructure.{SubHomeAPI, SubHomePersistence, SubHomeReadAPI, SubHomeWriteAPI} +import com.github.unchama.seichiassist.subsystems.subhome.infrastructure.{SubHomePersistence, SubHomeReadAPI, SubHomeWriteAPI} import org.bukkit.command.TabExecutor trait System[F[_]] extends Subsystem[F] { - def api: SubHomeAPI[F] + def api: SubHomeReadAPI[F] with SubHomeWriteAPI[F] } object System { @@ -19,7 +19,7 @@ object System { : NonServerThreadContextShift ]: System[F] = new System[F] { val persistence = new SubHomePersistence[F]() - override def api: SubHomeAPI[F] = persistence + override def api: SubHomeReadAPI[F] with SubHomeWriteAPI[F] = persistence private implicit val writer: SubHomeWriteAPI[F] = api private implicit val reader: SubHomeReadAPI[F] = api diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/domain/SubHome.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/domain/SubHome.scala index 368f919948..924ed2a4d1 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/domain/SubHome.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/domain/SubHome.scala @@ -9,4 +9,8 @@ case class SubHome(location: Location, name: String) { def getLocation = { // BukkitのLocationはミュータブルなのでコピーして返す必要がある location.clone } +} + +object SubHome { + type ID = Int } \ No newline at end of file diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/SubHomePersistence.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/SubHomePersistence.scala index 27a5236bdb..e904aaa63d 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/SubHomePersistence.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/SubHomePersistence.scala @@ -3,18 +3,19 @@ package com.github.unchama.seichiassist.subsystems.subhome.infrastructure import cats.effect.Sync import com.github.unchama.seichiassist.SeichiAssist import com.github.unchama.seichiassist.subsystems.subhome.domain.SubHome -import com.github.unchama.seichiassist.subsystems.subhome.infrastructure.SubHomeAPI.{PlayerIdentifier, SubHomeNumber} import org.bukkit.{Bukkit, Location} import scalikejdbc._ -class SubHomePersistence[F[_]: Sync] extends SubHomeAPI[F] { +import java.util.UUID + +class SubHomePersistence[F[_]: Sync] extends SubHomeReadAPI[F] with SubHomeWriteAPI[F] { final val table = "seichiassist.sub_home" - val serverId = SeichiAssist.seichiAssistConfig.getServerNum - override def get(player: PlayerIdentifier, number: SubHomeNumber): F[Option[SubHome]] = { + private val serverId = SeichiAssist.seichiAssistConfig.getServerNum + override def get(player: UUID, id: SubHome.ID): F[Option[SubHome]] = { Sync[F].delay { DB.readOnly { implicit session => sql"""SELECT id, name, location_x, location_y, location_z, world_name FROM $table - WHERE player = ${player.toString} AND server_id = $serverId AND id = $number""" + WHERE player = ${player.toString} AND server_id = $serverId AND id = $id""" .map(extractSubHome) // もしかすると見つからないかもしれない .first() @@ -23,7 +24,7 @@ class SubHomePersistence[F[_]: Sync] extends SubHomeAPI[F] { } } - override def list(player: PlayerIdentifier): F[Map[SubHomeNumber, SubHome]] = Sync[F].delay { + override def list(player: UUID): F[Map[SubHome.ID, SubHome]] = Sync[F].delay { DB.readOnly { implicit session => sql"""SELECT id, name, location_x, location_y, location_z, world_name FROM $table""" .map(rs => { @@ -37,7 +38,7 @@ class SubHomePersistence[F[_]: Sync] extends SubHomeAPI[F] { }.toMap } - override def updateLocation(player: PlayerIdentifier, number: SubHomeNumber, location: Location): F[Unit] = + override def updateLocation(player: UUID, id: SubHome.ID, location: Location): F[Unit] = Sync[F].delay { val x = location.getX.toInt val y = location.getY.toInt @@ -47,7 +48,7 @@ class SubHomePersistence[F[_]: Sync] extends SubHomeAPI[F] { // 重複したとき、もとのエントリを残す必要はないので黙って上書きする sql"""insert into $table |(player_uuid,server_id,id,location_x,location_y,location_z,world_name) values - |(${player.toString},$serverId,$number,$x,$y,$z,$worldName) + |(${player.toString},$serverId,$id,$x,$y,$z,$worldName) |on duplicate key update |location_x = values(location_x), |location_y = values(location_y), @@ -59,7 +60,7 @@ class SubHomePersistence[F[_]: Sync] extends SubHomeAPI[F] { } } - override def updateName(player: PlayerIdentifier, number: SubHomeNumber, name: String): F[Unit] = + override def updateName(player: UUID, number: SubHome.ID, name: String): F[Unit] = Sync[F].delay { DB.localTx { implicit session => sql"""insert into $table diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/SubHomeReadAPI.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/SubHomeReadAPI.scala new file mode 100644 index 0000000000..9da5a95303 --- /dev/null +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/SubHomeReadAPI.scala @@ -0,0 +1,12 @@ +package com.github.unchama.seichiassist.subsystems.subhome.infrastructure + +import com.github.unchama.seichiassist.subsystems.subhome.domain.SubHome +import simulacrum.typeclass + +import java.util.UUID + +@typeclass trait SubHomeReadAPI[F[_]] { + def get(player: UUID, number: SubHome.ID): F[Option[SubHome]] + + def list(player: UUID): F[Map[SubHome.ID, SubHome]] +} diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/SubHomeWriteAPI.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/SubHomeWriteAPI.scala new file mode 100644 index 0000000000..16b1293b25 --- /dev/null +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/SubHomeWriteAPI.scala @@ -0,0 +1,13 @@ +package com.github.unchama.seichiassist.subsystems.subhome.infrastructure + +import com.github.unchama.seichiassist.subsystems.subhome.domain.SubHome +import org.bukkit.Location +import simulacrum.typeclass + +import java.util.UUID + +@typeclass trait SubHomeWriteAPI[F[_]] { + def updateLocation(player: UUID, id: SubHome.ID, location: Location): F[Unit] + + def updateName(player: UUID, id: SubHome.ID, name: String): F[Unit] +} From d649a39902baaa7beb66b9a0e0e4fea44650218a Mon Sep 17 00:00:00 2001 From: Kory <6561358+kory33@users.noreply.github.com> Date: Tue, 18 May 2021 16:45:08 +0900 Subject: [PATCH 03/73] =?UTF-8?q?[update]=20API=E3=81=AE=E3=83=91=E3=83=83?= =?UTF-8?q?=E3=82=B1=E3=83=BC=E3=82=B8=E3=82=92=E7=A7=BB=E5=8B=95=E3=81=99?= =?UTF-8?q?=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../scala/com/github/unchama/seichiassist/SeichiAssist.scala | 2 +- .../com/github/unchama/seichiassist/menus/HomeMenu.scala | 2 +- .../github/unchama/seichiassist/menus/TopLevelRouter.scala | 2 +- .../subhome/{infrastructure => }/SubHomeReadAPI.scala | 2 +- .../subhome/{infrastructure => }/SubHomeWriteAPI.scala | 2 +- .../unchama/seichiassist/subsystems/subhome/System.scala | 2 +- .../subsystems/subhome/bukkit/command/SubHomeCommand.scala | 4 ++-- .../subhome/infrastructure/SubHomePersistence.scala | 1 + 8 files changed, 9 insertions(+), 8 deletions(-) rename src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/{infrastructure => }/SubHomeReadAPI.scala (79%) rename src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/{infrastructure => }/SubHomeWriteAPI.scala (82%) diff --git a/src/main/scala/com/github/unchama/seichiassist/SeichiAssist.scala b/src/main/scala/com/github/unchama/seichiassist/SeichiAssist.scala index 5ca1a3f72f..3ce93a8af7 100644 --- a/src/main/scala/com/github/unchama/seichiassist/SeichiAssist.scala +++ b/src/main/scala/com/github/unchama/seichiassist/SeichiAssist.scala @@ -54,8 +54,8 @@ import com.github.unchama.seichiassist.subsystems.mana.{ManaApi, ManaReadApi} import com.github.unchama.seichiassist.subsystems.managedfly.ManagedFlyApi import com.github.unchama.seichiassist.subsystems.present.infrastructure.GlobalPlayerAccessor import com.github.unchama.seichiassist.subsystems.seasonalevents.api.SeasonalEventsAPI +import com.github.unchama.seichiassist.subsystems.subhome.SubHomeReadAPI import com.github.unchama.seichiassist.subsystems.subhome.bukkit.command.SubHomeCommand -import com.github.unchama.seichiassist.subsystems.subhome.infrastructure.SubHomeReadAPI import com.github.unchama.seichiassist.task.PlayerDataSaveTask import com.github.unchama.seichiassist.task.global._ import com.github.unchama.util.{ActionStatus, ClassUtils} diff --git a/src/main/scala/com/github/unchama/seichiassist/menus/HomeMenu.scala b/src/main/scala/com/github/unchama/seichiassist/menus/HomeMenu.scala index e5b1bf3985..fc111fb947 100644 --- a/src/main/scala/com/github/unchama/seichiassist/menus/HomeMenu.scala +++ b/src/main/scala/com/github/unchama/seichiassist/menus/HomeMenu.scala @@ -6,8 +6,8 @@ import com.github.unchama.menuinventory.router.CanOpen import com.github.unchama.menuinventory.slot.button.Button import com.github.unchama.menuinventory.slot.button.action.LeftClickButtonEffect import com.github.unchama.menuinventory.{ChestSlotRef, Menu, MenuFrame, MenuSlotLayout} +import com.github.unchama.seichiassist.subsystems.subhome.SubHomeReadAPI import com.github.unchama.seichiassist.subsystems.subhome.domain.SubHome -import com.github.unchama.seichiassist.subsystems.subhome.infrastructure.SubHomeReadAPI import com.github.unchama.seichiassist.{ManagedWorld, SeichiAssist} import com.github.unchama.targetedeffect._ import com.github.unchama.targetedeffect.player.PlayerEffects._ diff --git a/src/main/scala/com/github/unchama/seichiassist/menus/TopLevelRouter.scala b/src/main/scala/com/github/unchama/seichiassist/menus/TopLevelRouter.scala index 53bccd6436..16b4558921 100644 --- a/src/main/scala/com/github/unchama/seichiassist/menus/TopLevelRouter.scala +++ b/src/main/scala/com/github/unchama/seichiassist/menus/TopLevelRouter.scala @@ -18,7 +18,7 @@ import com.github.unchama.seichiassist.subsystems.fourdimensionalpocket.FourDime import com.github.unchama.seichiassist.subsystems.gachapoint.GachaPointApi import com.github.unchama.seichiassist.subsystems.mana.ManaApi import com.github.unchama.seichiassist.subsystems.ranking.RankingApi -import com.github.unchama.seichiassist.subsystems.subhome.infrastructure.SubHomeReadAPI +import com.github.unchama.seichiassist.subsystems.subhome.SubHomeReadAPI import io.chrisdavenport.cats.effect.time.JavaTime import org.bukkit.entity.Player diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/SubHomeReadAPI.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/SubHomeReadAPI.scala similarity index 79% rename from src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/SubHomeReadAPI.scala rename to src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/SubHomeReadAPI.scala index 9da5a95303..27b7b9132b 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/SubHomeReadAPI.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/SubHomeReadAPI.scala @@ -1,4 +1,4 @@ -package com.github.unchama.seichiassist.subsystems.subhome.infrastructure +package com.github.unchama.seichiassist.subsystems.subhome import com.github.unchama.seichiassist.subsystems.subhome.domain.SubHome import simulacrum.typeclass diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/SubHomeWriteAPI.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/SubHomeWriteAPI.scala similarity index 82% rename from src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/SubHomeWriteAPI.scala rename to src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/SubHomeWriteAPI.scala index 16b1293b25..8a68551964 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/SubHomeWriteAPI.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/SubHomeWriteAPI.scala @@ -1,4 +1,4 @@ -package com.github.unchama.seichiassist.subsystems.subhome.infrastructure +package com.github.unchama.seichiassist.subsystems.subhome import com.github.unchama.seichiassist.subsystems.subhome.domain.SubHome import org.bukkit.Location diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/System.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/System.scala index b3e43289b0..3f56fa4c2a 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/System.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/System.scala @@ -5,7 +5,7 @@ import com.github.unchama.concurrent.NonServerThreadContextShift import com.github.unchama.seichiassist.SeichiAssist.Scopes.globalChatInterceptionScope import com.github.unchama.seichiassist.meta.subsystem.Subsystem import com.github.unchama.seichiassist.subsystems.subhome.bukkit.command.SubHomeCommand -import com.github.unchama.seichiassist.subsystems.subhome.infrastructure.{SubHomePersistence, SubHomeReadAPI, SubHomeWriteAPI} +import com.github.unchama.seichiassist.subsystems.subhome.infrastructure.SubHomePersistence import org.bukkit.command.TabExecutor trait System[F[_]] extends Subsystem[F] { diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/bukkit/command/SubHomeCommand.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/bukkit/command/SubHomeCommand.scala index 34b195e264..4ce5c47296 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/bukkit/command/SubHomeCommand.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/bukkit/command/SubHomeCommand.scala @@ -4,7 +4,6 @@ import cats.data.Kleisli import cats.effect.{ConcurrentEffect, IO} import cats.implicits._ import cats.effect.implicits._ - import com.github.unchama.chatinterceptor.CancellationReason.Overridden import com.github.unchama.chatinterceptor.ChatInterceptionScope import com.github.unchama.concurrent.NonServerThreadContextShift @@ -12,8 +11,9 @@ import com.github.unchama.contextualexecutor.builder.Parsers import com.github.unchama.contextualexecutor.executors.{BranchedExecutor, EchoExecutor} import com.github.unchama.seichiassist.SeichiAssist import com.github.unchama.seichiassist.commands.contextual.builder.BuilderTemplates.playerCommandBuilder +import com.github.unchama.seichiassist.subsystems.subhome.{SubHomeReadAPI, SubHomeWriteAPI} import com.github.unchama.seichiassist.subsystems.subhome.domain.SubHome -import com.github.unchama.seichiassist.subsystems.subhome.infrastructure.{SubHomeReadAPI, SubHomeWriteAPI} +import com.github.unchama.seichiassist.subsystems.subhome.infrastructure.SubHomeWriteAPI import com.github.unchama.targetedeffect.commandsender.MessageEffect import org.bukkit.ChatColor._ import org.bukkit.command.TabExecutor diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/SubHomePersistence.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/SubHomePersistence.scala index e904aaa63d..6f3d117dc8 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/SubHomePersistence.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/SubHomePersistence.scala @@ -2,6 +2,7 @@ package com.github.unchama.seichiassist.subsystems.subhome.infrastructure import cats.effect.Sync import com.github.unchama.seichiassist.SeichiAssist +import com.github.unchama.seichiassist.subsystems.subhome.{SubHomeReadAPI, SubHomeWriteAPI} import com.github.unchama.seichiassist.subsystems.subhome.domain.SubHome import org.bukkit.{Bukkit, Location} import scalikejdbc._ From be47b19d665143234d55ec185ddf9899ce26acd9 Mon Sep 17 00:00:00 2001 From: Kory <6561358+kory33@users.noreply.github.com> Date: Tue, 18 May 2021 16:50:06 +0900 Subject: [PATCH 04/73] =?UTF-8?q?[update]=20=E3=83=86=E3=83=BC=E3=83=96?= =?UTF-8?q?=E3=83=AB=E5=90=8D=E3=82=92=E5=B1=95=E9=96=8B=E3=81=99=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit こうしないと静的チェックが効かない --- .../infrastructure/SubHomePersistence.scala | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/SubHomePersistence.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/SubHomePersistence.scala index 6f3d117dc8..185390ecbf 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/SubHomePersistence.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/SubHomePersistence.scala @@ -10,13 +10,13 @@ import scalikejdbc._ import java.util.UUID class SubHomePersistence[F[_]: Sync] extends SubHomeReadAPI[F] with SubHomeWriteAPI[F] { - final val table = "seichiassist.sub_home" private val serverId = SeichiAssist.seichiAssistConfig.getServerNum + override def get(player: UUID, id: SubHome.ID): F[Option[SubHome]] = { Sync[F].delay { DB.readOnly { implicit session => - sql"""SELECT id, name, location_x, location_y, location_z, world_name FROM $table - WHERE player = ${player.toString} AND server_id = $serverId AND id = $id""" + sql"""SELECT id, name, location_x, location_y, location_z, world_name FROM seichiassist.sub_home + WHERE name = ${player.toString} AND server_id = $serverId AND id = $id""" .map(extractSubHome) // もしかすると見つからないかもしれない .first() @@ -27,7 +27,7 @@ class SubHomePersistence[F[_]: Sync] extends SubHomeReadAPI[F] with SubHomeWrite override def list(player: UUID): F[Map[SubHome.ID, SubHome]] = Sync[F].delay { DB.readOnly { implicit session => - sql"""SELECT id, name, location_x, location_y, location_z, world_name FROM $table""" + sql"""SELECT id, name, location_x, location_y, location_z, world_name FROM seichiassist.sub_home""" .map(rs => { ( rs.int("id"), @@ -47,7 +47,7 @@ class SubHomePersistence[F[_]: Sync] extends SubHomeReadAPI[F] with SubHomeWrite val worldName = location.getWorld.getName DB.localTx { implicit session => // 重複したとき、もとのエントリを残す必要はないので黙って上書きする - sql"""insert into $table + sql"""insert into seichiassist.sub_home |(player_uuid,server_id,id,location_x,location_y,location_z,world_name) values |(${player.toString},$serverId,$id,$x,$y,$z,$worldName) |on duplicate key update @@ -64,8 +64,8 @@ class SubHomePersistence[F[_]: Sync] extends SubHomeReadAPI[F] with SubHomeWrite override def updateName(player: UUID, number: SubHome.ID, name: String): F[Unit] = Sync[F].delay { DB.localTx { implicit session => - sql"""insert into $table - |(player_uuid,server_id,id,name) values + sql"""insert into seichiassist.sub_home + |(player_uuid, server_id, id, name) values |(${player.toString},$serverId,$number,$name) |on duplicate key update |name = values(name)""" From f3fd6cc95e396fcc4a6bf50ba56b2413b06ec6cd Mon Sep 17 00:00:00 2001 From: Kory <6561358+kory33@users.noreply.github.com> Date: Tue, 18 May 2021 16:54:41 +0900 Subject: [PATCH 05/73] =?UTF-8?q?[fix]=20SQL=E3=82=AF=E3=82=A8=E3=83=AA?= =?UTF-8?q?=E3=82=92=E3=83=95=E3=82=A9=E3=83=BC=E3=83=9E=E3=83=83=E3=83=88?= =?UTF-8?q?+=E4=BF=AE=E6=AD=A3=E3=81=99=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../infrastructure/SubHomePersistence.scala | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/SubHomePersistence.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/SubHomePersistence.scala index 185390ecbf..075e926f83 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/SubHomePersistence.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/SubHomePersistence.scala @@ -48,13 +48,13 @@ class SubHomePersistence[F[_]: Sync] extends SubHomeReadAPI[F] with SubHomeWrite DB.localTx { implicit session => // 重複したとき、もとのエントリを残す必要はないので黙って上書きする sql"""insert into seichiassist.sub_home - |(player_uuid,server_id,id,location_x,location_y,location_z,world_name) values - |(${player.toString},$serverId,$id,$x,$y,$z,$worldName) - |on duplicate key update - |location_x = values(location_x), - |location_y = values(location_y), - |location_z = values(location_z), - |world_name = values(world_name)""" + |(player_uuid, server_id, id, location_x, location_y, location_z, world_name) values + | (${player.toString}, $serverId, $id, $x, $y, $z, $worldName) + | on duplicate key update + | location_x = values(location_x), + | location_y = values(location_y), + | location_z = values(location_z), + | world_name = values(world_name)""" .stripMargin('|') .execute() .apply() @@ -64,11 +64,11 @@ class SubHomePersistence[F[_]: Sync] extends SubHomeReadAPI[F] with SubHomeWrite override def updateName(player: UUID, number: SubHome.ID, name: String): F[Unit] = Sync[F].delay { DB.localTx { implicit session => - sql"""insert into seichiassist.sub_home - |(player_uuid, server_id, id, name) values - |(${player.toString},$serverId,$number,$name) - |on duplicate key update - |name = values(name)""" + sql"""update seichiassist.sub_home set name = $name where + | player_uuid = ${player.toString} and + | server_id = $serverId and + | id = $number + |""" .stripMargin('|') .execute() .apply() From f3d1c7256350e528f6808574f284f4ae5b5ad375 Mon Sep 17 00:00:00 2001 From: Kory <6561358+kory33@users.noreply.github.com> Date: Tue, 18 May 2021 18:11:48 +0900 Subject: [PATCH 06/73] =?UTF-8?q?[update]=20@typeclass=E3=82=A2=E3=83=8E?= =?UTF-8?q?=E3=83=86=E3=83=BC=E3=82=B7=E3=83=A7=E3=83=B3=E3=82=92=E5=89=8A?= =?UTF-8?q?=E9=99=A4=E3=81=97plain=E3=81=AB=E6=9B=B8=E3=81=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../seichiassist/subsystems/subhome/SubHomeReadAPI.scala | 8 +++++++- .../seichiassist/subsystems/subhome/SubHomeWriteAPI.scala | 8 +++++++- .../subhome/bukkit/command/SubHomeCommand.scala | 1 - 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/SubHomeReadAPI.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/SubHomeReadAPI.scala index 27b7b9132b..5c62b11b2e 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/SubHomeReadAPI.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/SubHomeReadAPI.scala @@ -5,8 +5,14 @@ import simulacrum.typeclass import java.util.UUID -@typeclass trait SubHomeReadAPI[F[_]] { +trait SubHomeReadAPI[F[_]] { def get(player: UUID, number: SubHome.ID): F[Option[SubHome]] def list(player: UUID): F[Map[SubHome.ID, SubHome]] } + +object SubHomeReadAPI { + + def apply[F[_]](implicit ev: SubHomeReadAPI[F]): SubHomeReadAPI[F] = ev + +} diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/SubHomeWriteAPI.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/SubHomeWriteAPI.scala index 8a68551964..f73bd22702 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/SubHomeWriteAPI.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/SubHomeWriteAPI.scala @@ -6,8 +6,14 @@ import simulacrum.typeclass import java.util.UUID -@typeclass trait SubHomeWriteAPI[F[_]] { +trait SubHomeWriteAPI[F[_]] { def updateLocation(player: UUID, id: SubHome.ID, location: Location): F[Unit] def updateName(player: UUID, id: SubHome.ID, name: String): F[Unit] } + +object SubHomeWriteAPI { + + def apply[F[_]](implicit ev: SubHomeWriteAPI[F]): SubHomeWriteAPI[F] = ev + +} diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/bukkit/command/SubHomeCommand.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/bukkit/command/SubHomeCommand.scala index 4ce5c47296..c3c7847a6f 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/bukkit/command/SubHomeCommand.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/bukkit/command/SubHomeCommand.scala @@ -13,7 +13,6 @@ import com.github.unchama.seichiassist.SeichiAssist import com.github.unchama.seichiassist.commands.contextual.builder.BuilderTemplates.playerCommandBuilder import com.github.unchama.seichiassist.subsystems.subhome.{SubHomeReadAPI, SubHomeWriteAPI} import com.github.unchama.seichiassist.subsystems.subhome.domain.SubHome -import com.github.unchama.seichiassist.subsystems.subhome.infrastructure.SubHomeWriteAPI import com.github.unchama.targetedeffect.commandsender.MessageEffect import org.bukkit.ChatColor._ import org.bukkit.command.TabExecutor From 0594de8a1a1fb59983e83a8471c3243f75671bdc Mon Sep 17 00:00:00 2001 From: Kory <6561358+kory33@users.noreply.github.com> Date: Tue, 18 May 2021 18:23:59 +0900 Subject: [PATCH 07/73] =?UTF-8?q?[clean]=20=E3=82=B7=E3=82=B9=E3=83=86?= =?UTF-8?q?=E3=83=A0=E3=81=AE=E5=88=9D=E6=9C=9F=E5=8C=96=E3=81=AE=E3=82=B3?= =?UTF-8?q?=E3=83=BC=E3=83=89=E3=82=92=E5=8D=98=E7=B4=94=E5=8C=96=E3=81=99?= =?UTF-8?q?=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../subsystems/subhome/SubHomeReadAPI.scala | 2 ++ .../subsystems/subhome/SubHomeWriteAPI.scala | 2 ++ .../subsystems/subhome/System.scala | 19 +++++++++---------- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/SubHomeReadAPI.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/SubHomeReadAPI.scala index 5c62b11b2e..b724b21093 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/SubHomeReadAPI.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/SubHomeReadAPI.scala @@ -6,9 +6,11 @@ import simulacrum.typeclass import java.util.UUID trait SubHomeReadAPI[F[_]] { + def get(player: UUID, number: SubHome.ID): F[Option[SubHome]] def list(player: UUID): F[Map[SubHome.ID, SubHome]] + } object SubHomeReadAPI { diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/SubHomeWriteAPI.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/SubHomeWriteAPI.scala index f73bd22702..f34b6852e1 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/SubHomeWriteAPI.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/SubHomeWriteAPI.scala @@ -7,9 +7,11 @@ import simulacrum.typeclass import java.util.UUID trait SubHomeWriteAPI[F[_]] { + def updateLocation(player: UUID, id: SubHome.ID, location: Location): F[Unit] def updateName(player: UUID, id: SubHome.ID, name: String): F[Unit] + } object SubHomeWriteAPI { diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/System.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/System.scala index 3f56fa4c2a..12110f6b47 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/System.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/System.scala @@ -9,7 +9,7 @@ import com.github.unchama.seichiassist.subsystems.subhome.infrastructure.SubHome import org.bukkit.command.TabExecutor trait System[F[_]] extends Subsystem[F] { - def api: SubHomeReadAPI[F] with SubHomeWriteAPI[F] + val api: SubHomeReadAPI[F] with SubHomeWriteAPI[F] } object System { @@ -17,16 +17,15 @@ object System { F[_] : ConcurrentEffect : NonServerThreadContextShift - ]: System[F] = new System[F] { + ]: System[F] = { val persistence = new SubHomePersistence[F]() - override def api: SubHomeReadAPI[F] with SubHomeWriteAPI[F] = persistence - private implicit val writer: SubHomeWriteAPI[F] = api - private implicit val reader: SubHomeReadAPI[F] = api - - override val commands: Map[String, TabExecutor] = - Map( - "subhome" -> SubHomeCommand.executor - ) + new System[F] { + override implicit val api: SubHomeReadAPI[F] with SubHomeWriteAPI[F] = persistence + override val commands: Map[String, TabExecutor] = + Map( + "subhome" -> SubHomeCommand.executor + ) + } } } From 1c664b52a1a85391959ffbef8ee011e80351ac49 Mon Sep 17 00:00:00 2001 From: Kory <6561358+kory33@users.noreply.github.com> Date: Wed, 19 May 2021 06:09:45 +0900 Subject: [PATCH 08/73] =?UTF-8?q?[update]=20=E3=83=89=E3=83=A1=E3=82=A4?= =?UTF-8?q?=E3=83=B3=E3=81=8CBukkit=E3=81=AB=E4=BE=9D=E5=AD=98=E3=81=97?= =?UTF-8?q?=E3=81=AA=E3=81=84=E3=82=88=E3=81=86=E3=81=AB=E3=81=99=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../subsystems/subhome/domain/SubHome.scala | 7 +++ .../subsystems/subhome/domain/SubHomeId.scala | 3 + .../subhome/domain/SubHomePersistence.scala | 58 +++++++++++++++++++ 3 files changed, 68 insertions(+) create mode 100644 src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/domain/SubHomeId.scala create mode 100644 src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/domain/SubHomePersistence.scala diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/domain/SubHome.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/domain/SubHome.scala index 924ed2a4d1..4755eac944 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/domain/SubHome.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/domain/SubHome.scala @@ -11,6 +11,13 @@ case class SubHome(location: Location, name: String) { } } +case class SubHomeLocation(worldName: String, x: Int, y: Int, z: Int) + +/** + * サブホームオブジェクトのクラス + */ +case class SubHomeV2(name: String, location: SubHomeLocation) + object SubHome { type ID = Int } \ No newline at end of file diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/domain/SubHomeId.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/domain/SubHomeId.scala new file mode 100644 index 0000000000..1f3d9232e9 --- /dev/null +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/domain/SubHomeId.scala @@ -0,0 +1,3 @@ +package com.github.unchama.seichiassist.subsystems.subhome.domain + +case class SubHomeId(value: Int) extends AnyVal diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/domain/SubHomePersistence.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/domain/SubHomePersistence.scala new file mode 100644 index 0000000000..8f259f9e94 --- /dev/null +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/domain/SubHomePersistence.scala @@ -0,0 +1,58 @@ +package com.github.unchama.seichiassist.subsystems.subhome.domain + +import cats.{Functor, Monad} + +import java.util.UUID + +/** + * サブホームの永続化された情報。 + * + * この情報はサーバー間で共有されることを想定していない。 + * 例えばサーバー(s1, s2)、プレーヤーのUUID(u)があった時、s1でlist(u)をした結果とs2でlist(u)をした結果は一般に異なる。 + * これは、サブホームをサーバー間で共有しないという仕様に基づくものである。 + */ +trait SubHomePersistence[F[_]] { + + import cats.implicits._ + + /** + * 指定したUUIDのプレーヤーが現在のサーバーにて設定しているすべてのサブホームを取得する。 + */ + def list(ownerUuid: UUID): F[Map[SubHomeId, SubHomeV2]] + + /** + * サブホームを登録する。idの範囲などのバリデーションはしない。 + * + * すでにサブホームが指定されたidで存在した場合、サブホームを上書きする。 + */ + def upsert(ownerUuid: UUID, id: SubHomeId)(subHome: SubHomeV2): F[Unit] + + /** + * 所有者のUUIDとサブホームのIDから単一のサブホームを取得する。 + */ + final def get(ownerUuid: UUID, id: SubHomeId)(implicit F: Functor[F]): F[Option[SubHomeV2]] = + list(ownerUuid).map(_.get(id)) + + /** + * 指定されたサブホームをnon-atomicに更新する。存在しないサブホームが指定された場合何も行わない。 + * + * 作用の結果として更新が行われたかどうかを示すBooleanを返す。 + */ + final def alter(ownerUuid: UUID, id: SubHomeId)(f: SubHomeV2 => SubHomeV2)(implicit F: Monad[F]): F[Boolean] = + for { + current <- get(ownerUuid, id) + _ <- current match { + case Some(currentSubHome) => upsert(ownerUuid, id)(f(currentSubHome)) + case None => F.unit + } + } yield current.nonEmpty + + /** + * 指定されたサブホームをnon-atomicにリネームする。存在しないサブホームが指定された場合何も行わない。 + * + * 作用の結果として更新が行われたかどうかを示すBooleanを返す。 + */ + final def rename(ownerUuid: UUID, id: SubHomeId)(newName: String)(implicit F: Monad[F]): F[Boolean] = + alter(ownerUuid, id)(_.copy(name = newName)) + +} From 36d25e210dca362601a0ec88711571e3489c5531 Mon Sep 17 00:00:00 2001 From: Kory <6561358+kory33@users.noreply.github.com> Date: Wed, 19 May 2021 06:10:11 +0900 Subject: [PATCH 09/73] =?UTF-8?q?[update]=20SubHomePersistence=E3=81=AE?= =?UTF-8?q?=E5=AE=9F=E8=A3=85=E3=82=92=E8=BF=BD=E5=8A=A0=E3=81=99=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../JdbcSubHomePersistence.scala | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/JdbcSubHomePersistence.scala diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/JdbcSubHomePersistence.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/JdbcSubHomePersistence.scala new file mode 100644 index 0000000000..12d24396bf --- /dev/null +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/JdbcSubHomePersistence.scala @@ -0,0 +1,54 @@ +package com.github.unchama.seichiassist.subsystems.subhome.infrastructure + +import cats.effect.Sync +import com.github.unchama.seichiassist.SeichiAssist +import com.github.unchama.seichiassist.subsystems.subhome.domain.{SubHome, SubHomeId, SubHomeLocation, SubHomePersistence, SubHomeV2} +import com.github.unchama.seichiassist.subsystems.subhome.{SubHomeReadAPI, SubHomeWriteAPI} +import com.github.unchama.targetedeffect.player +import org.bukkit.{Bukkit, Location} +import scalikejdbc._ + +import java.util.UUID + +class JdbcSubHomePersistence[F[_]: Sync] extends SubHomePersistence[F] { + private val serverId = SeichiAssist.seichiAssistConfig.getServerNum + + override def upsert(ownerUuid: UUID, id: SubHomeId)(subHome: SubHomeV2): F[Unit] = { + Sync[F].delay { + DB.readOnly { implicit session => + val SubHomeLocation(worldName, x, y, z) = subHome.location + + sql"""insert into seichiassist.sub_home + |(player_uuid, server_id, id, name, location_x, location_y, location_z, world_name) values + | (${ownerUuid.toString}, $serverId, $id, ${subHome.name}, $x, $y, $z, $worldName) + | on duplicate key update + | name = values(name), + | location_x = values(location_x), + | location_y = values(location_y), + | location_z = values(location_z), + | world_name = values(world_name)""" + .update() + .apply() + } + } + } + + override def list(ownerUuid: UUID): F[Map[SubHomeId, SubHomeV2]] = Sync[F].delay { + DB.readOnly { implicit session => + sql"""SELECT id, name, location_x, location_y, location_z, world_name FROM seichiassist.sub_home""" + .map(rs => (SubHomeId(rs.int("id")), extractSubHome(rs))) + .list().apply() + }.toMap + } + + private def extractSubHome(rs: WrappedResultSet): SubHomeV2 = + SubHomeV2( + rs.string("name"), + SubHomeLocation( + rs.string("world_name"), + rs.int("location_x"), + rs.int("location_y"), + rs.int("location_z") + ) + ) +} From f88d904bcc4f30039930eef2272385cef0873427 Mon Sep 17 00:00:00 2001 From: Kory <6561358+kory33@users.noreply.github.com> Date: Wed, 19 May 2021 07:10:48 +0900 Subject: [PATCH 10/73] =?UTF-8?q?[update]=20=E6=96=B0=E3=81=97=E3=81=84Sub?= =?UTF-8?q?Home=E3=81=AE=E3=83=A2=E3=83=87=E3=83=AB=E3=81=A7=E5=AE=9F?= =?UTF-8?q?=E8=A3=85=E3=82=92=E7=BD=AE=E3=81=8D=E6=8F=9B=E3=81=88=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../seichiassist/data/player/PlayerData.scala | 2 - .../unchama/seichiassist/menus/HomeMenu.scala | 20 +++-- .../subsystems/subhome/SubHomeAPI.scala | 36 ++++++++ .../subsystems/subhome/SubHomeReadAPI.scala | 20 ----- .../subsystems/subhome/SubHomeWriteAPI.scala | 21 ----- .../subsystems/subhome/System.scala | 21 ++++- .../bukkit/command/SubHomeCommand.scala | 22 +++-- .../subsystems/subhome/domain/SubHome.scala | 17 +--- .../subsystems/subhome/domain/SubHomeId.scala | 6 +- .../subhome/domain/SubHomePersistence.scala | 8 +- .../JdbcSubHomePersistence.scala | 19 ++-- .../infrastructure/SubHomePersistence.scala | 86 ------------------- 12 files changed, 99 insertions(+), 179 deletions(-) create mode 100644 src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/SubHomeAPI.scala delete mode 100644 src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/SubHomeReadAPI.scala delete mode 100644 src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/SubHomeWriteAPI.scala delete mode 100644 src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/SubHomePersistence.scala diff --git a/src/main/scala/com/github/unchama/seichiassist/data/player/PlayerData.scala b/src/main/scala/com/github/unchama/seichiassist/data/player/PlayerData.scala index 353810b834..34b550bb9c 100644 --- a/src/main/scala/com/github/unchama/seichiassist/data/player/PlayerData.scala +++ b/src/main/scala/com/github/unchama/seichiassist/data/player/PlayerData.scala @@ -9,7 +9,6 @@ import com.github.unchama.seichiassist.data.GridTemplate import com.github.unchama.seichiassist.data.player.settings.PlayerSettings import com.github.unchama.seichiassist.minestack.MineStackUsageHistory import com.github.unchama.seichiassist.subsystems.breakcount.domain.level.SeichiStarLevel -import com.github.unchama.seichiassist.subsystems.subhome.domain.SubHome import com.github.unchama.seichiassist.task.VotingFairyTask import com.github.unchama.seichiassist.util.Util import com.github.unchama.seichiassist.util.Util.DirectionType @@ -52,7 +51,6 @@ class PlayerData( //プレイヤー名 val lowercaseName: String = name.toLowerCase() - private val subHomeMap: mutable.Map[Int, SubHome] = mutable.HashMap[Int, SubHome]() private val dummyDate = new GregorianCalendar(2100, 1, 1, 0, 0, 0) //チェスト破壊トグル var chestflag = true diff --git a/src/main/scala/com/github/unchama/seichiassist/menus/HomeMenu.scala b/src/main/scala/com/github/unchama/seichiassist/menus/HomeMenu.scala index fc111fb947..dffb4eaa35 100644 --- a/src/main/scala/com/github/unchama/seichiassist/menus/HomeMenu.scala +++ b/src/main/scala/com/github/unchama/seichiassist/menus/HomeMenu.scala @@ -7,7 +7,7 @@ import com.github.unchama.menuinventory.slot.button.Button import com.github.unchama.menuinventory.slot.button.action.LeftClickButtonEffect import com.github.unchama.menuinventory.{ChestSlotRef, Menu, MenuFrame, MenuSlotLayout} import com.github.unchama.seichiassist.subsystems.subhome.SubHomeReadAPI -import com.github.unchama.seichiassist.subsystems.subhome.domain.SubHome +import com.github.unchama.seichiassist.subsystems.subhome.domain.{SubHomeId, SubHome} import com.github.unchama.seichiassist.{ManagedWorld, SeichiAssist} import com.github.unchama.targetedeffect._ import com.github.unchama.targetedeffect.player.PlayerEffects._ @@ -160,20 +160,26 @@ object HomeMenu extends Menu { private case class ButtonComputations(player: Player) { def setSubHomeNameButton[F[_] : SubHomeReadAPI : ConcurrentEffect](subHomeNumber: Int): IO[Button] = { import cats.implicits._ + + val subHomeId = SubHomeId(subHomeNumber) + val program = for { - subhomeOpt <- SubHomeReadAPI[F].get(player.getUniqueId, subHomeNumber - 1) + subhomeOpt <- SubHomeReadAPI[F].get(player.getUniqueId, subHomeId) } yield { val lore = subhomeOpt match { - case None => List(s"${GRAY}サブホームポイント$subHomeNumber", s"${GRAY}ポイント未設定") + case None => List(s"${GRAY}サブホームポイント$subHomeId", s"${GRAY}ポイント未設定") case Some(SubHome(location, name)) => - val worldName = ManagedWorld.fromBukkitWorld(location.getWorld).map(_.japaneseName) - .getOrElse(location.getWorld.getName) + val worldName = + ManagedWorld + .fromBukkitWorld(location.getWorld).map(_.japaneseName) + .getOrElse(location.getWorld.getName) + List( - s"${GRAY}サブホームポイント${subHomeNumber}は", + s"${GRAY}サブホームポイント${subHomeId}は", s"$GRAY$name", s"${GRAY}と名付けられています", s"$DARK_RED${UNDERLINE}クリックで名称変更", - s"${DARK_GRAY}command->[/subhome name $subHomeNumber]", + s"${DARK_GRAY}command->[/subhome name $subHomeId]", s"$GRAY$worldName x:${location.getBlockX} y:${location.getBlockY} z:${location.getBlockZ}" ) } diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/SubHomeAPI.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/SubHomeAPI.scala new file mode 100644 index 0000000000..793d38fcf2 --- /dev/null +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/SubHomeAPI.scala @@ -0,0 +1,36 @@ +package com.github.unchama.seichiassist.subsystems.subhome + +import com.github.unchama.seichiassist.subsystems.subhome.domain.{SubHomeId, SubHome} +import org.bukkit.Location + +import java.util.UUID + +trait SubHomeReadAPI[F[_]] { + + def list(ownerUuid: UUID): F[Map[SubHomeId, SubHome]] + + def get(ownerUuid: UUID, id: SubHomeId): F[Option[SubHome]] + +} + +object SubHomeReadAPI { + + def apply[F[_]](implicit ev: SubHomeReadAPI[F]): SubHomeReadAPI[F] = ev + +} + +trait SubHomeWriteAPI[F[_]] { + + def updateLocation(ownerUuid: UUID, id: SubHomeId, location: Location): F[Unit] + + def updateName(ownerUuid: UUID, id: SubHomeId, name: String): F[Unit] + +} + +object SubHomeWriteAPI { + + def apply[F[_]](implicit ev: SubHomeWriteAPI[F]): SubHomeWriteAPI[F] = ev + +} + +trait SubHomeAPI[F[_]] extends SubHomeReadAPI[F] with SubHomeWriteAPI[F] diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/SubHomeReadAPI.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/SubHomeReadAPI.scala deleted file mode 100644 index b724b21093..0000000000 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/SubHomeReadAPI.scala +++ /dev/null @@ -1,20 +0,0 @@ -package com.github.unchama.seichiassist.subsystems.subhome - -import com.github.unchama.seichiassist.subsystems.subhome.domain.SubHome -import simulacrum.typeclass - -import java.util.UUID - -trait SubHomeReadAPI[F[_]] { - - def get(player: UUID, number: SubHome.ID): F[Option[SubHome]] - - def list(player: UUID): F[Map[SubHome.ID, SubHome]] - -} - -object SubHomeReadAPI { - - def apply[F[_]](implicit ev: SubHomeReadAPI[F]): SubHomeReadAPI[F] = ev - -} diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/SubHomeWriteAPI.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/SubHomeWriteAPI.scala deleted file mode 100644 index f34b6852e1..0000000000 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/SubHomeWriteAPI.scala +++ /dev/null @@ -1,21 +0,0 @@ -package com.github.unchama.seichiassist.subsystems.subhome - -import com.github.unchama.seichiassist.subsystems.subhome.domain.SubHome -import org.bukkit.Location -import simulacrum.typeclass - -import java.util.UUID - -trait SubHomeWriteAPI[F[_]] { - - def updateLocation(player: UUID, id: SubHome.ID, location: Location): F[Unit] - - def updateName(player: UUID, id: SubHome.ID, name: String): F[Unit] - -} - -object SubHomeWriteAPI { - - def apply[F[_]](implicit ev: SubHomeWriteAPI[F]): SubHomeWriteAPI[F] = ev - -} diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/System.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/System.scala index 12110f6b47..94c0e2e62e 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/System.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/System.scala @@ -5,9 +5,13 @@ import com.github.unchama.concurrent.NonServerThreadContextShift import com.github.unchama.seichiassist.SeichiAssist.Scopes.globalChatInterceptionScope import com.github.unchama.seichiassist.meta.subsystem.Subsystem import com.github.unchama.seichiassist.subsystems.subhome.bukkit.command.SubHomeCommand -import com.github.unchama.seichiassist.subsystems.subhome.infrastructure.SubHomePersistence +import com.github.unchama.seichiassist.subsystems.subhome.domain.{SubHomeId, SubHome} +import com.github.unchama.seichiassist.subsystems.subhome.infrastructure.JdbcSubHomePersistence +import org.bukkit.Location import org.bukkit.command.TabExecutor +import java.util.UUID + trait System[F[_]] extends Subsystem[F] { val api: SubHomeReadAPI[F] with SubHomeWriteAPI[F] } @@ -18,10 +22,21 @@ object System { : ConcurrentEffect : NonServerThreadContextShift ]: System[F] = { - val persistence = new SubHomePersistence[F]() + import cats.implicits._ + + val persistence = new JdbcSubHomePersistence[F]() new System[F] { - override implicit val api: SubHomeReadAPI[F] with SubHomeWriteAPI[F] = persistence + override implicit val api: SubHomeAPI[F] = new SubHomeAPI[F] { + override def updateLocation(ownerUuid: UUID, id: SubHomeId, location: Location): F[Unit] = + ??? // TODO semantics not clear + override def updateName(ownerUuid: UUID, id: SubHomeId, name: String): F[Unit] = + persistence.rename(ownerUuid, id)(name).as(()) + override def get(ownerUuid: UUID, id: SubHomeId): F[Option[SubHome]] = + persistence.get(ownerUuid, id) + override def list(ownerUuid: UUID): F[Map[SubHomeId, SubHome]] = + persistence.list(ownerUuid) + } override val commands: Map[String, TabExecutor] = Map( "subhome" -> SubHomeCommand.executor diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/bukkit/command/SubHomeCommand.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/bukkit/command/SubHomeCommand.scala index c3c7847a6f..354e7215f5 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/bukkit/command/SubHomeCommand.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/bukkit/command/SubHomeCommand.scala @@ -1,9 +1,9 @@ package com.github.unchama.seichiassist.subsystems.subhome.bukkit.command import cats.data.Kleisli +import cats.effect.implicits._ import cats.effect.{ConcurrentEffect, IO} import cats.implicits._ -import cats.effect.implicits._ import com.github.unchama.chatinterceptor.CancellationReason.Overridden import com.github.unchama.chatinterceptor.ChatInterceptionScope import com.github.unchama.concurrent.NonServerThreadContextShift @@ -11,8 +11,8 @@ import com.github.unchama.contextualexecutor.builder.Parsers import com.github.unchama.contextualexecutor.executors.{BranchedExecutor, EchoExecutor} import com.github.unchama.seichiassist.SeichiAssist import com.github.unchama.seichiassist.commands.contextual.builder.BuilderTemplates.playerCommandBuilder +import com.github.unchama.seichiassist.subsystems.subhome.domain.{SubHomeId, SubHome} import com.github.unchama.seichiassist.subsystems.subhome.{SubHomeReadAPI, SubHomeWriteAPI} -import com.github.unchama.seichiassist.subsystems.subhome.domain.SubHome import com.github.unchama.targetedeffect.commandsender.MessageEffect import org.bukkit.ChatColor._ import org.bukkit.command.TabExecutor @@ -31,7 +31,9 @@ object SubHomeCommand { ) ) ) + private val subHomeMax = SeichiAssist.seichiAssistConfig.getSubHomeMax + private val argsAndSenderConfiguredBuilder = playerCommandBuilder .argumentsParsers( List( @@ -41,6 +43,7 @@ object SubHomeCommand { ), onMissingArguments = printDescriptionExecutor ) + private def warpExecutor[ F[_] : ConcurrentEffect @@ -48,17 +51,17 @@ object SubHomeCommand { : SubHomeReadAPI ] = argsAndSenderConfiguredBuilder .execution { context => - val subHomeId = context.args.parsed.head.asInstanceOf[Int] + val subHomeId = SubHomeId(context.args.parsed.head.asInstanceOf[Int]) val player = context.sender val eff = for { _ <- NonServerThreadContextShift[F].shift - subHomeLocation <- SubHomeReadAPI[F].get(player.getUniqueId, subHomeId - 1) + subHomeLocation <- SubHomeReadAPI[F].get(player.getUniqueId, subHomeId) } yield { subHomeLocation match { case None => MessageEffect(s"サブホームポイント${subHomeId}が設定されてません") case Some(SubHome(location, _)) => - player.teleport(location) + player.teleport(location) // TODO これは副作用 MessageEffect(s"サブホームポイント${subHomeId}にワープしました") } } @@ -66,6 +69,7 @@ object SubHomeCommand { eff.toIO } .build() + private def setExecutor[ F[_] : ConcurrentEffect @@ -73,12 +77,12 @@ object SubHomeCommand { : SubHomeWriteAPI ] = argsAndSenderConfiguredBuilder .execution { context => - val subHomeId = context.args.parsed.head.asInstanceOf[Int] + val subHomeId = SubHomeId(context.args.parsed.head.asInstanceOf[Int]) val player = context.sender val eff = for { _ <- NonServerThreadContextShift[F].shift - _ <- SubHomeWriteAPI[F].updateLocation(player.getUniqueId, subHomeId - 1, player.getLocation) + _ <- SubHomeWriteAPI[F].updateLocation(player.getUniqueId, subHomeId, player.getLocation) } yield { MessageEffect(s"現在位置をサブホームポイント${subHomeId}に設定しました") } @@ -94,7 +98,7 @@ object SubHomeCommand { : SubHomeWriteAPI ](implicit scope: ChatInterceptionScope) = argsAndSenderConfiguredBuilder .execution { context => - val subHomeId = context.args.parsed.head.asInstanceOf[Int] + val subHomeId = SubHomeId(context.args.parsed.head.asInstanceOf[Int]) IO.pure { val sendInterceptionMessage = @@ -124,7 +128,7 @@ object SubHomeCommand { scope.interceptFrom(uuid).flatMap { case Left(newName) => val eff = for { - _ <- SubHomeWriteAPI[F].updateName(uuid, subHomeId - 1, newName) + _ <- SubHomeWriteAPI[F].updateName(uuid, subHomeId, newName) } yield {} eff.toIO *> sendCompletionMessage(newName)(player) diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/domain/SubHome.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/domain/SubHome.scala index 4755eac944..f2bae749e5 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/domain/SubHome.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/domain/SubHome.scala @@ -1,23 +1,8 @@ package com.github.unchama.seichiassist.subsystems.subhome.domain -import org.bukkit.Location - -/** - * サブホームオブジェクトのクラス - */ -case class SubHome(location: Location, name: String) { - def getLocation = { // BukkitのLocationはミュータブルなのでコピーして返す必要がある - location.clone - } -} - case class SubHomeLocation(worldName: String, x: Int, y: Int, z: Int) /** * サブホームオブジェクトのクラス */ -case class SubHomeV2(name: String, location: SubHomeLocation) - -object SubHome { - type ID = Int -} \ No newline at end of file +case class SubHome(name: String, location: SubHomeLocation) diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/domain/SubHomeId.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/domain/SubHomeId.scala index 1f3d9232e9..7fa0cacdc5 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/domain/SubHomeId.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/domain/SubHomeId.scala @@ -1,3 +1,7 @@ package com.github.unchama.seichiassist.subsystems.subhome.domain -case class SubHomeId(value: Int) extends AnyVal +case class SubHomeId(value: Int) extends AnyVal { + + override def toString: String = value.toString + +} diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/domain/SubHomePersistence.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/domain/SubHomePersistence.scala index 8f259f9e94..81a26eef25 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/domain/SubHomePersistence.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/domain/SubHomePersistence.scala @@ -18,19 +18,19 @@ trait SubHomePersistence[F[_]] { /** * 指定したUUIDのプレーヤーが現在のサーバーにて設定しているすべてのサブホームを取得する。 */ - def list(ownerUuid: UUID): F[Map[SubHomeId, SubHomeV2]] + def list(ownerUuid: UUID): F[Map[SubHomeId, SubHome]] /** * サブホームを登録する。idの範囲などのバリデーションはしない。 * * すでにサブホームが指定されたidで存在した場合、サブホームを上書きする。 */ - def upsert(ownerUuid: UUID, id: SubHomeId)(subHome: SubHomeV2): F[Unit] + def upsert(ownerUuid: UUID, id: SubHomeId)(subHome: SubHome): F[Unit] /** * 所有者のUUIDとサブホームのIDから単一のサブホームを取得する。 */ - final def get(ownerUuid: UUID, id: SubHomeId)(implicit F: Functor[F]): F[Option[SubHomeV2]] = + final def get(ownerUuid: UUID, id: SubHomeId)(implicit F: Functor[F]): F[Option[SubHome]] = list(ownerUuid).map(_.get(id)) /** @@ -38,7 +38,7 @@ trait SubHomePersistence[F[_]] { * * 作用の結果として更新が行われたかどうかを示すBooleanを返す。 */ - final def alter(ownerUuid: UUID, id: SubHomeId)(f: SubHomeV2 => SubHomeV2)(implicit F: Monad[F]): F[Boolean] = + final def alter(ownerUuid: UUID, id: SubHomeId)(f: SubHome => SubHome)(implicit F: Monad[F]): F[Boolean] = for { current <- get(ownerUuid, id) _ <- current match { diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/JdbcSubHomePersistence.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/JdbcSubHomePersistence.scala index 12d24396bf..79421f78ab 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/JdbcSubHomePersistence.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/JdbcSubHomePersistence.scala @@ -2,10 +2,7 @@ package com.github.unchama.seichiassist.subsystems.subhome.infrastructure import cats.effect.Sync import com.github.unchama.seichiassist.SeichiAssist -import com.github.unchama.seichiassist.subsystems.subhome.domain.{SubHome, SubHomeId, SubHomeLocation, SubHomePersistence, SubHomeV2} -import com.github.unchama.seichiassist.subsystems.subhome.{SubHomeReadAPI, SubHomeWriteAPI} -import com.github.unchama.targetedeffect.player -import org.bukkit.{Bukkit, Location} +import com.github.unchama.seichiassist.subsystems.subhome.domain.{SubHomeId, SubHomeLocation, SubHomePersistence, SubHome} import scalikejdbc._ import java.util.UUID @@ -13,14 +10,15 @@ import java.util.UUID class JdbcSubHomePersistence[F[_]: Sync] extends SubHomePersistence[F] { private val serverId = SeichiAssist.seichiAssistConfig.getServerNum - override def upsert(ownerUuid: UUID, id: SubHomeId)(subHome: SubHomeV2): F[Unit] = { + override def upsert(ownerUuid: UUID, id: SubHomeId)(subHome: SubHome): F[Unit] = { Sync[F].delay { DB.readOnly { implicit session => val SubHomeLocation(worldName, x, y, z) = subHome.location + // NOTE 2021/05/19: 何故かDB上のIDは1少ない。つまり、ID 1のサブホームはDB上ではid=0である。 sql"""insert into seichiassist.sub_home |(player_uuid, server_id, id, name, location_x, location_y, location_z, world_name) values - | (${ownerUuid.toString}, $serverId, $id, ${subHome.name}, $x, $y, $z, $worldName) + | (${ownerUuid.toString}, $serverId, ${id.value - 1}, ${subHome.name}, $x, $y, $z, $worldName) | on duplicate key update | name = values(name), | location_x = values(location_x), @@ -33,16 +31,17 @@ class JdbcSubHomePersistence[F[_]: Sync] extends SubHomePersistence[F] { } } - override def list(ownerUuid: UUID): F[Map[SubHomeId, SubHomeV2]] = Sync[F].delay { + override def list(ownerUuid: UUID): F[Map[SubHomeId, SubHome]] = Sync[F].delay { DB.readOnly { implicit session => + // NOTE 2021/05/19: 何故かDB上のIDは1少ない。つまり、ID 1のサブホームはDB上ではid=0である。 sql"""SELECT id, name, location_x, location_y, location_z, world_name FROM seichiassist.sub_home""" - .map(rs => (SubHomeId(rs.int("id")), extractSubHome(rs))) + .map(rs => (SubHomeId(rs.int("id") + 1), extractSubHome(rs))) .list().apply() }.toMap } - private def extractSubHome(rs: WrappedResultSet): SubHomeV2 = - SubHomeV2( + private def extractSubHome(rs: WrappedResultSet): SubHome = + SubHome( rs.string("name"), SubHomeLocation( rs.string("world_name"), diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/SubHomePersistence.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/SubHomePersistence.scala deleted file mode 100644 index 075e926f83..0000000000 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/SubHomePersistence.scala +++ /dev/null @@ -1,86 +0,0 @@ -package com.github.unchama.seichiassist.subsystems.subhome.infrastructure - -import cats.effect.Sync -import com.github.unchama.seichiassist.SeichiAssist -import com.github.unchama.seichiassist.subsystems.subhome.{SubHomeReadAPI, SubHomeWriteAPI} -import com.github.unchama.seichiassist.subsystems.subhome.domain.SubHome -import org.bukkit.{Bukkit, Location} -import scalikejdbc._ - -import java.util.UUID - -class SubHomePersistence[F[_]: Sync] extends SubHomeReadAPI[F] with SubHomeWriteAPI[F] { - private val serverId = SeichiAssist.seichiAssistConfig.getServerNum - - override def get(player: UUID, id: SubHome.ID): F[Option[SubHome]] = { - Sync[F].delay { - DB.readOnly { implicit session => - sql"""SELECT id, name, location_x, location_y, location_z, world_name FROM seichiassist.sub_home - WHERE name = ${player.toString} AND server_id = $serverId AND id = $id""" - .map(extractSubHome) - // もしかすると見つからないかもしれない - .first() - .apply() - } - } - } - - override def list(player: UUID): F[Map[SubHome.ID, SubHome]] = Sync[F].delay { - DB.readOnly { implicit session => - sql"""SELECT id, name, location_x, location_y, location_z, world_name FROM seichiassist.sub_home""" - .map(rs => { - ( - rs.int("id"), - extractSubHome(rs) - ) - }) - .list() - .apply() - }.toMap - } - - override def updateLocation(player: UUID, id: SubHome.ID, location: Location): F[Unit] = - Sync[F].delay { - val x = location.getX.toInt - val y = location.getY.toInt - val z = location.getZ.toInt - val worldName = location.getWorld.getName - DB.localTx { implicit session => - // 重複したとき、もとのエントリを残す必要はないので黙って上書きする - sql"""insert into seichiassist.sub_home - |(player_uuid, server_id, id, location_x, location_y, location_z, world_name) values - | (${player.toString}, $serverId, $id, $x, $y, $z, $worldName) - | on duplicate key update - | location_x = values(location_x), - | location_y = values(location_y), - | location_z = values(location_z), - | world_name = values(world_name)""" - .stripMargin('|') - .execute() - .apply() - } - } - - override def updateName(player: UUID, number: SubHome.ID, name: String): F[Unit] = - Sync[F].delay { - DB.localTx { implicit session => - sql"""update seichiassist.sub_home set name = $name where - | player_uuid = ${player.toString} and - | server_id = $serverId and - | id = $number - |""" - .stripMargin('|') - .execute() - .apply() - } - } - - private def extractSubHome(rs: WrappedResultSet): SubHome = { - val x = rs.int("location_x") - val y = rs.int("location_y") - val z = rs.int("location_z") - val world = Bukkit.getWorld(rs.string("world_name")) - val homeName = rs.string("name") - new SubHome(new Location(world, x, y, z), homeName) - } -} From f627bf2b8bb575453168e01842504723d6702422 Mon Sep 17 00:00:00 2001 From: Kory <6561358+kory33@users.noreply.github.com> Date: Wed, 19 May 2021 07:41:16 +0900 Subject: [PATCH 11/73] =?UTF-8?q?[update]=20SubHome=E3=81=AE=E3=83=A2?= =?UTF-8?q?=E3=83=87=E3=83=AB=E3=82=92=E6=94=B9=E5=96=84=E3=81=99=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../github/unchama/seichiassist/data/player/PlayerData.scala | 1 - .../seichiassist/subsystems/subhome/domain/SubHome.scala | 2 +- .../subsystems/subhome/domain/SubHomePersistence.scala | 2 +- .../subhome/infrastructure/JdbcSubHomePersistence.scala | 4 ++-- .../github/unchama/seichiassist/task/PlayerDataLoading.scala | 2 -- 5 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/main/scala/com/github/unchama/seichiassist/data/player/PlayerData.scala b/src/main/scala/com/github/unchama/seichiassist/data/player/PlayerData.scala index 34b550bb9c..b19fefd0fa 100644 --- a/src/main/scala/com/github/unchama/seichiassist/data/player/PlayerData.scala +++ b/src/main/scala/com/github/unchama/seichiassist/data/player/PlayerData.scala @@ -70,7 +70,6 @@ class PlayerData( var gachacooldownflag = true //インベントリ共有ボタン連打防止用 var shareinvcooldownflag = true - var selectHomeNum = 0 var samepageflag = false //実績ショップ用 //endregion diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/domain/SubHome.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/domain/SubHome.scala index f2bae749e5..386ee7b1bb 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/domain/SubHome.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/domain/SubHome.scala @@ -5,4 +5,4 @@ case class SubHomeLocation(worldName: String, x: Int, y: Int, z: Int) /** * サブホームオブジェクトのクラス */ -case class SubHome(name: String, location: SubHomeLocation) +case class SubHome(name: Option[String], location: SubHomeLocation) diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/domain/SubHomePersistence.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/domain/SubHomePersistence.scala index 81a26eef25..7bf9dc1127 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/domain/SubHomePersistence.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/domain/SubHomePersistence.scala @@ -53,6 +53,6 @@ trait SubHomePersistence[F[_]] { * 作用の結果として更新が行われたかどうかを示すBooleanを返す。 */ final def rename(ownerUuid: UUID, id: SubHomeId)(newName: String)(implicit F: Monad[F]): F[Boolean] = - alter(ownerUuid, id)(_.copy(name = newName)) + alter(ownerUuid, id)(_.copy(name = Some(newName))) } diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/JdbcSubHomePersistence.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/JdbcSubHomePersistence.scala index 79421f78ab..a06811fcaa 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/JdbcSubHomePersistence.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/JdbcSubHomePersistence.scala @@ -18,7 +18,7 @@ class JdbcSubHomePersistence[F[_]: Sync] extends SubHomePersistence[F] { // NOTE 2021/05/19: 何故かDB上のIDは1少ない。つまり、ID 1のサブホームはDB上ではid=0である。 sql"""insert into seichiassist.sub_home |(player_uuid, server_id, id, name, location_x, location_y, location_z, world_name) values - | (${ownerUuid.toString}, $serverId, ${id.value - 1}, ${subHome.name}, $x, $y, $z, $worldName) + | (${ownerUuid.toString}, $serverId, ${id.value - 1}, ${subHome.name.orNull}, $x, $y, $z, $worldName) | on duplicate key update | name = values(name), | location_x = values(location_x), @@ -42,7 +42,7 @@ class JdbcSubHomePersistence[F[_]: Sync] extends SubHomePersistence[F] { private def extractSubHome(rs: WrappedResultSet): SubHome = SubHome( - rs.string("name"), + rs.stringOpt("name"), SubHomeLocation( rs.string("world_name"), rs.int("location_x"), diff --git a/src/main/scala/com/github/unchama/seichiassist/task/PlayerDataLoading.scala b/src/main/scala/com/github/unchama/seichiassist/task/PlayerDataLoading.scala index d31c62cd64..e35071f641 100644 --- a/src/main/scala/com/github/unchama/seichiassist/task/PlayerDataLoading.scala +++ b/src/main/scala/com/github/unchama/seichiassist/task/PlayerDataLoading.scala @@ -207,8 +207,6 @@ object PlayerDataLoading { serializedInventory != null && serializedInventory != "" } - playerData.selectHomeNum = 0 - //実績、二つ名の情報 playerData.p_vote_forT = rs.getInt("p_vote") playerData.giveachvNo = rs.getInt("giveachvNo") From ad21ec5143d607f8bdf4a666aedf865321d02106 Mon Sep 17 00:00:00 2001 From: Kory <6561358+kory33@users.noreply.github.com> Date: Wed, 19 May 2021 07:52:15 +0900 Subject: [PATCH 12/73] =?UTF-8?q?[update]=20JdbcSubHomePersistence?= =?UTF-8?q?=E3=81=8C=E5=B8=B8=E3=81=ABshift=E3=81=99=E3=82=8B=E3=82=88?= =?UTF-8?q?=E3=81=86=E3=81=AB=E3=81=99=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../JdbcSubHomePersistence.scala | 53 ++++++++++--------- 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/JdbcSubHomePersistence.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/JdbcSubHomePersistence.scala index a06811fcaa..f9289a9e7e 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/JdbcSubHomePersistence.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/JdbcSubHomePersistence.scala @@ -1,17 +1,20 @@ package com.github.unchama.seichiassist.subsystems.subhome.infrastructure import cats.effect.Sync +import com.github.unchama.concurrent.NonServerThreadContextShift import com.github.unchama.seichiassist.SeichiAssist -import com.github.unchama.seichiassist.subsystems.subhome.domain.{SubHomeId, SubHomeLocation, SubHomePersistence, SubHome} +import com.github.unchama.seichiassist.subsystems.subhome.domain.{SubHome, SubHomeId, SubHomeLocation, SubHomePersistence} import scalikejdbc._ import java.util.UUID -class JdbcSubHomePersistence[F[_]: Sync] extends SubHomePersistence[F] { +class JdbcSubHomePersistence[F[_]: Sync: NonServerThreadContextShift] extends SubHomePersistence[F] { private val serverId = SeichiAssist.seichiAssistConfig.getServerNum - override def upsert(ownerUuid: UUID, id: SubHomeId)(subHome: SubHome): F[Unit] = { - Sync[F].delay { + import cats.implicits._ + + override def upsert(ownerUuid: UUID, id: SubHomeId)(subHome: SubHome): F[Unit] = + NonServerThreadContextShift[F].shift >> Sync[F].delay[Unit] { DB.readOnly { implicit session => val SubHomeLocation(worldName, x, y, z) = subHome.location @@ -29,25 +32,27 @@ class JdbcSubHomePersistence[F[_]: Sync] extends SubHomePersistence[F] { .apply() } } - } - - override def list(ownerUuid: UUID): F[Map[SubHomeId, SubHome]] = Sync[F].delay { - DB.readOnly { implicit session => - // NOTE 2021/05/19: 何故かDB上のIDは1少ない。つまり、ID 1のサブホームはDB上ではid=0である。 - sql"""SELECT id, name, location_x, location_y, location_z, world_name FROM seichiassist.sub_home""" - .map(rs => (SubHomeId(rs.int("id") + 1), extractSubHome(rs))) - .list().apply() - }.toMap - } - private def extractSubHome(rs: WrappedResultSet): SubHome = - SubHome( - rs.stringOpt("name"), - SubHomeLocation( - rs.string("world_name"), - rs.int("location_x"), - rs.int("location_y"), - rs.int("location_z") - ) - ) + override def list(ownerUuid: UUID): F[Map[SubHomeId, SubHome]] = + NonServerThreadContextShift[F].shift >> Sync[F].delay { + DB.readOnly { implicit session => + // NOTE 2021/05/19: 何故かDB上のIDは1少ない。つまり、ID 1のサブホームはDB上ではid=0である。 + sql"""SELECT id, name, location_x, location_y, location_z, world_name FROM seichiassist.sub_home""" + .map(rs => + ( + SubHomeId(rs.int("id") + 1), + SubHome( + rs.stringOpt("name"), + SubHomeLocation( + rs.string("world_name"), + rs.int("location_x"), + rs.int("location_y"), + rs.int("location_z") + ) + ) + ) + ) + .list().apply() + }.toMap + } } From c54542e28695066f1d77d01ce284fa505be0382d Mon Sep 17 00:00:00 2001 From: Kory <6561358+kory33@users.noreply.github.com> Date: Fri, 30 Jul 2021 08:15:39 +0900 Subject: [PATCH 13/73] =?UTF-8?q?[fix]=20=E3=82=B3=E3=83=B3=E3=83=91?= =?UTF-8?q?=E3=82=A4=E3=83=AB=E3=82=A8=E3=83=A9=E3=83=BC=E3=82=92=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3=E3=81=99=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../unchama/seichiassist/menus/HomeMenu.scala | 13 +++++++------ .../unchama/seichiassist/menus/TopLevelRouter.scala | 6 ++---- .../subhome/bukkit/command/SubHomeCommand.scala | 8 +++++--- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/main/scala/com/github/unchama/seichiassist/menus/HomeMenu.scala b/src/main/scala/com/github/unchama/seichiassist/menus/HomeMenu.scala index dffb4eaa35..a031f90482 100644 --- a/src/main/scala/com/github/unchama/seichiassist/menus/HomeMenu.scala +++ b/src/main/scala/com/github/unchama/seichiassist/menus/HomeMenu.scala @@ -7,7 +7,7 @@ import com.github.unchama.menuinventory.slot.button.Button import com.github.unchama.menuinventory.slot.button.action.LeftClickButtonEffect import com.github.unchama.menuinventory.{ChestSlotRef, Menu, MenuFrame, MenuSlotLayout} import com.github.unchama.seichiassist.subsystems.subhome.SubHomeReadAPI -import com.github.unchama.seichiassist.subsystems.subhome.domain.{SubHomeId, SubHome} +import com.github.unchama.seichiassist.subsystems.subhome.domain.{SubHome, SubHomeId} import com.github.unchama.seichiassist.{ManagedWorld, SeichiAssist} import com.github.unchama.targetedeffect._ import com.github.unchama.targetedeffect.player.PlayerEffects._ @@ -168,11 +168,12 @@ object HomeMenu extends Menu { } yield { val lore = subhomeOpt match { case None => List(s"${GRAY}サブホームポイント$subHomeId", s"${GRAY}ポイント未設定") - case Some(SubHome(location, name)) => - val worldName = + case Some(SubHome(name, location)) => + val worldName = { ManagedWorld - .fromBukkitWorld(location.getWorld).map(_.japaneseName) - .getOrElse(location.getWorld.getName) + .fromName(location.worldName).map(_.japaneseName) + .getOrElse(location.worldName) + } List( s"${GRAY}サブホームポイント${subHomeId}は", @@ -180,7 +181,7 @@ object HomeMenu extends Menu { s"${GRAY}と名付けられています", s"$DARK_RED${UNDERLINE}クリックで名称変更", s"${DARK_GRAY}command->[/subhome name $subHomeId]", - s"$GRAY$worldName x:${location.getBlockX} y:${location.getBlockY} z:${location.getBlockZ}" + s"$GRAY$worldName x:${location.x} y:${location.y} z:${location.z}" ) } diff --git a/src/main/scala/com/github/unchama/seichiassist/menus/TopLevelRouter.scala b/src/main/scala/com/github/unchama/seichiassist/menus/TopLevelRouter.scala index 8ab6c46f63..eb82503812 100644 --- a/src/main/scala/com/github/unchama/seichiassist/menus/TopLevelRouter.scala +++ b/src/main/scala/com/github/unchama/seichiassist/menus/TopLevelRouter.scala @@ -15,15 +15,14 @@ import com.github.unchama.seichiassist.subsystems.breakcount.BreakCountAPI import com.github.unchama.seichiassist.subsystems.breakcount.domain.SeichiAmountData import com.github.unchama.seichiassist.subsystems.breakcountbar.BreakCountBarAPI import com.github.unchama.seichiassist.subsystems.buildcount.domain.playerdata.BuildAmountData +import com.github.unchama.seichiassist.subsystems.discordnotification.DiscordNotificationAPI import com.github.unchama.seichiassist.subsystems.fastdiggingeffect.{FastDiggingEffectApi, FastDiggingSettingsApi} import com.github.unchama.seichiassist.subsystems.fourdimensionalpocket.FourDimensionalPocketApi import com.github.unchama.seichiassist.subsystems.gachapoint.GachaPointApi import com.github.unchama.seichiassist.subsystems.mana.ManaApi -import com.github.unchama.seichiassist.subsystems.ranking.RankingApi -import com.github.unchama.seichiassist.subsystems.subhome.SubHomeReadAPI -import com.github.unchama.seichiassist.subsystems.discordnotification.DiscordNotificationAPI import com.github.unchama.seichiassist.subsystems.ranking.api.AssortedRankingApi import com.github.unchama.seichiassist.subsystems.ranking.domain.values.{LoginTime, VoteCount} +import com.github.unchama.seichiassist.subsystems.subhome.SubHomeReadAPI import io.chrisdavenport.cats.effect.time.JavaTime import org.bukkit.entity.Player @@ -53,7 +52,6 @@ object TopLevelRouter { subHomeReadApi: SubHomeReadAPI[IO]): TopLevelRouter[IO] = new TopLevelRouter[IO] { import assortedRankingApi._ - implicit lazy val seichiRankingMenuEnv: SeichiRankingMenu.Environment = new SeichiRankingMenu.Environment implicit lazy val secondPageEnv: SecondPage.Environment = new SecondPage.Environment implicit lazy val mineStackMainMenuEnv: MineStackMainMenu.Environment = new MineStackMainMenu.Environment implicit lazy val categorizedMineStackMenuEnv: CategorizedMineStackMenu.Environment = new CategorizedMineStackMenu.Environment diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/bukkit/command/SubHomeCommand.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/bukkit/command/SubHomeCommand.scala index 354e7215f5..baefb1e576 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/bukkit/command/SubHomeCommand.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/bukkit/command/SubHomeCommand.scala @@ -11,11 +11,12 @@ import com.github.unchama.contextualexecutor.builder.Parsers import com.github.unchama.contextualexecutor.executors.{BranchedExecutor, EchoExecutor} import com.github.unchama.seichiassist.SeichiAssist import com.github.unchama.seichiassist.commands.contextual.builder.BuilderTemplates.playerCommandBuilder -import com.github.unchama.seichiassist.subsystems.subhome.domain.{SubHomeId, SubHome} +import com.github.unchama.seichiassist.subsystems.subhome.domain.{SubHome, SubHomeId} import com.github.unchama.seichiassist.subsystems.subhome.{SubHomeReadAPI, SubHomeWriteAPI} import com.github.unchama.targetedeffect.commandsender.MessageEffect import org.bukkit.ChatColor._ import org.bukkit.command.TabExecutor +import org.bukkit.{Bukkit, Location} object SubHomeCommand { private val printDescriptionExecutor = new EchoExecutor( @@ -60,8 +61,9 @@ object SubHomeCommand { } yield { subHomeLocation match { case None => MessageEffect(s"サブホームポイント${subHomeId}が設定されてません") - case Some(SubHome(location, _)) => - player.teleport(location) // TODO これは副作用 + case Some(SubHome(_, location)) => + // TODO これは副作用 + player.teleport(new Location(Bukkit.getWorld(location.worldName), location.x, location.y, location.z)) MessageEffect(s"サブホームポイント${subHomeId}にワープしました") } } From 7bbcfc77f1ea61a43fb09fe72517212ff605a88d Mon Sep 17 00:00:00 2001 From: Lucky <lucky3028@users.noreply.github.com> Date: Mon, 2 Aug 2021 15:47:25 +0900 Subject: [PATCH 14/73] =?UTF-8?q?[Fix]=20=E4=BF=AE=E7=B9=95=E3=81=AE?= =?UTF-8?q?=E6=9C=AC=E3=82=92=E3=82=B3=E3=83=94=E3=83=BC=E3=81=97=E3=81=A6?= =?UTF-8?q?=E3=82=82=E9=80=9A=E5=B8=B8=E9=80=9A=E3=82=8A=E4=BD=BF=E3=81=88?= =?UTF-8?q?=E3=81=A6=E3=81=97=E3=81=BE=E3=81=86=E5=95=8F=E9=A1=8C=E3=82=92?= =?UTF-8?q?=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../seasonalevents/anniversary/AnniversaryItemData.scala | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/seasonalevents/anniversary/AnniversaryItemData.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/seasonalevents/anniversary/AnniversaryItemData.scala index 2cc9d03838..b2590acd46 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/seasonalevents/anniversary/AnniversaryItemData.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/seasonalevents/anniversary/AnniversaryItemData.scala @@ -8,8 +8,9 @@ import org.bukkit.Bukkit import org.bukkit.ChatColor._ import org.bukkit.Material._ import org.bukkit.enchantments.Enchantment +import org.bukkit.inventory.meta.BookMeta.Generation +import org.bukkit.inventory.meta.{BookMeta, ItemMeta, SkullMeta} import org.bukkit.inventory.{ItemFlag, ItemStack} -import org.bukkit.inventory.meta.SkullMeta import scala.jdk.CollectionConverters._ import scala.util.chaining._ @@ -100,6 +101,12 @@ object AnniversaryItemData { def isMendingBook(item: ItemStack): Boolean = item != null && item.getType == WRITTEN_BOOK && { new NBTItem(item).getByte(NBTTagConstants.typeIdTag) == 2 + } && isOriginalBook(item.getItemMeta) + + private def isOriginalBook(meta: ItemMeta) = + meta match { + case bookMeta: BookMeta => bookMeta.hasGeneration && bookMeta.getGeneration == Generation.ORIGINAL + case _ => false } //endregion From 4d0a52882aa4f3ecfe7ea140a7787052ac011749 Mon Sep 17 00:00:00 2001 From: Lucky <lucky3028@users.noreply.github.com> Date: Mon, 2 Aug 2021 15:57:06 +0900 Subject: [PATCH 15/73] =?UTF-8?q?[Add]=20ItemMeta=E3=82=92=E3=82=82?= =?UTF-8?q?=E3=81=A3=E3=81=A6=E3=81=84=E3=82=8B=E3=81=8B=E3=81=A9=E3=81=86?= =?UTF-8?q?=E3=81=8B=E3=81=AE=E7=A2=BA=E8=AA=8D=E3=82=92=E3=81=99=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../seasonalevents/anniversary/AnniversaryItemData.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/seasonalevents/anniversary/AnniversaryItemData.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/seasonalevents/anniversary/AnniversaryItemData.scala index b2590acd46..92eea6154e 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/seasonalevents/anniversary/AnniversaryItemData.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/seasonalevents/anniversary/AnniversaryItemData.scala @@ -101,7 +101,7 @@ object AnniversaryItemData { def isMendingBook(item: ItemStack): Boolean = item != null && item.getType == WRITTEN_BOOK && { new NBTItem(item).getByte(NBTTagConstants.typeIdTag) == 2 - } && isOriginalBook(item.getItemMeta) + } && item.hasItemMeta && isOriginalBook(item.getItemMeta) private def isOriginalBook(meta: ItemMeta) = meta match { From 3070219873f4024c7038906837791a8e9e88dc2d Mon Sep 17 00:00:00 2001 From: Lucky <lucky3028@users.noreply.github.com> Date: Mon, 2 Aug 2021 15:58:38 +0900 Subject: [PATCH 16/73] =?UTF-8?q?[Fix]=20=E3=83=AC=E3=83=93=E3=83=A5?= =?UTF-8?q?=E3=83=BC=E3=82=92=E5=8F=97=E3=81=91=E3=81=9F=E5=86=85=E5=AE=B9?= =?UTF-8?q?=E3=81=AE=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../anniversary/AnniversaryItemData.scala | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/seasonalevents/anniversary/AnniversaryItemData.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/seasonalevents/anniversary/AnniversaryItemData.scala index 92eea6154e..b4bcc7f985 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/seasonalevents/anniversary/AnniversaryItemData.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/seasonalevents/anniversary/AnniversaryItemData.scala @@ -98,16 +98,17 @@ object AnniversaryItemData { .pipe(_.getItem) } - def isMendingBook(item: ItemStack): Boolean = + def isMendingBook(item: ItemStack): Boolean = { + def isOriginal(meta: ItemMeta) = + meta match { + case bookMeta: BookMeta => bookMeta.hasGeneration && bookMeta.getGeneration == Generation.ORIGINAL + case _ => false + } + item != null && item.getType == WRITTEN_BOOK && { new NBTItem(item).getByte(NBTTagConstants.typeIdTag) == 2 - } && item.hasItemMeta && isOriginalBook(item.getItemMeta) - - private def isOriginalBook(meta: ItemMeta) = - meta match { - case bookMeta: BookMeta => bookMeta.hasGeneration && bookMeta.getGeneration == Generation.ORIGINAL - case _ => false - } + } && item.hasItemMeta && isOriginal(item.getItemMeta) + } //endregion From e2db25654c06d5c4f53be9bc36974826b2352aa0 Mon Sep 17 00:00:00 2001 From: Kory <6561358+kory33@users.noreply.github.com> Date: Mon, 2 Aug 2021 16:46:48 +0900 Subject: [PATCH 17/73] =?UTF-8?q?[update]=20rename=E6=99=82=E3=81=AB?= =?UTF-8?q?=E3=82=B5=E3=83=96=E3=83=9B=E3=83=BC=E3=83=A0=E3=81=8C=E5=AD=98?= =?UTF-8?q?=E5=9C=A8=E3=81=97=E3=81=A6=E3=81=84=E3=81=AA=E3=81=8B=E3=81=A3?= =?UTF-8?q?=E3=81=9F=E5=A0=B4=E5=90=88=E3=81=AE=E6=8C=99=E5=8B=95=E3=82=92?= =?UTF-8?q?=E6=98=8E=E7=A4=BA=E7=9A=84=E3=81=AB=E8=A8=98=E8=BF=B0=E3=81=99?= =?UTF-8?q?=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../subsystems/subhome/SubHomeAPI.scala | 7 +- .../subsystems/subhome/System.scala | 14 ++- .../subhome/bukkit/LocationCodec.scala | 24 ++++++ .../subhome/bukkit/TeleportEffect.scala | 14 +++ .../bukkit/command/SubHomeCommand.scala | 85 ++++++++++--------- .../subhome/domain/OperationResult.scala | 9 ++ .../subhome/domain/SubHomePersistence.scala | 9 +- 7 files changed, 105 insertions(+), 57 deletions(-) create mode 100644 src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/bukkit/LocationCodec.scala create mode 100644 src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/bukkit/TeleportEffect.scala create mode 100644 src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/domain/OperationResult.scala diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/SubHomeAPI.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/SubHomeAPI.scala index 793d38fcf2..36d6eab12d 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/SubHomeAPI.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/SubHomeAPI.scala @@ -1,7 +1,6 @@ package com.github.unchama.seichiassist.subsystems.subhome -import com.github.unchama.seichiassist.subsystems.subhome.domain.{SubHomeId, SubHome} -import org.bukkit.Location +import com.github.unchama.seichiassist.subsystems.subhome.domain.{OperationResult, SubHome, SubHomeId, SubHomeLocation} import java.util.UUID @@ -21,9 +20,9 @@ object SubHomeReadAPI { trait SubHomeWriteAPI[F[_]] { - def updateLocation(ownerUuid: UUID, id: SubHomeId, location: Location): F[Unit] + def upsertLocation(ownerUuid: UUID, id: SubHomeId, location: SubHomeLocation): F[Unit] - def updateName(ownerUuid: UUID, id: SubHomeId, name: String): F[Unit] + def rename(ownerUuid: UUID, id: SubHomeId)(name: String): F[OperationResult.RenameResult] } diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/System.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/System.scala index 94c0e2e62e..752880de03 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/System.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/System.scala @@ -5,9 +5,9 @@ import com.github.unchama.concurrent.NonServerThreadContextShift import com.github.unchama.seichiassist.SeichiAssist.Scopes.globalChatInterceptionScope import com.github.unchama.seichiassist.meta.subsystem.Subsystem import com.github.unchama.seichiassist.subsystems.subhome.bukkit.command.SubHomeCommand -import com.github.unchama.seichiassist.subsystems.subhome.domain.{SubHomeId, SubHome} +import com.github.unchama.seichiassist.subsystems.subhome.domain.OperationResult.RenameResult +import com.github.unchama.seichiassist.subsystems.subhome.domain.{SubHome, SubHomeId, SubHomeLocation} import com.github.unchama.seichiassist.subsystems.subhome.infrastructure.JdbcSubHomePersistence -import org.bukkit.Location import org.bukkit.command.TabExecutor import java.util.UUID @@ -22,16 +22,14 @@ object System { : ConcurrentEffect : NonServerThreadContextShift ]: System[F] = { - import cats.implicits._ - val persistence = new JdbcSubHomePersistence[F]() new System[F] { override implicit val api: SubHomeAPI[F] = new SubHomeAPI[F] { - override def updateLocation(ownerUuid: UUID, id: SubHomeId, location: Location): F[Unit] = - ??? // TODO semantics not clear - override def updateName(ownerUuid: UUID, id: SubHomeId, name: String): F[Unit] = - persistence.rename(ownerUuid, id)(name).as(()) + override def upsertLocation(ownerUuid: UUID, id: SubHomeId, location: SubHomeLocation): F[Unit] = + persistence.upsert(ownerUuid, id)(SubHome(None, location)) + override def rename(ownerUuid: UUID, id: SubHomeId)(name: String): F[RenameResult] = + persistence.rename(ownerUuid, id)(name) override def get(ownerUuid: UUID, id: SubHomeId): F[Option[SubHome]] = persistence.get(ownerUuid, id) override def list(ownerUuid: UUID): F[Map[SubHomeId, SubHome]] = diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/bukkit/LocationCodec.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/bukkit/LocationCodec.scala new file mode 100644 index 0000000000..69fbc82467 --- /dev/null +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/bukkit/LocationCodec.scala @@ -0,0 +1,24 @@ +package com.github.unchama.seichiassist.subsystems.subhome.bukkit + +import com.github.unchama.seichiassist.subsystems.subhome.domain.SubHomeLocation +import org.bukkit.{Bukkit, Location} + +/** + * [[org.bukkit.Location]] と [[SubHomeLocation]] との相互変換を実現するコーデック。 + * + * [[SubHomeLocation]] は [[org.bukkit.Location]] よりも真に情報量が少ない(ワールドへの参照を持っていない)ため、 + * [[SubHomeLocation]] から [[org.bukkit.Location]] への変換は [[Option]] として返ってくる。 + */ +object LocationCodec { + + def fromBukkitLocation(location: Location): SubHomeLocation = { + SubHomeLocation(location.getWorld.getName, location.getBlockX, location.getBlockY, location.getBlockZ) + } + + def toBukkitLocation(location: SubHomeLocation): Option[Location] = { + val world = Bukkit.getWorld(location.worldName) + + Option.when(world != null)(new Location(world, location.x, location.y, location.z)) + } + +} diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/bukkit/TeleportEffect.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/bukkit/TeleportEffect.scala new file mode 100644 index 0000000000..95c5282086 --- /dev/null +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/bukkit/TeleportEffect.scala @@ -0,0 +1,14 @@ +package com.github.unchama.seichiassist.subsystems.subhome.bukkit + +import cats.data.Kleisli +import cats.effect.Sync +import org.bukkit.Location +import org.bukkit.entity.Player + +object TeleportEffect { + def to[F[_]: Sync](location: Location): Kleisli[F, Player, Unit] = { + Kleisli { player => + Sync[F].delay(player.teleport(location)) + } + } +} diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/bukkit/command/SubHomeCommand.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/bukkit/command/SubHomeCommand.scala index baefb1e576..41a9ea323a 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/bukkit/command/SubHomeCommand.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/bukkit/command/SubHomeCommand.scala @@ -3,7 +3,6 @@ package com.github.unchama.seichiassist.subsystems.subhome.bukkit.command import cats.data.Kleisli import cats.effect.implicits._ import cats.effect.{ConcurrentEffect, IO} -import cats.implicits._ import com.github.unchama.chatinterceptor.CancellationReason.Overridden import com.github.unchama.chatinterceptor.ChatInterceptionScope import com.github.unchama.concurrent.NonServerThreadContextShift @@ -11,14 +10,17 @@ import com.github.unchama.contextualexecutor.builder.Parsers import com.github.unchama.contextualexecutor.executors.{BranchedExecutor, EchoExecutor} import com.github.unchama.seichiassist.SeichiAssist import com.github.unchama.seichiassist.commands.contextual.builder.BuilderTemplates.playerCommandBuilder +import com.github.unchama.seichiassist.subsystems.subhome.bukkit.{LocationCodec, TeleportEffect} import com.github.unchama.seichiassist.subsystems.subhome.domain.{SubHome, SubHomeId} -import com.github.unchama.seichiassist.subsystems.subhome.{SubHomeReadAPI, SubHomeWriteAPI} +import com.github.unchama.seichiassist.subsystems.subhome.{SubHomeAPI, SubHomeReadAPI, SubHomeWriteAPI} import com.github.unchama.targetedeffect.commandsender.MessageEffect import org.bukkit.ChatColor._ import org.bukkit.command.TabExecutor -import org.bukkit.{Bukkit, Location} object SubHomeCommand { + + import cats.implicits._ + private val printDescriptionExecutor = new EchoExecutor( MessageEffect( List( @@ -45,6 +47,20 @@ object SubHomeCommand { onMissingArguments = printDescriptionExecutor ) + def executor[ + F[_] + : SubHomeAPI + : ConcurrentEffect + : NonServerThreadContextShift + ](implicit scope: ChatInterceptionScope): TabExecutor = BranchedExecutor( + Map( + "warp" -> warpExecutor, + "set" -> setExecutor, + "name" -> nameExecutor + ), + whenArgInsufficient = Some(printDescriptionExecutor), whenBranchNotFound = Some(printDescriptionExecutor) + ).asNonBlockingTabExecutor() + private def warpExecutor[ F[_] : ConcurrentEffect @@ -62,9 +78,16 @@ object SubHomeCommand { subHomeLocation match { case None => MessageEffect(s"サブホームポイント${subHomeId}が設定されてません") case Some(SubHome(_, location)) => - // TODO これは副作用 - player.teleport(new Location(Bukkit.getWorld(location.worldName), location.x, location.y, location.z)) - MessageEffect(s"サブホームポイント${subHomeId}にワープしました") + LocationCodec.toBukkitLocation(location) match { + case Some(bukkitLocation) => + TeleportEffect.to[IO](bukkitLocation) >> + MessageEffect(s"サブホームポイント${subHomeId}にワープしました") + case None => + MessageEffect(List( + s"${RED}サブホームポイントへのワープに失敗しました", + s"${RED}登録先のワールドが削除された可能性があります" + )) + } } } @@ -84,10 +107,12 @@ object SubHomeCommand { val eff = for { _ <- NonServerThreadContextShift[F].shift - _ <- SubHomeWriteAPI[F].updateLocation(player.getUniqueId, subHomeId, player.getLocation) - } yield { - MessageEffect(s"現在位置をサブホームポイント${subHomeId}に設定しました") - } + _ <- SubHomeWriteAPI[F].upsertLocation( + player.getUniqueId, + subHomeId, + LocationCodec.fromBukkitLocation(player.getLocation) + ) + } yield MessageEffect(s"現在位置をサブホームポイント${subHomeId}に設定しました") eff.toIO } @@ -104,23 +129,19 @@ object SubHomeCommand { IO.pure { val sendInterceptionMessage = - MessageEffect( - List( - s"サブホームポイント${subHomeId}に設定する名前をチャットで入力してください", - s"$YELLOW※入力されたチャット内容は他のプレイヤーには見えません" - ) - ) + MessageEffect(List( + s"サブホームポイント${subHomeId}に設定する名前をチャットで入力してください", + s"$YELLOW※入力されたチャット内容は他のプレイヤーには見えません" + )) val sendCancellationMessage = MessageEffect(s"${YELLOW}入力がキャンセルされました。") def sendCompletionMessage(inputName: String) = - MessageEffect( - List( - s"${GREEN}サブホームポイント${subHomeId}の名前を", - s"$GREEN${inputName}に更新しました" - ) - ) + MessageEffect(List( + s"${GREEN}サブホームポイント${subHomeId}の名前を", + s"$GREEN${inputName}に更新しました" + )) import com.github.unchama.generic.syntax._ @@ -129,10 +150,7 @@ object SubHomeCommand { scope.interceptFrom(uuid).flatMap { case Left(newName) => - val eff = for { - _ <- SubHomeWriteAPI[F].updateName(uuid, subHomeId, newName) - } yield {} - eff.toIO *> + SubHomeWriteAPI[F].rename(uuid, subHomeId)(newName).toIO >> sendCompletionMessage(newName)(player) case Right(Overridden) => sendCancellationMessage(player) case Right(_) => IO.pure(()) @@ -141,19 +159,4 @@ object SubHomeCommand { } } .build() - - def executor[ - F[_] - : SubHomeReadAPI - : SubHomeWriteAPI - : ConcurrentEffect - : NonServerThreadContextShift - ](implicit scope: ChatInterceptionScope): TabExecutor = BranchedExecutor( - Map( - "warp" -> warpExecutor, - "set" -> setExecutor, - "name" -> nameExecutor - ), - whenArgInsufficient = Some(printDescriptionExecutor), whenBranchNotFound = Some(printDescriptionExecutor) - ).asNonBlockingTabExecutor() } \ No newline at end of file diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/domain/OperationResult.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/domain/OperationResult.scala new file mode 100644 index 0000000000..4877505065 --- /dev/null +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/domain/OperationResult.scala @@ -0,0 +1,9 @@ +package com.github.unchama.seichiassist.subsystems.subhome.domain + +object OperationResult { + sealed trait RenameResult + object RenameResult { + case object Done extends RenameResult + case object NotFound extends RenameResult + } +} diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/domain/SubHomePersistence.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/domain/SubHomePersistence.scala index 7bf9dc1127..dbc63d21c8 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/domain/SubHomePersistence.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/domain/SubHomePersistence.scala @@ -1,6 +1,7 @@ package com.github.unchama.seichiassist.subsystems.subhome.domain import cats.{Functor, Monad} +import com.github.unchama.seichiassist.subsystems.subhome.domain.OperationResult.RenameResult import java.util.UUID @@ -49,10 +50,10 @@ trait SubHomePersistence[F[_]] { /** * 指定されたサブホームをnon-atomicにリネームする。存在しないサブホームが指定された場合何も行わない。 - * - * 作用の結果として更新が行われたかどうかを示すBooleanを返す。 */ - final def rename(ownerUuid: UUID, id: SubHomeId)(newName: String)(implicit F: Monad[F]): F[Boolean] = - alter(ownerUuid, id)(_.copy(name = Some(newName))) + final def rename(ownerUuid: UUID, id: SubHomeId)(newName: String)(implicit F: Monad[F]): F[OperationResult.RenameResult] = + alter(ownerUuid, id)(_.copy(name = Some(newName))).map { r => + if (r) RenameResult.Done else RenameResult.NotFound + } } From e7217490b76b3727b190e2903730e2fed1589a78 Mon Sep 17 00:00:00 2001 From: Kory <6561358+kory33@users.noreply.github.com> Date: Mon, 2 Aug 2021 18:04:12 +0900 Subject: [PATCH 18/73] =?UTF-8?q?[fix]=20subhomeSystem=E3=81=8C=E7=B9=8B?= =?UTF-8?q?=E3=81=8C=E3=81=A3=E3=81=A6=E3=81=84=E3=81=AA=E3=81=84=E3=81=AE?= =?UTF-8?q?=E3=82=92=E4=BF=AE=E6=AD=A3=E3=81=99=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../unchama/seichiassist/SeichiAssist.scala | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/scala/com/github/unchama/seichiassist/SeichiAssist.scala b/src/main/scala/com/github/unchama/seichiassist/SeichiAssist.scala index c5fcf2d5b6..c894f13266 100644 --- a/src/main/scala/com/github/unchama/seichiassist/SeichiAssist.scala +++ b/src/main/scala/com/github/unchama/seichiassist/SeichiAssist.scala @@ -58,7 +58,6 @@ import com.github.unchama.seichiassist.subsystems.managedfly.ManagedFlyApi import com.github.unchama.seichiassist.subsystems.present.infrastructure.GlobalPlayerAccessor import com.github.unchama.seichiassist.subsystems.seasonalevents.api.SeasonalEventsAPI import com.github.unchama.seichiassist.subsystems.subhome.SubHomeReadAPI -import com.github.unchama.seichiassist.subsystems.subhome.bukkit.command.SubHomeCommand import com.github.unchama.seichiassist.task.PlayerDataSaveTask import com.github.unchama.seichiassist.task.global._ import com.github.unchama.util.{ActionStatus, ClassUtils} @@ -304,6 +303,14 @@ class SeichiAssist extends JavaPlugin() { subsystems.discordnotification.System.wired[IO](seichiAssistConfig.discordNotificationConfiguration) } + lazy val subhomeSystem: subhome.System[IO] = { + import PluginExecutionContexts.asyncShift + + implicit val effectEnvironment: EffectEnvironment = DefaultEffectEnvironment + implicit val concurrentEffect: ConcurrentEffect[IO] = IO.ioConcurrentEffect(asyncShift) + subhome.System.wired + } + private lazy val wiredSubsystems: List[Subsystem[IO]] = List( mebiusSystem, expBottleStackSystem, @@ -321,6 +328,7 @@ class SeichiAssist extends JavaPlugin() { fourDimensionalPocketSystem, gachaPointSystem, discordNotificationSystem, + subhomeSystem ) private lazy val buildAssist: BuildAssist = { @@ -371,14 +379,6 @@ class SeichiAssist extends JavaPlugin() { subsystems.present.System.wired } - lazy val subhomeSystem: subhome.System[IO] = { - import PluginExecutionContexts.{asyncShift, onMainThread} - - implicit val effectEnvironment: EffectEnvironment = DefaultEffectEnvironment - implicit val concurrentEffect: ConcurrentEffect[IO] = IO.ioConcurrentEffect(asyncShift) - subhome.System.wired - } - //endregion private implicit val _akkaSystem: ActorSystem = ConfiguredActorSystemProvider("reference.conf").provide() From 3c946d4463782f71f0be8f0acecb3da7df778789 Mon Sep 17 00:00:00 2001 From: Kory <6561358+kory33@users.noreply.github.com> Date: Mon, 2 Aug 2021 18:10:05 +0900 Subject: [PATCH 19/73] =?UTF-8?q?[fix]=20JdbcSubHomePersistence=E3=81=A7?= =?UTF-8?q?=E3=81=AEupsert=E3=82=92readOnly=E3=81=AB=E3=81=97=E3=81=AA?= =?UTF-8?q?=E3=81=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../subhome/infrastructure/JdbcSubHomePersistence.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/JdbcSubHomePersistence.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/JdbcSubHomePersistence.scala index f9289a9e7e..00aa194d2b 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/JdbcSubHomePersistence.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/JdbcSubHomePersistence.scala @@ -15,7 +15,7 @@ class JdbcSubHomePersistence[F[_]: Sync: NonServerThreadContextShift] extends Su override def upsert(ownerUuid: UUID, id: SubHomeId)(subHome: SubHome): F[Unit] = NonServerThreadContextShift[F].shift >> Sync[F].delay[Unit] { - DB.readOnly { implicit session => + DB.localTx { implicit session => val SubHomeLocation(worldName, x, y, z) = subHome.location // NOTE 2021/05/19: 何故かDB上のIDは1少ない。つまり、ID 1のサブホームはDB上ではid=0である。 From e2541a654952bf1add6f830cca95cdb7f46c574b Mon Sep 17 00:00:00 2001 From: Kory <6561358+kory33@users.noreply.github.com> Date: Mon, 2 Aug 2021 18:15:14 +0900 Subject: [PATCH 20/73] =?UTF-8?q?[fix]=20=E3=82=AF=E3=82=A8=E3=83=AA?= =?UTF-8?q?=E3=82=92stripMargin=E3=81=99=E3=82=8B=E3=82=88=E3=81=86?= =?UTF-8?q?=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../subhome/infrastructure/JdbcSubHomePersistence.scala | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/JdbcSubHomePersistence.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/JdbcSubHomePersistence.scala index 00aa194d2b..332b164871 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/JdbcSubHomePersistence.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/infrastructure/JdbcSubHomePersistence.scala @@ -28,6 +28,7 @@ class JdbcSubHomePersistence[F[_]: Sync: NonServerThreadContextShift] extends Su | location_y = values(location_y), | location_z = values(location_z), | world_name = values(world_name)""" + .stripMargin .update() .apply() } @@ -52,7 +53,9 @@ class JdbcSubHomePersistence[F[_]: Sync: NonServerThreadContextShift] extends Su ) ) ) - .list().apply() + .stripMargin + .list() + .apply() }.toMap } } From 2440f53e78fffd02b9ccb60aa229f530134d3588 Mon Sep 17 00:00:00 2001 From: Kory <6561358+kory33@users.noreply.github.com> Date: Mon, 2 Aug 2021 20:32:00 +0900 Subject: [PATCH 21/73] =?UTF-8?q?[update]=20=E3=83=9D=E3=82=A4=E3=83=B3?= =?UTF-8?q?=E3=83=88=E6=9C=AA=E8=A8=AD=E5=AE=9A=E3=81=AE=E6=99=82/subhome?= =?UTF-8?q?=20name=E3=81=8C=E3=82=A8=E3=83=A9=E3=83=BC=E3=82=92=E5=87=BA?= =?UTF-8?q?=E3=81=99=E3=82=88=E3=81=86=E3=81=AB=E3=81=99=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../subsystems/subhome/SubHomeAPI.scala | 4 + .../bukkit/command/SubHomeCommand.scala | 74 +++++++++++-------- 2 files changed, 46 insertions(+), 32 deletions(-) diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/SubHomeAPI.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/SubHomeAPI.scala index 36d6eab12d..089504bba3 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/SubHomeAPI.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/SubHomeAPI.scala @@ -1,5 +1,6 @@ package com.github.unchama.seichiassist.subsystems.subhome +import cats.Functor import com.github.unchama.seichiassist.subsystems.subhome.domain.{OperationResult, SubHome, SubHomeId, SubHomeLocation} import java.util.UUID @@ -10,6 +11,9 @@ trait SubHomeReadAPI[F[_]] { def get(ownerUuid: UUID, id: SubHomeId): F[Option[SubHome]] + final def configured(ownerUuid: UUID, id: SubHomeId)(implicit F: Functor[F]): F[Boolean] = + F.map(get(ownerUuid, id))(_.nonEmpty) + } object SubHomeReadAPI { diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/bukkit/command/SubHomeCommand.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/bukkit/command/SubHomeCommand.scala index 41a9ea323a..b5dd06e1ea 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/bukkit/command/SubHomeCommand.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/bukkit/command/SubHomeCommand.scala @@ -1,6 +1,6 @@ package com.github.unchama.seichiassist.subsystems.subhome.bukkit.command -import cats.data.Kleisli +import cats.Monad import cats.effect.implicits._ import cats.effect.{ConcurrentEffect, IO} import com.github.unchama.chatinterceptor.CancellationReason.Overridden @@ -11,8 +11,10 @@ import com.github.unchama.contextualexecutor.executors.{BranchedExecutor, EchoEx import com.github.unchama.seichiassist.SeichiAssist import com.github.unchama.seichiassist.commands.contextual.builder.BuilderTemplates.playerCommandBuilder import com.github.unchama.seichiassist.subsystems.subhome.bukkit.{LocationCodec, TeleportEffect} +import com.github.unchama.seichiassist.subsystems.subhome.domain.OperationResult.RenameResult import com.github.unchama.seichiassist.subsystems.subhome.domain.{SubHome, SubHomeId} import com.github.unchama.seichiassist.subsystems.subhome.{SubHomeAPI, SubHomeReadAPI, SubHomeWriteAPI} +import com.github.unchama.targetedeffect.TargetedEffect import com.github.unchama.targetedeffect.commandsender.MessageEffect import org.bukkit.ChatColor._ import org.bukkit.command.TabExecutor @@ -47,6 +49,10 @@ object SubHomeCommand { onMissingArguments = printDescriptionExecutor ) + private def subHomeNotSetMessage(id: SubHomeId): List[String] = List( + s"${YELLOW}指定されたサブホームポイントが設定されていません。" + ) + def executor[ F[_] : SubHomeAPI @@ -122,41 +128,45 @@ object SubHomeCommand { F[_] : ConcurrentEffect : NonServerThreadContextShift - : SubHomeWriteAPI + : SubHomeAPI ](implicit scope: ChatInterceptionScope) = argsAndSenderConfiguredBuilder .execution { context => val subHomeId = SubHomeId(context.args.parsed.head.asInstanceOf[Int]) - IO.pure { - val sendInterceptionMessage = - MessageEffect(List( - s"サブホームポイント${subHomeId}に設定する名前をチャットで入力してください", - s"$YELLOW※入力されたチャット内容は他のプレイヤーには見えません" - )) - - val sendCancellationMessage = - MessageEffect(s"${YELLOW}入力がキャンセルされました。") - - def sendCompletionMessage(inputName: String) = - MessageEffect(List( - s"${GREEN}サブホームポイント${subHomeId}の名前を", - s"$GREEN${inputName}に更新しました" - )) - - import com.github.unchama.generic.syntax._ - - sendInterceptionMessage.followedBy(Kleisli { player => - val uuid = player.getUniqueId - - scope.interceptFrom(uuid).flatMap { - case Left(newName) => - SubHomeWriteAPI[F].rename(uuid, subHomeId)(newName).toIO >> - sendCompletionMessage(newName)(player) - case Right(Overridden) => sendCancellationMessage(player) - case Right(_) => IO.pure(()) - } - }) - } + val player = context.sender + val uuid = player.getUniqueId + + val instruction = List( + s"サブホームポイント${subHomeId}に設定する名前をチャットで入力してください", + s"$YELLOW※入力されたチャット内容は他のプレイヤーには見えません" + ) + + def doneMessage(inputName: String) = List( + s"${GREEN}サブホームポイント${subHomeId}の名前を", + s"$GREEN${inputName}に更新しました" + ) + + val cancelledInputMessage = List( + s"${YELLOW}入力がキャンセルされました。" + ) + + for { + _ <- Monad[IO].ifM(SubHomeReadAPI[F].configured(uuid, subHomeId).toIO)( + MessageEffect(instruction)(player) >> + scope.interceptFrom(uuid).flatMap { + case Left(newName) => + SubHomeWriteAPI[F].rename(uuid, subHomeId)(newName).toIO.flatMap { + case RenameResult.Done => + MessageEffect(doneMessage(newName))(player) + case RenameResult.NotFound => + MessageEffect(subHomeNotSetMessage(subHomeId))(player) + } + case Right(Overridden) => MessageEffect(cancelledInputMessage)(player) + case Right(_) => IO.unit + }, + MessageEffect(subHomeNotSetMessage(subHomeId))(player) + ) + } yield TargetedEffect.emptyEffect } .build() } \ No newline at end of file From 808c74839f594a3baf9f50c62793ee33d5481782 Mon Sep 17 00:00:00 2001 From: Kory <6561358+kory33@users.noreply.github.com> Date: Mon, 2 Aug 2021 20:38:03 +0900 Subject: [PATCH 22/73] =?UTF-8?q?[fix]=20=E3=82=B5=E3=83=96=E3=83=9B?= =?UTF-8?q?=E3=83=BC=E3=83=A0=E3=81=AE=E5=90=8D=E5=89=8D=E3=81=8COption?= =?UTF-8?q?=E3=81=A8=E3=81=97=E3=81=A6=E8=A1=A8=E7=A4=BA=E3=81=95=E3=82=8C?= =?UTF-8?q?=E3=81=A6=E3=81=84=E3=81=9F=E3=81=AE=E3=82=92=E4=BF=AE=E6=AD=A3?= =?UTF-8?q?=E3=81=99=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../unchama/seichiassist/menus/HomeMenu.scala | 24 +++++++++++++++---- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/src/main/scala/com/github/unchama/seichiassist/menus/HomeMenu.scala b/src/main/scala/com/github/unchama/seichiassist/menus/HomeMenu.scala index a031f90482..73fbe13783 100644 --- a/src/main/scala/com/github/unchama/seichiassist/menus/HomeMenu.scala +++ b/src/main/scala/com/github/unchama/seichiassist/menus/HomeMenu.scala @@ -168,21 +168,35 @@ object HomeMenu extends Menu { } yield { val lore = subhomeOpt match { case None => List(s"${GRAY}サブホームポイント$subHomeId", s"${GRAY}ポイント未設定") - case Some(SubHome(name, location)) => + case Some(SubHome(optionName, location)) => val worldName = { ManagedWorld .fromName(location.worldName).map(_.japaneseName) .getOrElse(location.worldName) } - List( - s"${GRAY}サブホームポイント${subHomeId}は", - s"$GRAY$name", - s"${GRAY}と名付けられています", + val nameStatus = optionName match { + case Some(name) => List( + s"${GRAY}サブホームポイント${subHomeId}は", + s"$GRAY$name", + s"${GRAY}と名付けられています", + ) + case None => List( + s"${GRAY}サブホームポイント${subHomeId}は", + s"${GRAY}名前が未設定です", + ) + } + + val commandInfo = List( s"$DARK_RED${UNDERLINE}クリックで名称変更", s"${DARK_GRAY}command->[/subhome name $subHomeId]", + ) + + val coordinates = List( s"$GRAY$worldName x:${location.x} y:${location.y} z:${location.z}" ) + + nameStatus ++ commandInfo ++ coordinates } Button( From 27cbeeb4a33add4fe195738ea7d348dae9633ef3 Mon Sep 17 00:00:00 2001 From: Kory <6561358+kory33@users.noreply.github.com> Date: Mon, 2 Aug 2021 22:10:27 +0900 Subject: [PATCH 23/73] =?UTF-8?q?[fix]=20subhome=20set=E3=81=A7=E5=90=8D?= =?UTF-8?q?=E5=89=8D=E3=81=8C=E6=B6=88=E3=81=88=E3=81=AA=E3=81=84=E3=82=88?= =?UTF-8?q?=E3=81=86=E3=81=AB=E3=81=99=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../subsystems/subhome/SubHomeAPI.scala | 2 +- .../seichiassist/subsystems/subhome/System.scala | 4 ++-- .../subhome/bukkit/command/SubHomeCommand.scala | 8 +++----- .../subhome/domain/SubHomePersistence.scala | 13 +++++++++++++ 4 files changed, 19 insertions(+), 8 deletions(-) diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/SubHomeAPI.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/SubHomeAPI.scala index 089504bba3..ff4547d97e 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/SubHomeAPI.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/SubHomeAPI.scala @@ -24,7 +24,7 @@ object SubHomeReadAPI { trait SubHomeWriteAPI[F[_]] { - def upsertLocation(ownerUuid: UUID, id: SubHomeId, location: SubHomeLocation): F[Unit] + def upsertLocation(ownerUuid: UUID, id: SubHomeId)(location: SubHomeLocation): F[Unit] def rename(ownerUuid: UUID, id: SubHomeId)(name: String): F[OperationResult.RenameResult] diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/System.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/System.scala index 752880de03..c44dadd21e 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/System.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/System.scala @@ -26,8 +26,8 @@ object System { new System[F] { override implicit val api: SubHomeAPI[F] = new SubHomeAPI[F] { - override def upsertLocation(ownerUuid: UUID, id: SubHomeId, location: SubHomeLocation): F[Unit] = - persistence.upsert(ownerUuid, id)(SubHome(None, location)) + override def upsertLocation(ownerUuid: UUID, id: SubHomeId)(location: SubHomeLocation): F[Unit] = + persistence.upsertLocation(ownerUuid, id)(location) override def rename(ownerUuid: UUID, id: SubHomeId)(name: String): F[RenameResult] = persistence.rename(ownerUuid, id)(name) override def get(ownerUuid: UUID, id: SubHomeId): F[Option[SubHome]] = diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/bukkit/command/SubHomeCommand.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/bukkit/command/SubHomeCommand.scala index b5dd06e1ea..eaa25d45f7 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/bukkit/command/SubHomeCommand.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/bukkit/command/SubHomeCommand.scala @@ -111,13 +111,11 @@ object SubHomeCommand { val subHomeId = SubHomeId(context.args.parsed.head.asInstanceOf[Int]) val player = context.sender + val subHomeLocation = LocationCodec.fromBukkitLocation(player.getLocation) + val eff = for { _ <- NonServerThreadContextShift[F].shift - _ <- SubHomeWriteAPI[F].upsertLocation( - player.getUniqueId, - subHomeId, - LocationCodec.fromBukkitLocation(player.getLocation) - ) + _ <- SubHomeWriteAPI[F].upsertLocation(player.getUniqueId, subHomeId)(subHomeLocation) } yield MessageEffect(s"現在位置をサブホームポイント${subHomeId}に設定しました") eff.toIO diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/domain/SubHomePersistence.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/domain/SubHomePersistence.scala index dbc63d21c8..6fe9150e75 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/domain/SubHomePersistence.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/subhome/domain/SubHomePersistence.scala @@ -34,6 +34,19 @@ trait SubHomePersistence[F[_]] { final def get(ownerUuid: UUID, id: SubHomeId)(implicit F: Functor[F]): F[Option[SubHome]] = list(ownerUuid).map(_.get(id)) + /** + * 指定されたidのサブホームを登録する。idの範囲などのバリデーションはしない。 + * + * サブホームがすでに存在した場合、古いサブホームの名前を新しいサブホームへと引き継ぐ。 + */ + final def upsertLocation(ownerUuid: UUID, id: SubHomeId)(location: SubHomeLocation) + (implicit F: Monad[F]): F[Unit] = + for { + old <- get(ownerUuid, id) + newSubHome = SubHome(old.flatMap(_.name), location) + _ <- upsert(ownerUuid, id)(newSubHome) + } yield () + /** * 指定されたサブホームをnon-atomicに更新する。存在しないサブホームが指定された場合何も行わない。 * From e43641bbf3063b096801d74b0c7d87e0ec7099d9 Mon Sep 17 00:00:00 2001 From: Kory <6561358+kory33@users.noreply.github.com> Date: Mon, 2 Aug 2021 22:15:08 +0900 Subject: [PATCH 24/73] =?UTF-8?q?[fix]=20presentSystem=E3=81=8CwiredSubsys?= =?UTF-8?q?tem=E3=81=AB=E5=85=A5=E3=81=A3=E3=81=A6=E3=81=84=E3=81=AA?= =?UTF-8?q?=E3=81=84=E3=81=AE=E3=82=92=E4=BF=AE=E6=AD=A3=E3=81=99=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../unchama/seichiassist/SeichiAssist.scala | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/main/scala/com/github/unchama/seichiassist/SeichiAssist.scala b/src/main/scala/com/github/unchama/seichiassist/SeichiAssist.scala index c894f13266..b06043e8d1 100644 --- a/src/main/scala/com/github/unchama/seichiassist/SeichiAssist.scala +++ b/src/main/scala/com/github/unchama/seichiassist/SeichiAssist.scala @@ -311,6 +311,15 @@ class SeichiAssist extends JavaPlugin() { subhome.System.wired } + lazy val presentSystem: Subsystem[IO] = { + import PluginExecutionContexts.{asyncShift, onMainThread} + + implicit val effectEnvironment: EffectEnvironment = DefaultEffectEnvironment + implicit val concurrentEffect: ConcurrentEffect[IO] = IO.ioConcurrentEffect(asyncShift) + implicit val uuidToLastSeenName: UuidToLastSeenName[IO] = new GlobalPlayerAccessor[IO] + subsystems.present.System.wired + } + private lazy val wiredSubsystems: List[Subsystem[IO]] = List( mebiusSystem, expBottleStackSystem, @@ -328,7 +337,8 @@ class SeichiAssist extends JavaPlugin() { fourDimensionalPocketSystem, gachaPointSystem, discordNotificationSystem, - subhomeSystem + subhomeSystem, + presentSystem ) private lazy val buildAssist: BuildAssist = { @@ -370,15 +380,6 @@ class SeichiAssist extends JavaPlugin() { ) } - lazy val presentSystem: Subsystem[IO] = { - import PluginExecutionContexts.{asyncShift, onMainThread} - - implicit val effectEnvironment: EffectEnvironment = DefaultEffectEnvironment - implicit val concurrentEffect: ConcurrentEffect[IO] = IO.ioConcurrentEffect(asyncShift) - implicit val uuidToLastSeenName: UuidToLastSeenName[IO] = new GlobalPlayerAccessor[IO] - subsystems.present.System.wired - } - //endregion private implicit val _akkaSystem: ActorSystem = ConfiguredActorSystemProvider("reference.conf").provide() From c94ab8cef1270d09eb73405d70746e2c38152e85 Mon Sep 17 00:00:00 2001 From: Kory <6561358+kory33@users.noreply.github.com> Date: Mon, 2 Aug 2021 22:25:38 +0900 Subject: [PATCH 25/73] [fix] fix #1049 --- .../bukkit/GiftItemInterpreter.scala | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/seichilevelupgift/bukkit/GiftItemInterpreter.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/seichilevelupgift/bukkit/GiftItemInterpreter.scala index 329a521e7d..682d21ed36 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/seichilevelupgift/bukkit/GiftItemInterpreter.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/seichilevelupgift/bukkit/GiftItemInterpreter.scala @@ -1,18 +1,14 @@ package com.github.unchama.seichiassist.subsystems.seichilevelupgift.bukkit import cats.data.Kleisli -import cats.effect.{IO, LiftIO, Sync, SyncIO} -import cats.kernel.Monoid -import com.github.unchama.seichiassist.SeichiAssist +import cats.effect.Sync import com.github.unchama.minecraft.actions.OnMinecraftServerThread -import com.github.unchama.seichiassist.concurrent.PluginExecutionContexts.onMainThread import com.github.unchama.seichiassist.data.{GachaSkullData, ItemData} import com.github.unchama.seichiassist.subsystems.seichilevelupgift.domain.Gift import com.github.unchama.seichiassist.subsystems.seichilevelupgift.domain.Gift.Item import com.github.unchama.seichiassist.util.Util.grantItemStacksEffect -import com.github.unchama.targetedeffect.{SequentialEffect, TargetedEffect} -import com.github.unchama.targetedeffect.commandsender.{MessageEffect, MessageEffectF} -import org.bukkit.command.CommandSender +import com.github.unchama.targetedeffect.SequentialEffect +import com.github.unchama.targetedeffect.commandsender.MessageEffectF import org.bukkit.entity.Player /** @@ -28,11 +24,9 @@ class GiftItemInterpreter[F[_] : OnMinecraftServerThread : Sync] extends (Gift.I case Item.Elsa => ItemData.getElsa(1) } - import cats.implicits._ - import cats.effect.implicits._ SequentialEffect( MessageEffectF[F]("レベルアップ記念のアイテムを配布しました。"), - grantItemStacksEffect[F]() + grantItemStacksEffect[F](itemStack) ) } From 638852c870b6d8e84c15fb4efc3f92c9060f06fe Mon Sep 17 00:00:00 2001 From: Kory <6561358+kory33@users.noreply.github.com> Date: Mon, 2 Aug 2021 22:42:23 +0900 Subject: [PATCH 26/73] [fix] fix #1105 --- .../seichiassist/subsystems/breakcountbar/System.scala | 6 ++---- .../ExpBarSynchronizationRepositoryTemplate.scala | 10 ++++++---- .../seichiassist/subsystems/manabar/System.scala | 2 +- .../application/ManaBarSynchronizationRepository.scala | 10 ++++++---- 4 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/breakcountbar/System.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/breakcountbar/System.scala index 0cd44c3496..ed011dd155 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/breakcountbar/System.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/breakcountbar/System.scala @@ -57,10 +57,8 @@ object System { ContextCoercion { BukkitRepositoryControls.createHandles( RepositoryDefinition.Phased.TwoPhased( - ExpBarSynchronizationRepositoryTemplate.initialization[G, F, Player]( - breakCountReadAPI.seichiAmountUpdates, - visibilityValues - )(CreateFreshBossBar.in[G, F]), + ExpBarSynchronizationRepositoryTemplate + .initialization[G, F, Player](breakCountReadAPI, visibilityValues)(CreateFreshBossBar.in[G, F]), ExpBarSynchronizationRepositoryTemplate.finalization[G, F, Player] ) ) diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/breakcountbar/application/ExpBarSynchronizationRepositoryTemplate.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/breakcountbar/application/ExpBarSynchronizationRepositoryTemplate.scala index fe26524515..bafa03ef2f 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/breakcountbar/application/ExpBarSynchronizationRepositoryTemplate.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/breakcountbar/application/ExpBarSynchronizationRepositoryTemplate.scala @@ -9,7 +9,7 @@ import com.github.unchama.generic.effect.EffectExtra import com.github.unchama.generic.effect.stream.StreamExtra import com.github.unchama.minecraft.algebra.HasUuid import com.github.unchama.minecraft.objects.MinecraftBossBar -import com.github.unchama.seichiassist.subsystems.breakcount.domain.SeichiAmountData +import com.github.unchama.seichiassist.subsystems.breakcount.BreakCountReadAPI import com.github.unchama.seichiassist.subsystems.breakcountbar.domain.BreakCountBarVisibility import io.chrisdavenport.log4cats.ErrorLogger @@ -38,7 +38,7 @@ object ExpBarSynchronizationRepositoryTemplate { G[_] : Sync, F[_] : ConcurrentEffect : ContextCoercion[G, *[_]] : ErrorLogger, Player: HasUuid, - ](breakCountValues: fs2.Stream[F, (Player, SeichiAmountData)], + ](breakCountReadAPI: BreakCountReadAPI[F, G, Player], visibilityValues: fs2.Stream[F, (Player, BreakCountBarVisibility)]) (createFreshBossBar: G[BossBarWithPlayer[F, Player]]) : TwoPhasedRepositoryInitialization[G, Player, RepositoryValueType[F, Player]] = @@ -46,8 +46,10 @@ object ExpBarSynchronizationRepositoryTemplate { for { bossBar <- createFreshBossBar - synchronization = breakCountValues - .through(StreamExtra.valuesWithKeyOfSameUuidAs(player)) + synchronization = fs2.Stream + .eval(breakCountReadAPI.seichiAmountDataRepository(player).read) + .translate(ContextCoercion.asFunctionK[G, F]) + .append(breakCountReadAPI.seichiAmountUpdates.through(StreamExtra.valuesWithKeyOfSameUuidAs(player))) .evalTap(BreakCountBarManipulation.write(_, bossBar)) switching = visibilityValues diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/manabar/System.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/manabar/System.scala index e8f755a588..afbfecd0cb 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/manabar/System.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/manabar/System.scala @@ -20,7 +20,7 @@ object System { import com.github.unchama.minecraft.bukkit.algebra.BukkitPlayerHasUuid.instance val definition = - ManaBarSynchronizationRepository.withContext(manaApi.manaAmountUpdates)(CreateFreshBossBar.in[G, F]) + ManaBarSynchronizationRepository.withContext(manaApi)(CreateFreshBossBar.in[G, F]) BukkitRepositoryControls.createHandles(definition).map { control => new Subsystem[F] { diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/manabar/application/ManaBarSynchronizationRepository.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/manabar/application/ManaBarSynchronizationRepository.scala index 340532d425..a0650b8e0d 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/manabar/application/ManaBarSynchronizationRepository.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/manabar/application/ManaBarSynchronizationRepository.scala @@ -8,7 +8,7 @@ import com.github.unchama.generic.effect.EffectExtra import com.github.unchama.generic.effect.stream.StreamExtra import com.github.unchama.minecraft.algebra.HasUuid import com.github.unchama.minecraft.objects.MinecraftBossBar -import com.github.unchama.seichiassist.subsystems.mana.domain.LevelCappedManaAmount +import com.github.unchama.seichiassist.subsystems.mana.ManaReadApi import io.chrisdavenport.log4cats.ErrorLogger object ManaBarSynchronizationRepository { @@ -21,7 +21,7 @@ object ManaBarSynchronizationRepository { G[_] : Sync, F[_] : ConcurrentEffect : ContextCoercion[G, *[_]] : ErrorLogger, Player: HasUuid - ](manaValues: fs2.Stream[F, (Player, LevelCappedManaAmount)]) + ](manaApi: ManaReadApi[F, G, Player]) (createFreshBossBar: G[BossBarWithPlayer[F, Player]]): RepositoryDefinition[G, Player, _] = { FiberAdjoinedRepositoryDefinition.extending { RepositoryDefinition.Phased.SinglePhased @@ -30,8 +30,10 @@ object ManaBarSynchronizationRepository { val (bossBar, promise) = pair val synchronization = - manaValues - .through(StreamExtra.valuesWithKeyOfSameUuidAs(player)) + fs2.Stream + .eval(manaApi.readManaAmount(player)) + .translate(ContextCoercion.asFunctionK[G, F]) + .append(manaApi.manaAmountUpdates.through(StreamExtra.valuesWithKeyOfSameUuidAs(player))) .evalTap(ManaBarManipulation.write[F](_, bossBar)) val programToRunAsync = From 9295260347677127b595aacff3d2e091e141efd3 Mon Sep 17 00:00:00 2001 From: Kory <6561358+kory33@users.noreply.github.com> Date: Mon, 2 Aug 2021 23:10:44 +0900 Subject: [PATCH 27/73] =?UTF-8?q?[clean]=20interpolation=E3=82=92=E9=81=BF?= =?UTF-8?q?=E3=81=91=E3=82=8B=E3=81=9F=E3=82=81=E3=81=AB=E3=82=82=E3=83=86?= =?UTF-8?q?=E3=83=BC=E3=83=96=E3=83=AB=E5=90=8D=E3=81=AA=E3=81=A9=E3=82=92?= =?UTF-8?q?=E3=83=8F=E3=83=BC=E3=83=89=E3=82=B3=E3=83=BC=E3=83=89=E3=81=99?= =?UTF-8?q?=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../JdbcBackedPresentPersistence.scala | 54 +++++++++---------- 1 file changed, 24 insertions(+), 30 deletions(-) diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/infrastructure/JdbcBackedPresentPersistence.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/infrastructure/JdbcBackedPresentPersistence.scala index a52c54ae78..a21a08c60f 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/infrastructure/JdbcBackedPresentPersistence.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/infrastructure/JdbcBackedPresentPersistence.scala @@ -2,9 +2,9 @@ package com.github.unchama.seichiassist.subsystems.present.infrastructure import cats.effect.Sync import com.github.unchama.seichiassist.subsystems.present.domain.PresentClaimingState -import eu.timepit.refined.numeric.{NonNegative, Positive} import eu.timepit.refined.api.Refined import eu.timepit.refined.auto._ +import eu.timepit.refined.numeric.Positive import org.bukkit.inventory.ItemStack import scalikejdbc._ @@ -15,25 +15,20 @@ import java.util.UUID */ class JdbcBackedPresentPersistence[F[_] : Sync] extends PresentPersistence[F] { override type PresentID = Int - private final val definitionTable = "present" - private final val stateTable = "present_state" - private final val claimingStateColumn = "claimed" - private final val presentIdColumn = "present_id" - private final val itemStackColumn = "itemstack" override def define(itemstack: ItemStack): F[PresentID] = Sync[F].delay { val stackAsBlob = ItemStackBlobProxy.itemStackToBlob(itemstack) DB.localTx { implicit session => // プレゼントのIDはauto_incrementなので明示的に指定しなくて良い - sql"""INSERT INTO $definitionTable ($itemStackColumn) VALUES ($stackAsBlob)""" + sql"""INSERT INTO present (itemstack) VALUES ($stackAsBlob)""" .execute() .apply() val newPresentID = DB.readOnly { implicit session => // ここで、itemstackは同じItemStackであるプレゼントが複数存在させたいケースを考慮して、UNIQUEではない。 // 他方、present_idは主キーであり、AUTO_INCREMENTであることから単調増加なので、単純にMAXを取れば良い。 - sql"""SELECT MAX($presentIdColumn) FROM $definitionTable WHERE $itemStackColumn = $stackAsBlob""" - .map { rs => rs.int(presentIdColumn) } + sql"""SELECT MAX(present_id) FROM present WHERE itemstack = $stackAsBlob""" + .map { rs => rs.int("present_id") } .first() .apply() // 上でINSERTしてるんだから、必ず見つかるはず @@ -51,12 +46,12 @@ class JdbcBackedPresentPersistence[F[_] : Sync] extends PresentPersistence[F] { */ override def delete(presentId: PresentID): F[Unit] = Sync[F].delay { DB.localTx { implicit session => - // 制約をかけているので$stateTableの方から先に消さないと整合性エラーを吐く - sql"""DELETE $stateTable WHERE $presentIdColumn = $presentId""" + // 制約をかけているのでpresent_stateの方から先に消さないと整合性エラーを吐く + sql"""DELETE FROM present_state WHERE present_id = $presentId""" .execute() .apply() - sql"""DELETE $definitionTable WHERE $presentIdColumn = $presentId""" + sql"""DELETE FROM present WHERE present_id = $presentId""" .execute() .apply() } @@ -70,7 +65,7 @@ class JdbcBackedPresentPersistence[F[_] : Sync] extends PresentPersistence[F] { .toSeq DB.localTx { implicit session => - sql"""INSERT INTO $stateTable VALUES (?, ?, ?)""" + sql"""INSERT INTO present_state VALUES (?, ?, ?)""" .batch(initialValues: _*) .apply() } @@ -81,7 +76,7 @@ class JdbcBackedPresentPersistence[F[_] : Sync] extends PresentPersistence[F] { DB.localTx { implicit session => // https://discord.com/channels/237758724121427969/565935041574731807/824107651985834004 - sql"""DELETE FROM $stateTable WHERE $presentIdColumn = $presentID AND uuid IN ($scopeAsSQL)""" + sql"""DELETE FROM present_state WHERE present_id = $presentID AND uuid IN ($scopeAsSQL)""" .execute() .apply() } @@ -89,7 +84,7 @@ class JdbcBackedPresentPersistence[F[_] : Sync] extends PresentPersistence[F] { override def markAsClaimed(presentId: PresentID, player: UUID): F[Unit] = Sync[F].delay { DB.localTx { implicit session => - sql"""UPDATE $stateTable SET $claimingStateColumn = TRUE WHERE uuid = ${player.toString} AND $presentIdColumn = $presentId""" + sql"""UPDATE present_state SET claimed = TRUE WHERE uuid = ${player.toString} AND present_id = $presentId""" .update() .apply() } @@ -97,10 +92,10 @@ class JdbcBackedPresentPersistence[F[_] : Sync] extends PresentPersistence[F] { override def mapping: F[Map[PresentID, ItemStack]] = Sync[F].delay { DB.readOnly { implicit session => - sql"""SELECT $presentIdColumn, $itemStackColumn FROM $definitionTable""" + sql"""SELECT present_id, itemstack FROM present""" .map { rs => ( - rs.int(presentIdColumn), + rs.int("present_id"), unwrapItemStack(rs) ) } @@ -118,10 +113,11 @@ class JdbcBackedPresentPersistence[F[_] : Sync] extends PresentPersistence[F] { // ページネーションはIDを列挙するときにすでに完了している val associatedEntries = DB.readOnly { implicit session => sql""" - SELECT $presentIdColumn, $claimingStateColumn - FROM $stateTable - WHERE uuid = ${player.toString} AND $presentIdColumn IN ($idSliceWithPagination) -""" + |SELECT present_id, claimed + |FROM present_state + |WHERE uuid = ${player.toString} AND present_id IN ($idSliceWithPagination) + """ + .stripMargin .map(wrapResultForState) .toList() .apply() @@ -139,7 +135,7 @@ class JdbcBackedPresentPersistence[F[_] : Sync] extends PresentPersistence[F] { validPresentIDs = validPresentMapping.keys } yield { val associatedEntries = DB.readOnly { implicit session => - sql"""SELECT $presentIdColumn, $claimingStateColumn FROM $stateTable WHERE uuid = ${player.toString}""" + sql"""SELECT present_id, claimed FROM present_state WHERE uuid = ${player.toString}""" .map(wrapResultForState) .list() .apply() @@ -152,7 +148,7 @@ class JdbcBackedPresentPersistence[F[_] : Sync] extends PresentPersistence[F] { override def lookup(presentID: PresentID): F[Option[ItemStack]] = Sync[F].delay { DB.readOnly { implicit session => - sql"""SELECT $itemStackColumn FROM $definitionTable WHERE $presentIdColumn = $presentID""" + sql"""SELECT itemstack FROM present WHERE present_id = $presentID""" .map(unwrapItemStack) .first() .apply() @@ -163,10 +159,8 @@ class JdbcBackedPresentPersistence[F[_] : Sync] extends PresentPersistence[F] { Sync[F].delay { val offset = (page - 1) * perPage DB.readOnly { implicit session => - sql"""SELECT $presentIdColumn ORDER BY $presentIdColumn LIMIT $perPage OFFSET $offset""" - .map { rs => - rs.int(presentIdColumn) - } + sql"""SELECT present_id FROM present ORDER BY present_id LIMIT $perPage OFFSET $offset""" + .map { _.int("present_id") } .toList() .apply() .toSet @@ -174,16 +168,16 @@ class JdbcBackedPresentPersistence[F[_] : Sync] extends PresentPersistence[F] { } private def wrapResultForState(rs: WrappedResultSet): (Int, PresentClaimingState) = { - val claimState = if (rs.boolean(claimingStateColumn)) + val claimState = if (rs.boolean("claimed")) PresentClaimingState.Claimed else PresentClaimingState.NotClaimed - (rs.int(presentIdColumn), claimState) + (rs.int("present_id"), claimState) } private def unwrapItemStack(rs: WrappedResultSet): ItemStack = { - ItemStackBlobProxy.blobToItemStack(rs.string(itemStackColumn)) + ItemStackBlobProxy.blobToItemStack(rs.string("itemstack")) } private def filledEntries(knownState: Map[PresentID, PresentClaimingState], validGlobalId: Iterable[PresentID]) = { From d8bbe0552ce866c9d1b06c9924d93a16e29a7dc3 Mon Sep 17 00:00:00 2001 From: Kory <6561358+kory33@users.noreply.github.com> Date: Tue, 3 Aug 2021 07:54:23 +0900 Subject: [PATCH 28/73] =?UTF-8?q?[update]=20=E7=94=9F=E6=88=90=E3=81=95?= =?UTF-8?q?=E3=82=8C=E3=81=9F=E3=82=AD=E3=83=BC=E3=82=92updateAndReturnGen?= =?UTF-8?q?eratedKey=E3=81=A7=E6=8C=81=E3=81=A3=E3=81=A6=E3=81=8F=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../db/migration/V1.7.2__Widen_present_id.sql | 23 ++++++++++++++ .../PresentPersistence.scala | 17 +++++----- .../JdbcBackedPresentPersistence.scala | 31 +++++-------------- 3 files changed, 39 insertions(+), 32 deletions(-) create mode 100644 src/main/resources/db/migration/V1.7.2__Widen_present_id.sql rename src/main/scala/com/github/unchama/seichiassist/subsystems/present/{infrastructure => domain}/PresentPersistence.scala (91%) diff --git a/src/main/resources/db/migration/V1.7.2__Widen_present_id.sql b/src/main/resources/db/migration/V1.7.2__Widen_present_id.sql new file mode 100644 index 0000000000..979469faf2 --- /dev/null +++ b/src/main/resources/db/migration/V1.7.2__Widen_present_id.sql @@ -0,0 +1,23 @@ +use seichiassist; + +-- このマイグレーションが走る時点ではpresentシステムが正常に動作しておらず、 +-- データが入っていないため問題なし +-- foreign key制約によってalter table出来なかったため作り直している +DROP TABLE present_state; +DROP TABLE present; + +-- プレゼントIDと実体の対応付け +CREATE TABLE IF NOT EXISTS present( + present_id bigint PRIMARY KEY auto_increment, + itemstack blob NOT NULL +); + +-- プレイヤーがプレゼントを受け取ったかどうかをモデリングする +CREATE TABLE IF NOT EXISTS present_state( + present_id bigint NOT NULL, + uuid char(36) NOT NULL, + claimed boolean NOT NULL, + + PRIMARY KEY(present_id, uuid), + FOREIGN KEY present_id_in_present_state_must_exist_in_presents_table(present_id) REFERENCES present(present_id) +); diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/infrastructure/PresentPersistence.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/domain/PresentPersistence.scala similarity index 91% rename from src/main/scala/com/github/unchama/seichiassist/subsystems/present/infrastructure/PresentPersistence.scala rename to src/main/scala/com/github/unchama/seichiassist/subsystems/present/domain/PresentPersistence.scala index ee61c688ca..beb0a1edea 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/infrastructure/PresentPersistence.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/domain/PresentPersistence.scala @@ -1,9 +1,7 @@ -package com.github.unchama.seichiassist.subsystems.present.infrastructure +package com.github.unchama.seichiassist.subsystems.present.domain -import com.github.unchama.seichiassist.subsystems.present.domain.PresentClaimingState import eu.timepit.refined.api.Refined import eu.timepit.refined.numeric.Positive -import org.bukkit.inventory.ItemStack import java.util.UUID @@ -13,8 +11,8 @@ import java.util.UUID * - 引数で渡される`PresentID`は対応するプレゼントが存在し、一意でなければならない * - 返り値としての`PresentID`は対応するプレゼントが存在する */ -trait PresentPersistence[F[_]] { - type PresentID +trait PresentPersistence[F[_], ItemStack] { + type PresentID = Long /** * 指定した[[ItemStack]]に対応するプレゼントを新しく定義する。 @@ -26,6 +24,7 @@ trait PresentPersistence[F[_]] { /** * 指定したPresentIDに対応するプレゼントを消去する。 + * * @param presentID プレゼントID */ def delete(presentID: PresentID): F[Unit] @@ -51,7 +50,7 @@ trait PresentPersistence[F[_]] { /** * 永続化層でプレゼントを受け取ったことにする。 * - * @param player プレイヤーのUUID + * @param player プレイヤーのUUID * @param presentID プレゼントID * @return 永続化層への書き込みを行う作用 */ @@ -77,15 +76,15 @@ trait PresentPersistence[F[_]] { * * この時 `pp.mappingWithPagination(A, 1, 5)` を呼び出すと、作用の中で計算される結果は次のとおりになる: * - * `Map(1 -> Claimed, 2 -> Claimed, 3 -> Claimed, 4 -> NotClaimed, 5 -> Unavailable)` + * `Map(1 -> Claimed, 2 -> Claimed, 3 -> Claimed, 4 -> NotClaimed, 5 -> Unavailable)` * * 備考: * - 実装によっては、[[fetchState]]などを呼び出して既知のエントリを全列挙する可能性がある。 * - このメソッドは一貫性のために[[fetchState]]のドキュメントにある制約を継承する。 * - * @param player 調べる対象のプレイヤー + * @param player 調べる対象のプレイヤー * @param perPage ページごとのエントリの数 - * @param page ページ、1オリジン + * @param page ページ、1オリジン * @return ページネーションを計算して返す作用 */ def fetchStateWithPagination(player: UUID, perPage: Int Refined Positive, page: Int Refined Positive): F[Map[PresentID, PresentClaimingState]] diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/infrastructure/JdbcBackedPresentPersistence.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/infrastructure/JdbcBackedPresentPersistence.scala index a21a08c60f..5613f763d3 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/infrastructure/JdbcBackedPresentPersistence.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/infrastructure/JdbcBackedPresentPersistence.scala @@ -1,7 +1,7 @@ package com.github.unchama.seichiassist.subsystems.present.infrastructure import cats.effect.Sync -import com.github.unchama.seichiassist.subsystems.present.domain.PresentClaimingState +import com.github.unchama.seichiassist.subsystems.present.domain.{PresentClaimingState, PresentPersistence} import eu.timepit.refined.api.Refined import eu.timepit.refined.auto._ import eu.timepit.refined.numeric.Positive @@ -13,31 +13,16 @@ import java.util.UUID /** * [[PresentPersistence]]のJDBC実装。この実装は[[PresentPersistence]]の制約を引き継ぐ。 */ -class JdbcBackedPresentPersistence[F[_] : Sync] extends PresentPersistence[F] { - override type PresentID = Int - +class JdbcBackedPresentPersistence[F[_] : Sync] extends PresentPersistence[F, ItemStack] { override def define(itemstack: ItemStack): F[PresentID] = Sync[F].delay { val stackAsBlob = ItemStackBlobProxy.itemStackToBlob(itemstack) DB.localTx { implicit session => // プレゼントのIDはauto_incrementなので明示的に指定しなくて良い sql"""INSERT INTO present (itemstack) VALUES ($stackAsBlob)""" - .execute() + .updateAndReturnGeneratedKey("present_id") .apply() - - val newPresentID = DB.readOnly { implicit session => - // ここで、itemstackは同じItemStackであるプレゼントが複数存在させたいケースを考慮して、UNIQUEではない。 - // 他方、present_idは主キーであり、AUTO_INCREMENTであることから単調増加なので、単純にMAXを取れば良い。 - sql"""SELECT MAX(present_id) FROM present WHERE itemstack = $stackAsBlob""" - .map { rs => rs.int("present_id") } - .first() - .apply() - // 上でINSERTしてるんだから、必ず見つかるはず - .get } - - newPresentID } - } /** * 指定したPresentIDに対応するプレゼントを物理消去する。 @@ -95,7 +80,7 @@ class JdbcBackedPresentPersistence[F[_] : Sync] extends PresentPersistence[F] { sql"""SELECT present_id, itemstack FROM present""" .map { rs => ( - rs.int("present_id"), + rs.long("present_id"), unwrapItemStack(rs) ) } @@ -105,7 +90,7 @@ class JdbcBackedPresentPersistence[F[_] : Sync] extends PresentPersistence[F] { } } - override def fetchStateWithPagination(player: UUID, perPage: Int Refined Positive, page: Int Refined Positive): F[Map[Int, PresentClaimingState]] = { + override def fetchStateWithPagination(player: UUID, perPage: Int Refined Positive, page: Int Refined Positive): F[Map[PresentID, PresentClaimingState]] = { import cats.implicits._ for { idSliceWithPagination <- idSliceWithPagination(perPage, page) @@ -160,20 +145,20 @@ class JdbcBackedPresentPersistence[F[_] : Sync] extends PresentPersistence[F] { val offset = (page - 1) * perPage DB.readOnly { implicit session => sql"""SELECT present_id FROM present ORDER BY present_id LIMIT $perPage OFFSET $offset""" - .map { _.int("present_id") } + .map { _.long("present_id") } .toList() .apply() .toSet } } - private def wrapResultForState(rs: WrappedResultSet): (Int, PresentClaimingState) = { + private def wrapResultForState(rs: WrappedResultSet): (Long, PresentClaimingState) = { val claimState = if (rs.boolean("claimed")) PresentClaimingState.Claimed else PresentClaimingState.NotClaimed - (rs.int("present_id"), claimState) + (rs.long("present_id"), claimState) } private def unwrapItemStack(rs: WrappedResultSet): ItemStack = { From b205f4cc903c940a154a960994953caf91bcca62 Mon Sep 17 00:00:00 2001 From: Kory <6561358+kory33@users.noreply.github.com> Date: Tue, 3 Aug 2021 07:54:56 +0900 Subject: [PATCH 29/73] =?UTF-8?q?[clean]=20PresentCommand=E3=81=8C?= =?UTF-8?q?=E5=AE=9F=E8=A3=85=E3=81=A7=E3=81=AA=E3=81=8Finterface=E3=81=AB?= =?UTF-8?q?=E4=BE=9D=E5=AD=98=E3=81=99=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bukkit/command/PresentCommand.scala | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/bukkit/command/PresentCommand.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/bukkit/command/PresentCommand.scala index e24596dab2..e9b5b0a388 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/bukkit/command/PresentCommand.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/bukkit/command/PresentCommand.scala @@ -11,8 +11,7 @@ import com.github.unchama.contextualexecutor.executors.{BranchedExecutor, EchoEx import com.github.unchama.minecraft.actions.OnMinecraftServerThread import com.github.unchama.seichiassist.commands.contextual.builder.BuilderTemplates.playerCommandBuilder import com.github.unchama.seichiassist.domain.actions.UuidToLastSeenName -import com.github.unchama.seichiassist.subsystems.present.domain.PresentClaimingState -import com.github.unchama.seichiassist.subsystems.present.infrastructure.JdbcBackedPresentPersistence +import com.github.unchama.seichiassist.subsystems.present.domain.{PresentClaimingState, PresentPersistence} import com.github.unchama.seichiassist.util.Util import com.github.unchama.targetedeffect.commandsender.MessageEffect import com.github.unchama.targetedeffect.{SequentialEffect, TargetedEffect} @@ -22,6 +21,7 @@ import eu.timepit.refined.auto._ import eu.timepit.refined.numeric.Positive import org.bukkit.command.TabExecutor import org.bukkit.entity.Player +import org.bukkit.inventory.ItemStack import org.bukkit.{ChatColor, Material} /** @@ -59,7 +59,7 @@ class PresentCommand(implicit val ioOnMainThread: OnMinecraftServerThread[IO]) { * * 出力: 定義が成功した場合は、割り振られたアイテムのIDを表示する。失敗した場合は、適切なエラーメッセージを表示する。 */ - private def defineExecutor[F[_] : ConcurrentEffect : NonServerThreadContextShift](implicit persistence: JdbcBackedPresentPersistence[F]) = + private def defineExecutor[F[_] : ConcurrentEffect : NonServerThreadContextShift](implicit persistence: PresentPersistence[F, ItemStack]) = playerCommandBuilder .argumentsParsers(List()) .execution { context => @@ -92,7 +92,7 @@ class PresentCommand(implicit val ioOnMainThread: OnMinecraftServerThread[IO]) { * * 出力: 操作の結果とそれに伴うメッセージ。 */ - private def deleteExecutor[F[_] : ConcurrentEffect : NonServerThreadContextShift](implicit persistence: JdbcBackedPresentPersistence[F]) = + private def deleteExecutor[F[_] : ConcurrentEffect : NonServerThreadContextShift](implicit persistence: PresentPersistence[F, ItemStack]) = playerCommandBuilder .argumentsParsers(List(presentIdParser)) .execution { context => @@ -125,7 +125,7 @@ class PresentCommand(implicit val ioOnMainThread: OnMinecraftServerThread[IO]) { * 備考: * - †: スペース区切り。 */ - private def grantRightExecutor[F[_] : ConcurrentEffect : NonServerThreadContextShift](implicit persistence: JdbcBackedPresentPersistence[F], globalPlayerAccessor: UuidToLastSeenName[F]) = + private def grantRightExecutor[F[_] : ConcurrentEffect : NonServerThreadContextShift](implicit persistence: PresentPersistence[F, ItemStack], globalPlayerAccessor: UuidToLastSeenName[F]) = playerCommandBuilder .argumentsParsers( List( @@ -178,7 +178,7 @@ class PresentCommand(implicit val ioOnMainThread: OnMinecraftServerThread[IO]) { * 備考: * - ✝: スペース区切り。 */ - private def revokeRightExecutor[F[_] : ConcurrentEffect : NonServerThreadContextShift](implicit persistence: JdbcBackedPresentPersistence[F], globalPlayerAccessor: UuidToLastSeenName[F]) = + private def revokeRightExecutor[F[_] : ConcurrentEffect : NonServerThreadContextShift](implicit persistence: PresentPersistence[F, ItemStack], globalPlayerAccessor: UuidToLastSeenName[F]) = playerCommandBuilder .argumentsParsers( List( @@ -228,7 +228,7 @@ class PresentCommand(implicit val ioOnMainThread: OnMinecraftServerThread[IO]) { * * 出力: 受け取った場合は、その旨表示する。失敗した場合は、適切なエラーメッセージを表示する。 */ - private def claimExecutor[F[_] : ConcurrentEffect : NonServerThreadContextShift](implicit persistence: JdbcBackedPresentPersistence[F]) = + private def claimExecutor[F[_] : ConcurrentEffect : NonServerThreadContextShift](implicit persistence: PresentPersistence[F, ItemStack]) = playerCommandBuilder .argumentsParsers(List(presentIdParser)) .execution { context => @@ -275,7 +275,7 @@ class PresentCommand(implicit val ioOnMainThread: OnMinecraftServerThread[IO]) { * 構文: * - /present state */ - private def showStateExecutor[F[_] : ConcurrentEffect : NonServerThreadContextShift](implicit persistence: JdbcBackedPresentPersistence[F]) = playerCommandBuilder + private def showStateExecutor[F[_] : ConcurrentEffect : NonServerThreadContextShift](implicit persistence: PresentPersistence[F, ItemStack]) = playerCommandBuilder .execution { context => val eff = for { // off-main-thread @@ -304,7 +304,7 @@ class PresentCommand(implicit val ioOnMainThread: OnMinecraftServerThread[IO]) { * * - /present list <page: PositiveInt> */ - private def listExecutor[F[_] : ConcurrentEffect : NonServerThreadContextShift](implicit persistence: JdbcBackedPresentPersistence[F]) = + private def listExecutor[F[_] : ConcurrentEffect : NonServerThreadContextShift](implicit persistence: PresentPersistence[F, ItemStack]) = playerCommandBuilder .argumentsParsers(List(Parsers.closedRangeInt(1, Int.MaxValue, MessageEffect("ページ数には1以上の数を指定してください。")))) .execution { context => @@ -359,7 +359,9 @@ class PresentCommand(implicit val ioOnMainThread: OnMinecraftServerThread[IO]) { ) ) - def executor[F[_] : ConcurrentEffect : NonServerThreadContextShift](implicit persistence: JdbcBackedPresentPersistence[F], globalPlayerAccessor: UuidToLastSeenName[F]): TabExecutor = BranchedExecutor( + def executor[ + F[_] : ConcurrentEffect : NonServerThreadContextShift + ](implicit persistence: PresentPersistence[F, ItemStack], globalPlayerAccessor: UuidToLastSeenName[F]): TabExecutor = BranchedExecutor( Map( "define" -> defineExecutor, "delete" -> deleteExecutor, From 16f9192a6c0989e83e99a57067e81ab216862879 Mon Sep 17 00:00:00 2001 From: Kory <6561358+kory33@users.noreply.github.com> Date: Tue, 3 Aug 2021 08:20:45 +0900 Subject: [PATCH 30/73] =?UTF-8?q?[fix]=20updateAndReturnGeneratedKey?= =?UTF-8?q?=E3=81=AEindex=E6=8C=87=E5=AE=9A=E3=82=92=E6=B6=88=E3=81=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../present/infrastructure/JdbcBackedPresentPersistence.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/infrastructure/JdbcBackedPresentPersistence.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/infrastructure/JdbcBackedPresentPersistence.scala index 5613f763d3..6673e96452 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/infrastructure/JdbcBackedPresentPersistence.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/infrastructure/JdbcBackedPresentPersistence.scala @@ -19,7 +19,7 @@ class JdbcBackedPresentPersistence[F[_] : Sync] extends PresentPersistence[F, It DB.localTx { implicit session => // プレゼントのIDはauto_incrementなので明示的に指定しなくて良い sql"""INSERT INTO present (itemstack) VALUES ($stackAsBlob)""" - .updateAndReturnGeneratedKey("present_id") + .updateAndReturnGeneratedKey .apply() } } From e8a870601cc11f14dcce27fb4877e44fc582f498 Mon Sep 17 00:00:00 2001 From: Kory <6561358+kory33@users.noreply.github.com> Date: Tue, 3 Aug 2021 12:18:59 +0900 Subject: [PATCH 31/73] =?UTF-8?q?[update]=20=E5=BC=95=E6=95=B0=E3=81=8C?= =?UTF-8?q?=E8=B6=B3=E3=82=8A=E3=81=AA=E3=81=8B=E3=81=A3=E3=81=9F=E6=99=82?= =?UTF-8?q?=E3=81=AE=E3=83=A1=E3=83=83=E3=82=BB=E3=83=BC=E3=82=B8=E3=82=92?= =?UTF-8?q?=E6=98=8E=E7=A2=BA=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/plugin.yml | 2 +- .../executors/EchoExecutor.scala | 2 +- .../executors/TraverseExecutor.scala | 12 + .../bukkit/command/PresentCommand.scala | 640 ++++++++++-------- 4 files changed, 357 insertions(+), 299 deletions(-) create mode 100644 src/main/scala/com/github/unchama/contextualexecutor/executors/TraverseExecutor.scala diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index e9c064fc2a..6236a907fe 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -105,7 +105,7 @@ commands: permission-message: *denied present: description: send a gift - usage: /<command> [player name] + usage: /present <操作> (詳細については/present helpを参照してください) permission-message: *denied hat: description: set item in hand to head diff --git a/src/main/scala/com/github/unchama/contextualexecutor/executors/EchoExecutor.scala b/src/main/scala/com/github/unchama/contextualexecutor/executors/EchoExecutor.scala index afe06994e7..d5dec4d92f 100644 --- a/src/main/scala/com/github/unchama/contextualexecutor/executors/EchoExecutor.scala +++ b/src/main/scala/com/github/unchama/contextualexecutor/executors/EchoExecutor.scala @@ -8,6 +8,6 @@ import org.bukkit.command.CommandSender /** * 実行されたときに[effect]を送り返すだけの[ContextualExecutor]. */ -class EchoExecutor(private val effect: TargetedEffect[CommandSender]) extends ContextualExecutor { +case class EchoExecutor(effect: TargetedEffect[CommandSender]) extends ContextualExecutor { override def executeWith(rawContext: RawCommandContext): IO[Unit] = effect(rawContext.sender) } \ No newline at end of file diff --git a/src/main/scala/com/github/unchama/contextualexecutor/executors/TraverseExecutor.scala b/src/main/scala/com/github/unchama/contextualexecutor/executors/TraverseExecutor.scala new file mode 100644 index 0000000000..617b3a0ede --- /dev/null +++ b/src/main/scala/com/github/unchama/contextualexecutor/executors/TraverseExecutor.scala @@ -0,0 +1,12 @@ +package com.github.unchama.contextualexecutor.executors + +import cats.effect.IO +import com.github.unchama.contextualexecutor.{ContextualExecutor, RawCommandContext} + +case class TraverseExecutor(executors: List[ContextualExecutor]) extends ContextualExecutor { + import cats.implicits._ + + override def executeWith(commandContext: RawCommandContext): IO[Unit] = { + executors.traverse(_.executeWith(commandContext)).void + } +} diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/bukkit/command/PresentCommand.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/bukkit/command/PresentCommand.scala index e9b5b0a388..3e6b8a5506 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/bukkit/command/PresentCommand.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/bukkit/command/PresentCommand.scala @@ -7,10 +7,11 @@ import cats.implicits._ import com.github.unchama.concurrent.NonServerThreadContextShift import com.github.unchama.contextualexecutor.ContextualExecutor import com.github.unchama.contextualexecutor.builder.Parsers -import com.github.unchama.contextualexecutor.executors.{BranchedExecutor, EchoExecutor} +import com.github.unchama.contextualexecutor.executors.{BranchedExecutor, EchoExecutor, TraverseExecutor} import com.github.unchama.minecraft.actions.OnMinecraftServerThread import com.github.unchama.seichiassist.commands.contextual.builder.BuilderTemplates.playerCommandBuilder import com.github.unchama.seichiassist.domain.actions.UuidToLastSeenName +import com.github.unchama.seichiassist.subsystems.present.domain.OperationResult.DeleteResult import com.github.unchama.seichiassist.subsystems.present.domain.{PresentClaimingState, PresentPersistence} import com.github.unchama.seichiassist.util.Util import com.github.unchama.targetedeffect.commandsender.MessageEffect @@ -48,332 +49,377 @@ class PresentCommand(implicit val ioOnMainThread: OnMinecraftServerThread[IO]) { private val noPermissionMessage = MessageEffect("You don't have the permission.") - /** - * 概要: メインハンドに持っているアイテムをプレゼントとして定義する。 - * プレイヤーがプレゼントを受け取ることができるようになるには、必ずプレゼントを定義しなければならない。 - * - * 権限ノード: `seichiassist.present.define` - * - * 構文: - * - /present define - * - * 出力: 定義が成功した場合は、割り振られたアイテムのIDを表示する。失敗した場合は、適切なエラーメッセージを表示する。 - */ - private def defineExecutor[F[_] : ConcurrentEffect : NonServerThreadContextShift](implicit persistence: PresentPersistence[F, ItemStack]) = - playerCommandBuilder - .argumentsParsers(List()) - .execution { context => - val player = context.sender - if (!player.hasPermission("seichiassist.present.define")) { - IO.pure(noPermissionMessage) - } else { - val mainHandItem = player.getInventory.getItemInMainHand - if (mainHandItem.getType eq Material.AIR) { - // おそらくこれは意図した動作ではないのでエラーメッセージを表示する - IO.pure(MessageEffect("メインハンドに何も持っていません。プレゼントを定義するためには、メインハンドに対象アイテムを持ってください。")) - } else { + private object SubCommands { + object State { + val help: EchoExecutor = EchoExecutor(MessageEffect(List( + "/present state", + " 対象となっている全てのプレゼントを表示します" + ))) + + /** + * 概要: 全てのプレゼントのうち、実行プレイヤーが対象となっているプレゼントの受け取り状況を表示する。 + * 実行プレイヤーが対象ではないプレゼントは表示されない。 + * + * 構文: + * - /present state + */ + def executor[F[_] : ConcurrentEffect : NonServerThreadContextShift](implicit persistence: PresentPersistence[F, ItemStack]): ContextualExecutor = playerCommandBuilder + .execution { context => + val eff = for { + // off-main-thread + _ <- NonServerThreadContextShift[F].shift + state <- persistence.fetchState(context.sender.getUniqueId) + } yield { + val mes = state + .toList + // 配布対象外のプレゼントを除外 + .filter { case (_, state) => state != PresentClaimingState.Unavailable } + .map { case (id, state) => + s"ID=$id: ${decoratePresentState(state)}" + } + .filter(_.nonEmpty) + MessageEffect(mes) + } + + eff.toIO + } + .build() + } + + object ListSubCommand { + val help: EchoExecutor = EchoExecutor(MessageEffect(List( + s"${ChatColor.GRAY}コマンドの構文: /present list <ページ数>" + ))) + + /** + * 概要: 実行プレイヤーと全てのプレゼントの受け取り状況をページネーションと共に表示する + * + * 構文: + * + * - /present list <page: PositiveInt> + */ + def executor[F[_] : ConcurrentEffect : NonServerThreadContextShift](implicit persistence: PresentPersistence[F, ItemStack]): ContextualExecutor = + playerCommandBuilder + .argumentsParsers( + List( + Parsers.closedRangeInt(1, Int.MaxValue, MessageEffect("ページ数には1以上の数を指定してください。")) + ), + onMissingArguments = help + ) + .execution { context => + val perPage: Int Refined Positive = 10 + val page = refineV[Positive](context.args.parsed.head.asInstanceOf[Int]) match { + // argumentsParsersで1以上を指定しているのでここでコケることはないはず + case Left(l) => throw new AssertionError(s"positive int: failed. message: $l") + case Right(v) => v + } + val player = context.sender.getUniqueId val eff = for { _ <- NonServerThreadContextShift[F].shift - presentID <- persistence.define(mainHandItem) + states <- persistence.fetchStateWithPagination(player, perPage, page) + messageLine = states + .map { case (id, state) => + s"ID=$id: ${decoratePresentState(state)}" + } + .toList } yield { - MessageEffect(s"メインハンドに持ったアイテムをプレゼントとして定義しました。IDは${presentID}です。") + MessageEffect(messageLine) } eff.toIO } - } - - } - .build() - - /** - * 概要: 指定したプレゼントを消去する。対応が失われるため、このコマンドの実行が完了した後、プレイヤーはそのプレゼントを受け取ることができなくなる。 - * - * 権限ノード: `seichiassist.present.delete` - * - * 出力: 操作の結果とそれに伴うメッセージ。 - */ - private def deleteExecutor[F[_] : ConcurrentEffect : NonServerThreadContextShift](implicit persistence: PresentPersistence[F, ItemStack]) = - playerCommandBuilder - .argumentsParsers(List(presentIdParser)) - .execution { context => - if (!context.sender.hasPermission("seichiassist.present.delete")) { - IO.pure(noPermissionMessage) - } else { - val presentId = context.args.parsed.head.asInstanceOf[Int] - val eff = for { - _ <- NonServerThreadContextShift[F].shift - _ <- persistence.delete(presentId) - } yield MessageEffect(s"IDが${presentId}のプレゼントの消去は正常に行われました。") + .build() + } - eff.toIO - } - } - .build() + object Claim { + val help: EchoExecutor = EchoExecutor(MessageEffect(List( + "/present claim <プレゼントID>", + " プレゼントを受け取ります", + ))) - /** - * 概要: プレイヤーが指定されたプレゼントを受け取れるようにする。 - * - * 権限ノード: `seichiassist.present.grant` - * - * 出力: 操作の結果とそれに伴うメッセージ - * - * コマンド構文: - * - * - /present grant <presentId: PresentID> player <...players^†^: PlayerName> - * - /present grant <presentId: PresentID> all - * - * 備考: - * - †: スペース区切り。 - */ - private def grantRightExecutor[F[_] : ConcurrentEffect : NonServerThreadContextShift](implicit persistence: PresentPersistence[F, ItemStack], globalPlayerAccessor: UuidToLastSeenName[F]) = - playerCommandBuilder - .argumentsParsers( - List( - presentIdParser, - presentScopeModeParser, - ) - ) - .execution { context => - if (!context.sender.hasPermission("seichiassist.present.grant")) { - IO.pure(noPermissionMessage) - } else { - // Parserを通した段階でargs[0]は "player" | "all" になっているのでこれでOK - val List(_presentId, mode) = context.args.parsed - val presentId = _presentId.asInstanceOf[Int] - val isGlobal = mode.asInstanceOf[String] == "all" - val eff = for { - _ <- NonServerThreadContextShift[F].shift - // TODO: 以下の処理は多分共通化できるがうまい方法が思いつかない - globalUUID2Name <- globalPlayerAccessor.entries - // 可変長引数には対応していないので`yetToBeParsed`を使う - restArg = context.args - // プレイヤー名は /[A-Za-z0-9_]{,16}/であるため空白が誤って解釈されることはない - .yetToBeParsed - // 連続した空白を消去 - .filter(_.nonEmpty) - target = if (isGlobal) - globalUUID2Name.keys - else - globalUUID2Name.filter { case (_, name) => restArg.contains(name) }.keys - errorIfNobody = if (target.isEmpty) Some(MessageEffect("対象のプレイヤーが存在しません!")) else None - _ <- persistence.grant(presentId, target.toSet) - } yield errorIfNobody.getOrElse(MessageEffect(s"プレゼントIDが${presentId}のプレゼントを受け取れるプレイヤーを追加することに成功しました。")) + /** + * 概要: 指定されたIDのプレゼントを受け取れるかどうかテストする。 + * 受け取れる場合は、プレイヤーのインベントリにアイテムを追加する。 + * 受け取れない場合は、エラーメッセージを表示する。 + * + * 構文: + * - /present claim <presentId: PresentID> + * + * 出力: 受け取った場合は、その旨表示する。失敗した場合は、適切なエラーメッセージを表示する。 + */ + def executor[F[_] : ConcurrentEffect : NonServerThreadContextShift](implicit persistence: PresentPersistence[F, ItemStack]): ContextualExecutor = + playerCommandBuilder + .argumentsParsers(List(presentIdParser), onMissingArguments = help) + .execution { context => + val player = context.sender.getUniqueId + val presentId = context.args.parsed.head.asInstanceOf[Int] - eff.toIO - } - } - .build() + // この明示的な型変数の指定は必要 + val eff: F[TargetedEffect[Player]] = for { + _ <- NonServerThreadContextShift[F].shift + states <- persistence.fetchState(player) + claimState = states.getOrElse(presentId, PresentClaimingState.Unavailable) + effect <- claimState match { + case PresentClaimingState.Claimed => + Monad[F].pure(MessageEffect(s"ID: ${presentId}のプレゼントはすでに受け取っています。")) + case PresentClaimingState.NotClaimed => + for { + _ <- persistence.markAsClaimed(presentId, player) + item <- persistence.lookup(presentId) + } yield { + // 注釈: この明示的な型変数の指定は必要 + // see: https://discord.com/channels/237758724121427969/565935041574731807/823495317499805776 + item.fold[TargetedEffect[Player]]( + MessageEffect(s"ID: ${presentId}のプレゼントは存在しません。IDをお確かめください。") + ) { item => + SequentialEffect( + Util.grantItemStacksEffect[IO](item), + MessageEffect(s"ID: ${presentId}のプレゼントを付与しました。") + ) + } + } + case PresentClaimingState.Unavailable => + Monad[F].pure(MessageEffect(s"ID: ${presentId}のプレゼントは存在しないか、あるいは配布対象ではありません。")) + } + } yield effect - /** - * 概要: プレイヤーがプレゼントを受け取れないようにする。 - * - * 権限ノード: `seichiassist.present.revoke` - * - * 構文: - * - /present revoke <presentId: PresentID> player <...players^✝^: PlayerName> - * - /present revoke <presentId: PresentID> all - * - * 出力: 操作の結果とそれに伴うメッセージ。 - * - * 備考: - * - ✝: スペース区切り。 - */ - private def revokeRightExecutor[F[_] : ConcurrentEffect : NonServerThreadContextShift](implicit persistence: PresentPersistence[F, ItemStack], globalPlayerAccessor: UuidToLastSeenName[F]) = - playerCommandBuilder - .argumentsParsers( - List( - presentIdParser, - presentScopeModeParser, - ) - ) - .execution { context => - if (!context.sender.hasPermission("seichiassist.present.revoke")) { - IO.pure(noPermissionMessage) - } else { - val args = context.args - val presentId = args.parsed.head.asInstanceOf[Int] - val isGlobal = args.parsed(1).asInstanceOf[String] == "all" - val eff = for { - _ <- NonServerThreadContextShift[F].shift - globalUUID2Name <- globalPlayerAccessor.entries - // 可変長引数には対応していないので`yetToBeParsed`を使う - restArg = args - // プレイヤー名は /[A-Za-z0-9_]{,16}/であるため空白が誤って解釈されることはない - .yetToBeParsed - // 連続した空白を消去 - .filter(_.nonEmpty) - target = if (isGlobal) - globalUUID2Name.keys - else - globalUUID2Name.filter { case (_, name) => restArg.contains(name) }.keys - errorIfNobody = if (target.isEmpty) Some(MessageEffect("対象のプレイヤーが存在しません!")) else None - _ <- persistence.revoke(presentId, target.toSet) - } yield { - errorIfNobody.getOrElse( - MessageEffect(s"プレゼントIDが${presentId}のプレゼントを受け取ることができるプレイヤーの削除に成功しました。") - ) + eff.toIO } - eff.toIO - } - } - .build() + .build() + } - /** - * 概要: 指定されたIDのプレゼントを受け取れるかどうかテストする。 - * 受け取れる場合は、プレイヤーのインベントリにアイテムを追加する。 - * 受け取れない場合は、エラーメッセージを表示する。 - * - * 構文: - * - /present claim <presentId: PresentID> - * - * 出力: 受け取った場合は、その旨表示する。失敗した場合は、適切なエラーメッセージを表示する。 - */ - private def claimExecutor[F[_] : ConcurrentEffect : NonServerThreadContextShift](implicit persistence: PresentPersistence[F, ItemStack]) = - playerCommandBuilder - .argumentsParsers(List(presentIdParser)) - .execution { context => - val player = context.sender.getUniqueId - val presentId = context.args.parsed.head.asInstanceOf[Int] + object Define { + val help: EchoExecutor = EchoExecutor(MessageEffect(List( + "/present define", + " プレゼントを手に持っているアイテムで定義します", + ))) - // この明示的な型変数の指定は必要 - val eff: F[TargetedEffect[Player]] = for { - _ <- NonServerThreadContextShift[F].shift - states <- persistence.fetchState(player) - claimState = states.getOrElse(presentId, PresentClaimingState.Unavailable) - effect <- claimState match { - case PresentClaimingState.Claimed => - Monad[F].pure(MessageEffect(s"ID: ${presentId}のプレゼントはすでに受け取っています。")) - case PresentClaimingState.NotClaimed => - for { - _ <- persistence.markAsClaimed(presentId, player) - item <- persistence.lookup(presentId) - } yield { - // 注釈: この明示的な型変数の指定は必要 - // see: https://discord.com/channels/237758724121427969/565935041574731807/823495317499805776 - item.fold[TargetedEffect[Player]]( - MessageEffect(s"ID: ${presentId}のプレゼントは存在しません。IDをお確かめください。") - ) { item => - SequentialEffect( - Util.grantItemStacksEffect[IO](item), - MessageEffect(s"ID: ${presentId}のプレゼントを付与しました。") - ) + /** + * 概要: メインハンドに持っているアイテムをプレゼントとして定義する。 + * プレイヤーがプレゼントを受け取ることができるようになるには、必ずプレゼントを定義しなければならない。 + * + * 権限ノード: `seichiassist.present.define` + * + * 構文: + * - /present define + * + * 出力: 定義が成功した場合は、割り振られたアイテムのIDを表示する。失敗した場合は、適切なエラーメッセージを表示する。 + */ + def executor[F[_] : ConcurrentEffect : NonServerThreadContextShift](implicit persistence: PresentPersistence[F, ItemStack]): ContextualExecutor = + playerCommandBuilder + .execution { context => + val player = context.sender + if (player.hasPermission("seichiassist.present.define")) { + val mainHandItem = player.getInventory.getItemInMainHand + if (mainHandItem.getType eq Material.AIR) { + // おそらくこれは意図した動作ではないのでエラーメッセージを表示する + IO.pure(MessageEffect("メインハンドに何も持っていません。プレゼントを定義するためには、メインハンドに対象アイテムを持ってください。")) + } else { + val eff = for { + _ <- NonServerThreadContextShift[F].shift + presentID <- persistence.define(mainHandItem) + } yield { + MessageEffect(s"メインハンドに持ったアイテムをプレゼントとして定義しました。IDは${presentID}です。") } + eff.toIO } - case PresentClaimingState.Unavailable => - Monad[F].pure(MessageEffect(s"ID: ${presentId}のプレゼントは存在しないか、あるいは配布対象ではありません。")) + } else { + IO.pure(noPermissionMessage) + } } - } yield effect + .build() + } - eff.toIO - } - .build() + object Delete { + val help: EchoExecutor = EchoExecutor(MessageEffect(List( + "/present delete <プレゼントID>", + " プレゼントを削除します", + ))) + + /** + * 概要: 指定したプレゼントを消去する。 + * 対応が失われるため、このコマンドの実行が完了した後、プレイヤーはそのプレゼントを受け取ることができなくなる。 + * + * 権限ノード: `seichiassist.present.delete` + * + * 出力: 操作の結果とそれに伴うメッセージ。 + */ + def executor[F[_] : ConcurrentEffect : NonServerThreadContextShift](implicit persistence: PresentPersistence[F, ItemStack]): ContextualExecutor = + playerCommandBuilder + .argumentsParsers(List(presentIdParser), onMissingArguments = help) + .execution { context => + if (!context.sender.hasPermission("seichiassist.present.delete")) { + IO.pure(noPermissionMessage) + } else { + val presentId = context.args.parsed.head.asInstanceOf[Int] + val eff = for { + _ <- NonServerThreadContextShift[F].shift + result <- persistence.delete(presentId) + } yield result match { + case DeleteResult.Done => + MessageEffect(s"IDが${presentId}のプレゼントの消去は正常に行われました。") + case DeleteResult.NotFount => + MessageEffect(s"IDが${presentId}のプレゼントは存在しませんでした。") + } - /** - * 概要: 全てのプレゼントのうち、実行プレイヤーが対象となっているプレゼントの受け取り状況を表示する。 - * 実行プレイヤーが対象ではないプレゼントは表示されない。 - * - * 構文: - * - /present state - */ - private def showStateExecutor[F[_] : ConcurrentEffect : NonServerThreadContextShift](implicit persistence: PresentPersistence[F, ItemStack]) = playerCommandBuilder - .execution { context => - val eff = for { - // off-main-thread - _ <- NonServerThreadContextShift[F].shift - state <- persistence.fetchState(context.sender.getUniqueId) - } yield { - val mes = state - .toList - // 配布対象外のプレゼントを除外 - .filter { case (_, state) => state != PresentClaimingState.Unavailable } - .map { case (id, state) => - s"ID=$id: ${decoratePresentState(state)}" + eff.toIO + } } - .filter(_.nonEmpty) - MessageEffect(mes) - } + .build() + } + + object Grant { + val help: EchoExecutor = EchoExecutor(MessageEffect(List( + "/present grant <プレゼントID> all|(player <...プレーヤー名>)", + " プレゼントを受け取れるプレイヤーを追加します", + ))) + + /** + * 概要: プレイヤーが指定されたプレゼントを受け取れるようにする。 + * + * 権限ノード: `seichiassist.present.grant` + * + * 出力: 操作の結果とそれに伴うメッセージ + * + * コマンド構文: + * + * - /present grant <presentId: PresentID> player <...players^†^: PlayerName> + * - /present grant <presentId: PresentID> all + * + * 備考: + * - †: スペース区切り。 + */ + def executor[F[_] : ConcurrentEffect : NonServerThreadContextShift](implicit persistence: PresentPersistence[F, ItemStack], globalPlayerAccessor: UuidToLastSeenName[F]): ContextualExecutor = + playerCommandBuilder + .argumentsParsers(List(presentIdParser, presentScopeModeParser), onMissingArguments = help) + .execution { context => + if (context.sender.hasPermission("seichiassist.present.grant")) { + // Parserを通した段階でargs[0]は "player" | "all" になっているのでこれでOK + val List(_presentId, mode) = context.args.parsed + val presentId = _presentId.asInstanceOf[Int] + val isGlobal = mode.asInstanceOf[String] == "all" + val eff = for { + _ <- NonServerThreadContextShift[F].shift + // TODO: 以下の処理は多分共通化できるがうまい方法が思いつかない + globalUUID2Name <- globalPlayerAccessor.entries + // 可変長引数には対応していないので`yetToBeParsed`を使う + restArg = context.args + // プレイヤー名は /[A-Za-z0-9_]{,16}/であるため空白が誤って解釈されることはない + .yetToBeParsed + // 連続した空白を消去 + .filter(_.nonEmpty) + target = if (isGlobal) + globalUUID2Name.keys + else + globalUUID2Name.filter { case (_, name) => restArg.contains(name) }.keys + errorIfNobody = if (target.isEmpty) Some(MessageEffect("対象のプレイヤーが存在しません!")) else None + _ <- persistence.grant(presentId, target.toSet) + } yield errorIfNobody.getOrElse(MessageEffect(s"プレゼントIDが${presentId}のプレゼントを受け取れるプレイヤーを追加することに成功しました。")) - eff.toIO + eff.toIO + } else { + IO.pure(noPermissionMessage) + } + } + .build() } - .build() - /** - * 概要: 実行プレイヤーと全てのプレゼントの受け取り状況をページネーションと共に表示する - * - * 構文: - * - * - /present list <page: PositiveInt> - */ - private def listExecutor[F[_] : ConcurrentEffect : NonServerThreadContextShift](implicit persistence: PresentPersistence[F, ItemStack]) = - playerCommandBuilder - .argumentsParsers(List(Parsers.closedRangeInt(1, Int.MaxValue, MessageEffect("ページ数には1以上の数を指定してください。")))) - .execution { context => - val perPage: Int Refined Positive = 10 - val page = refineV[Positive](context.args.parsed.head.asInstanceOf[Int]) match { - // argumentsParsersで1以上を指定しているのでここでコケることはないはず - case Left(l) => throw new AssertionError(s"positive int: failed. message: $l") - case Right(v) => v - } - val player = context.sender.getUniqueId - val eff = for { - _ <- NonServerThreadContextShift[F].shift - states <- persistence.fetchStateWithPagination(player, perPage, page) - messageLine = states - .map { case (id, state) => - s"ID=$id: ${decoratePresentState(state)}" + object Revoke { + val help: EchoExecutor = EchoExecutor(MessageEffect(List( + "/present revoke <プレゼントID> all|(player <...プレーヤー名>)", + " プレゼントを受け取れるプレイヤーを削除します" + ))) + + /** + * 概要: プレイヤーがプレゼントを受け取れないようにする。 + * + * 権限ノード: `seichiassist.present.revoke` + * + * 構文: + * - /present revoke <presentId: PresentID> player <...players^✝^: PlayerName> + * - /present revoke <presentId: PresentID> all + * + * 出力: 操作の結果とそれに伴うメッセージ。 + * + * 備考: + * - ✝: スペース区切り。 + */ + def executor[F[_] : ConcurrentEffect : NonServerThreadContextShift](implicit persistence: PresentPersistence[F, ItemStack], globalPlayerAccessor: UuidToLastSeenName[F]): ContextualExecutor = + playerCommandBuilder + .argumentsParsers(List(presentIdParser, presentScopeModeParser), onMissingArguments = help) + .execution { context => + if (context.sender.hasPermission("seichiassist.present.revoke")) { + val args = context.args + val presentId = args.parsed.head.asInstanceOf[Int] + val isGlobal = args.parsed(1).asInstanceOf[String] == "all" + val eff = for { + _ <- NonServerThreadContextShift[F].shift + globalUUID2Name <- globalPlayerAccessor.entries + // 可変長引数には対応していないので`yetToBeParsed`を使う + restArg = args + // プレイヤー名は /[A-Za-z0-9_]{,16}/であるため空白が誤って解釈されることはない + .yetToBeParsed + // 連続した空白を消去 + .filter(_.nonEmpty) + target = if (isGlobal) + globalUUID2Name.keys + else + globalUUID2Name.filter { case (_, name) => restArg.contains(name) }.keys + errorIfNobody = if (target.isEmpty) Some(MessageEffect("対象のプレイヤーが存在しません!")) else None + _ <- persistence.revoke(presentId, target.toSet) + } yield { + errorIfNobody.getOrElse( + MessageEffect(s"プレゼントIDが${presentId}のプレゼントを受け取ることができるプレイヤーの削除に成功しました。") + ) + } + eff.toIO + } else { + IO.pure(noPermissionMessage) } - .toList - } yield { - MessageEffect(messageLine) - } - eff.toIO - } - .build() + } + .build() + } - /** - * 概要: マニュアルを表示する。 - * - * 引数: - * - /present help - */ - def helpExecutor: ContextualExecutor = new EchoExecutor( - MessageEffect( - List( - "/present define", - " プレゼントを定義します", - "/present delete", - " プレゼントを削除します", - "/present grant", - " プレゼントを受け取れるプレイヤーを追加します", - "/present revoke", - " プレゼントを受け取れるプレイヤーを削除します", - "/present claim", - " プレゼントを受け取ります", - "/present list", - " 全てのプレゼントを表示します", - "/present state", - " 対象となっている全てのプレゼントを表示します", - "/present help", - " このメッセージを表示します" - ) - ) - ) + object Help { + /** + * 概要: マニュアルを表示する。 + * + * 引数: + * - /present help + */ + def executor: ContextualExecutor = { + TraverseExecutor(List( + SubCommands.State.help, + SubCommands.ListSubCommand.help, + SubCommands.Claim.help, + EchoExecutor(MessageEffect(List( + "/present help", + " このメッセージを表示します", + s"${ChatColor.GRAY}==== [管理者用コマンド] ====", + ))), + SubCommands.Define.help, + SubCommands.Delete.help, + SubCommands.Grant.help, + SubCommands.Revoke.help, + )) + } + } + } def executor[ F[_] : ConcurrentEffect : NonServerThreadContextShift ](implicit persistence: PresentPersistence[F, ItemStack], globalPlayerAccessor: UuidToLastSeenName[F]): TabExecutor = BranchedExecutor( Map( - "define" -> defineExecutor, - "delete" -> deleteExecutor, - "grant" -> grantRightExecutor, - "revoke" -> revokeRightExecutor, - "claim" -> claimExecutor, - "list" -> listExecutor, - "state" -> showStateExecutor, - "help" -> helpExecutor, + "define" -> SubCommands.Define.executor, + "delete" -> SubCommands.Delete.executor, + "grant" -> SubCommands.Grant.executor, + "revoke" -> SubCommands.Revoke.executor, + "claim" -> SubCommands.Claim.executor, + "list" -> SubCommands.ListSubCommand.executor, + "state" -> SubCommands.State.executor, + "help" -> SubCommands.Help.executor, ), - Some(helpExecutor), - Some(helpExecutor) + Some(SubCommands.Help.executor), + Some(SubCommands.Help.executor) ).asNonBlockingTabExecutor() private def decoratePresentState(state: PresentClaimingState): String = state match { From e7ffca15584bdd11ba152fcf27ea9493d1129456 Mon Sep 17 00:00:00 2001 From: Kory <6561358+kory33@users.noreply.github.com> Date: Tue, 3 Aug 2021 12:20:06 +0900 Subject: [PATCH 32/73] =?UTF-8?q?[update]=20delete=E6=99=82=E3=81=AE?= =?UTF-8?q?=E3=83=A1=E3=83=83=E3=82=BB=E3=83=BC=E3=82=B8=E3=82=92=E3=82=88?= =?UTF-8?q?=E3=82=8A=E3=82=AF=E3=83=AA=E3=82=A2=E3=81=AB=E3=81=99=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../present/domain/OperationResult.scala | 9 +++++++++ .../present/domain/PresentPersistence.scala | 3 ++- .../JdbcBackedPresentPersistence.scala | 14 +++++++++----- 3 files changed, 20 insertions(+), 6 deletions(-) create mode 100644 src/main/scala/com/github/unchama/seichiassist/subsystems/present/domain/OperationResult.scala diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/domain/OperationResult.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/domain/OperationResult.scala new file mode 100644 index 0000000000..ddb926eeea --- /dev/null +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/domain/OperationResult.scala @@ -0,0 +1,9 @@ +package com.github.unchama.seichiassist.subsystems.present.domain + +object OperationResult { + sealed trait DeleteResult + object DeleteResult { + case object Done extends DeleteResult + case object NotFount extends DeleteResult + } +} diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/domain/PresentPersistence.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/domain/PresentPersistence.scala index beb0a1edea..fb07d50e7b 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/domain/PresentPersistence.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/domain/PresentPersistence.scala @@ -1,5 +1,6 @@ package com.github.unchama.seichiassist.subsystems.present.domain +import com.github.unchama.seichiassist.subsystems.present.domain.OperationResult.DeleteResult import eu.timepit.refined.api.Refined import eu.timepit.refined.numeric.Positive @@ -27,7 +28,7 @@ trait PresentPersistence[F[_], ItemStack] { * * @param presentID プレゼントID */ - def delete(presentID: PresentID): F[Unit] + def delete(presentID: PresentID): F[DeleteResult] /** * 指定したUUIDを持つプレイヤーに対して`presentID`で指定されたプレゼントを受け取ることができるようにする。 diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/infrastructure/JdbcBackedPresentPersistence.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/infrastructure/JdbcBackedPresentPersistence.scala index 6673e96452..f6a6ad585b 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/infrastructure/JdbcBackedPresentPersistence.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/infrastructure/JdbcBackedPresentPersistence.scala @@ -1,6 +1,7 @@ package com.github.unchama.seichiassist.subsystems.present.infrastructure import cats.effect.Sync +import com.github.unchama.seichiassist.subsystems.present.domain.OperationResult.DeleteResult import com.github.unchama.seichiassist.subsystems.present.domain.{PresentClaimingState, PresentPersistence} import eu.timepit.refined.api.Refined import eu.timepit.refined.auto._ @@ -29,16 +30,19 @@ class JdbcBackedPresentPersistence[F[_] : Sync] extends PresentPersistence[F, It * * @param presentId プレゼントID */ - override def delete(presentId: PresentID): F[Unit] = Sync[F].delay { + override def delete(presentId: PresentID): F[DeleteResult] = Sync[F].delay { DB.localTx { implicit session => // 制約をかけているのでpresent_stateの方から先に消さないと整合性エラーを吐く sql"""DELETE FROM present_state WHERE present_id = $presentId""" .execute() .apply() - sql"""DELETE FROM present WHERE present_id = $presentId""" - .execute() - .apply() + val deletedRows = + sql"""DELETE FROM present WHERE present_id = $presentId""" + .update() + .apply() + + if (deletedRows == 1) DeleteResult.Done else DeleteResult.NotFount } } @@ -144,7 +148,7 @@ class JdbcBackedPresentPersistence[F[_] : Sync] extends PresentPersistence[F, It Sync[F].delay { val offset = (page - 1) * perPage DB.readOnly { implicit session => - sql"""SELECT present_id FROM present ORDER BY present_id LIMIT $perPage OFFSET $offset""" + sql"""SELECT present_id FROM present ORDER BY present_id LIMIT ${perPage.value} OFFSET $offset""" .map { _.long("present_id") } .toList() .apply() From 68324459d8fabbc19be7119fe1065ff1094889f9 Mon Sep 17 00:00:00 2001 From: Kory <6561358+kory33@users.noreply.github.com> Date: Tue, 3 Aug 2021 12:25:07 +0900 Subject: [PATCH 33/73] =?UTF-8?q?[update]=20/present=20list=E3=81=AEhelp?= =?UTF-8?q?=E3=82=92=E5=85=83=E3=81=AB=E6=88=BB=E3=81=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../subsystems/present/bukkit/command/PresentCommand.scala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/bukkit/command/PresentCommand.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/bukkit/command/PresentCommand.scala index 3e6b8a5506..2675e28013 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/bukkit/command/PresentCommand.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/bukkit/command/PresentCommand.scala @@ -88,7 +88,8 @@ class PresentCommand(implicit val ioOnMainThread: OnMinecraftServerThread[IO]) { object ListSubCommand { val help: EchoExecutor = EchoExecutor(MessageEffect(List( - s"${ChatColor.GRAY}コマンドの構文: /present list <ページ数>" + "/present list", + " 全てのプレゼントを表示します", ))) /** From d41f778947ae6d8f3e52721634bb0db410fcf129 Mon Sep 17 00:00:00 2001 From: Kory <6561358+kory33@users.noreply.github.com> Date: Tue, 3 Aug 2021 12:29:51 +0900 Subject: [PATCH 34/73] =?UTF-8?q?[update]=20/present=20grant/revoke?= =?UTF-8?q?=E3=81=AE=E7=B5=90=E6=9E=9C=E3=83=A1=E3=83=83=E3=82=BB=E3=83=BC?= =?UTF-8?q?=E3=82=B8=E3=82=92=E8=AA=AD=E3=81=BF=E3=82=84=E3=81=99=E3=81=8F?= =?UTF-8?q?=E3=81=99=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../present/bukkit/command/PresentCommand.scala | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/bukkit/command/PresentCommand.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/bukkit/command/PresentCommand.scala index 2675e28013..adb658a801 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/bukkit/command/PresentCommand.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/bukkit/command/PresentCommand.scala @@ -314,7 +314,10 @@ class PresentCommand(implicit val ioOnMainThread: OnMinecraftServerThread[IO]) { globalUUID2Name.filter { case (_, name) => restArg.contains(name) }.keys errorIfNobody = if (target.isEmpty) Some(MessageEffect("対象のプレイヤーが存在しません!")) else None _ <- persistence.grant(presentId, target.toSet) - } yield errorIfNobody.getOrElse(MessageEffect(s"プレゼントIDが${presentId}のプレゼントを受け取れるプレイヤーを追加することに成功しました。")) + } yield + errorIfNobody.getOrElse(MessageEffect( + s"プレゼント(id: $presentId)を受け取れるプレイヤーを追加しました。" + )) eff.toIO } else { @@ -368,9 +371,9 @@ class PresentCommand(implicit val ioOnMainThread: OnMinecraftServerThread[IO]) { errorIfNobody = if (target.isEmpty) Some(MessageEffect("対象のプレイヤーが存在しません!")) else None _ <- persistence.revoke(presentId, target.toSet) } yield { - errorIfNobody.getOrElse( - MessageEffect(s"プレゼントIDが${presentId}のプレゼントを受け取ることができるプレイヤーの削除に成功しました。") - ) + errorIfNobody.getOrElse(MessageEffect( + s"プレゼント(id: $presentId)を受け取れるプレイヤーを削除しました。" + )) } eff.toIO } else { From 14aaf4f670c0d63beb31d3ed7bb3e99a13a2b074 Mon Sep 17 00:00:00 2001 From: KisaragiEffective <kisaragi.effective@gmail.com> Date: Tue, 3 Aug 2021 17:31:25 +0900 Subject: [PATCH 35/73] [fix] fix #1137 --- .../JdbcBackedPresentPersistence.scala | 28 +++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/infrastructure/JdbcBackedPresentPersistence.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/infrastructure/JdbcBackedPresentPersistence.scala index f6a6ad585b..1878a26c67 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/infrastructure/JdbcBackedPresentPersistence.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/infrastructure/JdbcBackedPresentPersistence.scala @@ -22,8 +22,8 @@ class JdbcBackedPresentPersistence[F[_] : Sync] extends PresentPersistence[F, It sql"""INSERT INTO present (itemstack) VALUES ($stackAsBlob)""" .updateAndReturnGeneratedKey .apply() - } } + } /** * 指定したPresentIDに対応するプレゼントを物理消去する。 @@ -60,15 +60,27 @@ class JdbcBackedPresentPersistence[F[_] : Sync] extends PresentPersistence[F, It } } - override def revoke(presentID: PresentID, players: Set[UUID]): F[Unit] = Sync[F].delay { - val scopeAsSQL = players.map(_.toString) - - DB.localTx { implicit session => - // https://discord.com/channels/237758724121427969/565935041574731807/824107651985834004 - sql"""DELETE FROM present_state WHERE present_id = $presentID AND uuid IN ($scopeAsSQL)""" - .execute() + override def revoke(presentID: PresentID, players: Set[UUID]): F[Unit] = { + val existence = DB.readOnly { implicit session => + sql"""SELECT present_state FROM present_state WHERE present_id = $presentID""" + .map(_ => ()) // avoid NoExtractor + .first() .apply() } + + import cats.Applicative + existence.fold(Applicative[F].pure(())) { _ => + Sync[F].delay { + val scopeAsSQL = players.map(_.toString) + + DB.localTx { implicit session => + // https://discord.com/channels/237758724121427969/565935041574731807/824107651985834004 + sql"""DELETE FROM present_state WHERE present_id = $presentID AND uuid IN ($scopeAsSQL)""" + .execute() + .apply() + } + } + } } override def markAsClaimed(presentId: PresentID, player: UUID): F[Unit] = Sync[F].delay { From be853edb4f53c9da141158714e68a5bf6f2b2e17 Mon Sep 17 00:00:00 2001 From: KisaragiEffective <kisaragi.effective@gmail.com> Date: Tue, 3 Aug 2021 17:44:55 +0900 Subject: [PATCH 36/73] [fix] fix #1132 --- .../present/bukkit/command/PresentCommand.scala | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/bukkit/command/PresentCommand.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/bukkit/command/PresentCommand.scala index adb658a801..bcaa2abb82 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/bukkit/command/PresentCommand.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/bukkit/command/PresentCommand.scala @@ -70,7 +70,7 @@ class PresentCommand(implicit val ioOnMainThread: OnMinecraftServerThread[IO]) { _ <- NonServerThreadContextShift[F].shift state <- persistence.fetchState(context.sender.getUniqueId) } yield { - val mes = state + val presents = state .toList // 配布対象外のプレゼントを除外 .filter { case (_, state) => state != PresentClaimingState.Unavailable } @@ -78,7 +78,17 @@ class PresentCommand(implicit val ioOnMainThread: OnMinecraftServerThread[IO]) { s"ID=$id: ${decoratePresentState(state)}" } .filter(_.nonEmpty) - MessageEffect(mes) + + val lines = if (presents.isEmpty) { + List("対象のプレゼントが存在しません") + } else { + List( + "対象のプレゼント一覧:", + "------------------" + ) ::: presents + } + + MessageEffect(lines) } eff.toIO From a0c1d39b76f075ef5e9cd61cbabce3556f02c04b Mon Sep 17 00:00:00 2001 From: KisaragiEffective <kisaragi.effective@gmail.com> Date: Tue, 3 Aug 2021 17:46:19 +0900 Subject: [PATCH 37/73] [fix] fix #1136 --- .../present/infrastructure/JdbcBackedPresentPersistence.scala | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/infrastructure/JdbcBackedPresentPersistence.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/infrastructure/JdbcBackedPresentPersistence.scala index 1878a26c67..de3c60a7cd 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/infrastructure/JdbcBackedPresentPersistence.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/infrastructure/JdbcBackedPresentPersistence.scala @@ -117,6 +117,7 @@ class JdbcBackedPresentPersistence[F[_] : Sync] extends PresentPersistence[F, It |SELECT present_id, claimed |FROM present_state |WHERE uuid = ${player.toString} AND present_id IN ($idSliceWithPagination) + |ORDER BY present_id """ .stripMargin .map(wrapResultForState) From 38a348bca7d97afed0926870345d5feae7134654 Mon Sep 17 00:00:00 2001 From: KisaragiEffective <kisaragi.effective@gmail.com> Date: Tue, 3 Aug 2021 19:31:29 +0900 Subject: [PATCH 38/73] [fix] fix #1133 --- .../bukkit/command/PresentCommand.scala | 13 ++++++------ .../domain/PaginationRejectReason.scala | 10 +++++++++ .../JdbcBackedPresentPersistence.scala | 21 ++++++++++++------- 3 files changed, 31 insertions(+), 13 deletions(-) create mode 100644 src/main/scala/com/github/unchama/seichiassist/subsystems/present/domain/PaginationRejectReason.scala diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/bukkit/command/PresentCommand.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/bukkit/command/PresentCommand.scala index bcaa2abb82..389722b98d 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/bukkit/command/PresentCommand.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/bukkit/command/PresentCommand.scala @@ -12,7 +12,7 @@ import com.github.unchama.minecraft.actions.OnMinecraftServerThread import com.github.unchama.seichiassist.commands.contextual.builder.BuilderTemplates.playerCommandBuilder import com.github.unchama.seichiassist.domain.actions.UuidToLastSeenName import com.github.unchama.seichiassist.subsystems.present.domain.OperationResult.DeleteResult -import com.github.unchama.seichiassist.subsystems.present.domain.{PresentClaimingState, PresentPersistence} +import com.github.unchama.seichiassist.subsystems.present.domain.{PaginationRejectReason, PresentClaimingState, PresentPersistence} import com.github.unchama.seichiassist.util.Util import com.github.unchama.targetedeffect.commandsender.MessageEffect import com.github.unchama.targetedeffect.{SequentialEffect, TargetedEffect} @@ -128,11 +128,12 @@ class PresentCommand(implicit val ioOnMainThread: OnMinecraftServerThread[IO]) { val eff = for { _ <- NonServerThreadContextShift[F].shift states <- persistence.fetchStateWithPagination(player, perPage, page) - messageLine = states - .map { case (id, state) => - s"ID=$id: ${decoratePresentState(state)}" - } - .toList + messageLine = states.fold({ + case PaginationRejectReason.TooLargePage(max) => + List(s"ページ数が大きすぎます。${max}ページ以下にしてください") + }, b => b.map { case (id, state) => + s"ID=$id: ${decoratePresentState(state)}" + }.toList) } yield { MessageEffect(messageLine) } diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/domain/PaginationRejectReason.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/domain/PaginationRejectReason.scala new file mode 100644 index 0000000000..8aa1df34e7 --- /dev/null +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/domain/PaginationRejectReason.scala @@ -0,0 +1,10 @@ +package com.github.unchama.seichiassist.subsystems.present.domain + +import eu.timepit.refined.api.Refined +import eu.timepit.refined.numeric.Positive + +sealed trait PaginationRejectReason + +object PaginationRejectReason { + case class TooLargePage(exceptedMax: Int Refined Positive) extends PaginationRejectReason +} \ No newline at end of file diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/infrastructure/JdbcBackedPresentPersistence.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/infrastructure/JdbcBackedPresentPersistence.scala index de3c60a7cd..05cda78aa0 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/infrastructure/JdbcBackedPresentPersistence.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/infrastructure/JdbcBackedPresentPersistence.scala @@ -111,13 +111,20 @@ class JdbcBackedPresentPersistence[F[_] : Sync] extends PresentPersistence[F, It for { idSliceWithPagination <- idSliceWithPagination(perPage, page) } yield { - // ページネーションはIDを列挙するときにすでに完了している - val associatedEntries = DB.readOnly { implicit session => - sql""" - |SELECT present_id, claimed - |FROM present_state - |WHERE uuid = ${player.toString} AND present_id IN ($idSliceWithPagination) - |ORDER BY present_id + if (idSliceWithPagination.isEmpty) { + for { + entries <- fetchState(player) + } yield { + Left(PaginationRejectReason.TooLargePage(Math.ceil(entries.size.toDouble / perPage).toInt)) + } + } else { + // ページネーションはIDを列挙するときにすでに完了している + val associatedEntries = DB.readOnly { implicit session => + sql""" + |SELECT present_id, claimed + |FROM present_state + |WHERE uuid = ${player.toString} AND present_id IN ($idSliceWithPagination) + |ORDER BY present_id """ .stripMargin .map(wrapResultForState) From f5207ce289f83557a0c204f9553215182574ddb5 Mon Sep 17 00:00:00 2001 From: KisaragiEffective <kisaragi.effective@gmail.com> Date: Tue, 3 Aug 2021 19:33:37 +0900 Subject: [PATCH 39/73] =?UTF-8?q?[update]=20=E3=83=89=E3=82=AD=E3=83=A5?= =?UTF-8?q?=E3=83=A1=E3=83=B3=E3=83=88=E5=8F=8A=E3=81=B3=E3=82=B9=E3=82=BF?= =?UTF-8?q?=E3=82=A4=E3=83=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../present/domain/PresentPersistence.scala | 26 ++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/domain/PresentPersistence.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/domain/PresentPersistence.scala index fb07d50e7b..3e3d7c646c 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/domain/PresentPersistence.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/domain/PresentPersistence.scala @@ -8,8 +8,8 @@ import java.util.UUID /** * プレゼントシステムに関する永続化のインターフェースを規定するトレイト。 - * 他で指定がない限り、以下の条件・制約を満たす。違反した時の動作は未定義である: - * - 引数で渡される`PresentID`は対応するプレゼントが存在し、一意でなければならない + * 他で指定がない限り、以下の条件および制約を満たす。違反した時の動作は未定義である: + * - 引数で渡される`PresentID`は対応するプレゼントが存在し、その多重度は * - 返り値としての`PresentID`は対応するプレゼントが存在する */ trait PresentPersistence[F[_], ItemStack] { @@ -31,8 +31,9 @@ trait PresentPersistence[F[_], ItemStack] { def delete(presentID: PresentID): F[DeleteResult] /** - * 指定したUUIDを持つプレイヤーに対して`presentID`で指定されたプレゼントを受け取ることができるようにする。 - * + * 指定したUUIDを持つプレイヤー群に対して`presentID`で指定されたプレゼントを受け取ることができるようにする。 + * このメソッドは同じプレイヤーとプレゼントIDで呼び出された場合はべき等である。また、すでに受取可能なプレイヤーが + * `players`の中に入っていた場合は、そのプレイヤーについての受取可能にする処理をスキップする。 * @param presentID 対象のプレゼントID * @param players 受け取ることができるようにするプレイヤーのUUID * @return 永続化層への書き込みを行う作用 @@ -40,7 +41,7 @@ trait PresentPersistence[F[_], ItemStack] { def grant(presentID: PresentID, players: Set[UUID]): F[Unit] /** - * 指定したUUIDを持つプレイヤーが`presentID`で指定されたプレゼントを受け取ることができないようにする。 + * 指定したUUIDを持つプレイヤー群が`presentID`で指定されたプレゼントを受け取ることができないようにする。 * * @param presentID 対象のプレゼントID * @param players 受け取ることができないようにするプレイヤーのUUID @@ -66,7 +67,8 @@ trait PresentPersistence[F[_], ItemStack] { /** * ページネーション付きでプレイヤーがプレゼントを受け取ることができるかどうか列挙する。 - * このときの出現順序は、[[PresentID]]が最も若いエントリから先に出現する。 + * このときのページネーションは、[[PresentID]]が最も若いエントリから先に出現するように行われるが、 + * ページネーションされたMap内での各エントリの出現順序は未規定である。 * * 例として以下のような状況を仮定する: * - 既知のPresentIDとItemStackのエントリ: `List((1, aaa), (3, ccc), (6, fff), (4, ddd), (5, eee), (2, bbb))` @@ -80,18 +82,24 @@ trait PresentPersistence[F[_], ItemStack] { * `Map(1 -> Claimed, 2 -> Claimed, 3 -> Claimed, 4 -> NotClaimed, 5 -> Unavailable)` * * 備考: - * - 実装によっては、[[fetchState]]などを呼び出して既知のエントリを全列挙する可能性がある。 + * - 実装によっては、[[fetchState]]などを呼び出して有効なエントリを全列挙する可能性がある。 * - このメソッドは一貫性のために[[fetchState]]のドキュメントにある制約を継承する。 + * - 最終インデックスが有効なプレゼントの総数を超えるとき、作用はLeftを返さなければならない。 + * - 最終インデックスが有効なプレゼントの総数を超えないとき、作用はRightを返さなければならない。 * * @param player 調べる対象のプレイヤー * @param perPage ページごとのエントリの数 * @param page ページ、1オリジン * @return ページネーションを計算して返す作用 */ - def fetchStateWithPagination(player: UUID, perPage: Int Refined Positive, page: Int Refined Positive): F[Map[PresentID, PresentClaimingState]] + def fetchStateWithPagination( + player: UUID, + perPage: Int Refined Positive, + page: Int Refined Positive + ): F[Either[PaginationRejectReason, Map[PresentID, PresentClaimingState]]] /** - * プレイヤーがプレゼントを受け取ることができるかどうか列挙する。このとき、計算されるMapは次の性質を持つ: + * プレイヤーがプレゼントを受け取ることができるかどうか列挙する。このとき、計算されるMapは次の性質を満たす: * * - すでに受け取ったプレゼントに対応するPresentIDに対して[[PresentClaimingState.Claimed]]がマッピングされる * - 受け取ることができるが、まだ受け取っていないプレゼントに対応するPresentIDに対して[[PresentClaimingState.NotClaimed]]がマッピングされる From 37e71f6943680313944410c27d7ed571d2fdd666 Mon Sep 17 00:00:00 2001 From: KisaragiEffective <kisaragi.effective@gmail.com> Date: Tue, 3 Aug 2021 19:34:02 +0900 Subject: [PATCH 40/73] [fix] fix #1134 --- .../JdbcBackedPresentPersistence.scala | 60 ++++++++++++------- 1 file changed, 40 insertions(+), 20 deletions(-) diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/infrastructure/JdbcBackedPresentPersistence.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/infrastructure/JdbcBackedPresentPersistence.scala index 05cda78aa0..47069e1f99 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/infrastructure/JdbcBackedPresentPersistence.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/infrastructure/JdbcBackedPresentPersistence.scala @@ -2,7 +2,7 @@ package com.github.unchama.seichiassist.subsystems.present.infrastructure import cats.effect.Sync import com.github.unchama.seichiassist.subsystems.present.domain.OperationResult.DeleteResult -import com.github.unchama.seichiassist.subsystems.present.domain.{PresentClaimingState, PresentPersistence} +import com.github.unchama.seichiassist.subsystems.present.domain.{PaginationRejectReason, PresentClaimingState, PresentPersistence} import eu.timepit.refined.api.Refined import eu.timepit.refined.auto._ import eu.timepit.refined.numeric.Positive @@ -46,17 +46,32 @@ class JdbcBackedPresentPersistence[F[_] : Sync] extends PresentPersistence[F, It } } - override def grant(presentID: PresentID, players: Set[UUID]): F[Unit] = Sync[F].delay { - import scala.collection.Seq.iterableFactory - - val initialValues = players - .map { uuid => Seq(presentID, uuid.toString, false) } - .toSeq - - DB.localTx { implicit session => - sql"""INSERT INTO present_state VALUES (?, ?, ?)""" - .batch(initialValues: _*) - .apply() + override def grant(presentID: PresentID, players: Set[UUID]): F[Unit] = { + import cats.implicits._ + for { + alreadyAddedPlayers <- Sync[F].delay { + DB.readOnly { implicit session => + sql"""SELECT uuid FROM present_state WHERE present_id = $presentID""" + .map(x => UUID.fromString(x.string("uuid"))) + .list() + .apply() + } + } + } yield { + import scala.collection.Seq.iterableFactory + + val initialValues = players + // すでに存在しているプレゼントIDとプレイヤーの組をINSERT + // すると整合性違反になるためフィルタ + .filterNot { alreadyAddedPlayers contains _ } + .map { uuid => Seq(presentID, uuid.toString, false) } + .toSeq + + DB.localTx { implicit session => + sql"""INSERT INTO present_state VALUES (?, ?, ?)""" + .batch(initialValues: _*) + .apply() + } } } @@ -106,7 +121,11 @@ class JdbcBackedPresentPersistence[F[_] : Sync] extends PresentPersistence[F, It } } - override def fetchStateWithPagination(player: UUID, perPage: Int Refined Positive, page: Int Refined Positive): F[Map[PresentID, PresentClaimingState]] = { + override def fetchStateWithPagination( + player: UUID, + perPage: Int Refined Positive, + page: Int Refined Positive + ): F[Either[PaginationRejectReason, Map[PresentID, PresentClaimingState]]] = { import cats.implicits._ for { idSliceWithPagination <- idSliceWithPagination(perPage, page) @@ -126,14 +145,15 @@ class JdbcBackedPresentPersistence[F[_] : Sync] extends PresentPersistence[F, It |WHERE uuid = ${player.toString} AND present_id IN ($idSliceWithPagination) |ORDER BY present_id """ - .stripMargin - .map(wrapResultForState) - .toList() - .apply() - .toMap - } + .stripMargin + .map(wrapResultForState) + .toList() + .apply() + .toMap + } - filledEntries(associatedEntries, idSliceWithPagination) + Right(filledEntries(associatedEntries, idSliceWithPagination)) + } } } From 915f338d8f0b87ed540284621a13d55e26e6ddbc Mon Sep 17 00:00:00 2001 From: KisaragiEffective <kisaragi.effective@gmail.com> Date: Tue, 3 Aug 2021 20:41:46 +0900 Subject: [PATCH 41/73] [fix] fix #1135 --- .../bukkit/command/PresentCommand.scala | 13 ++-- .../present/domain/GrantRejectReason.scala | 7 ++ .../domain/PaginationRejectReason.scala | 7 +- .../present/domain/PresentPersistence.scala | 2 +- .../JdbcBackedPresentPersistence.scala | 69 ++++++++++++------- 5 files changed, 63 insertions(+), 35 deletions(-) create mode 100644 src/main/scala/com/github/unchama/seichiassist/subsystems/present/domain/GrantRejectReason.scala diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/bukkit/command/PresentCommand.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/bukkit/command/PresentCommand.scala index 389722b98d..22b96ce74a 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/bukkit/command/PresentCommand.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/bukkit/command/PresentCommand.scala @@ -12,7 +12,7 @@ import com.github.unchama.minecraft.actions.OnMinecraftServerThread import com.github.unchama.seichiassist.commands.contextual.builder.BuilderTemplates.playerCommandBuilder import com.github.unchama.seichiassist.domain.actions.UuidToLastSeenName import com.github.unchama.seichiassist.subsystems.present.domain.OperationResult.DeleteResult -import com.github.unchama.seichiassist.subsystems.present.domain.{PaginationRejectReason, PresentClaimingState, PresentPersistence} +import com.github.unchama.seichiassist.subsystems.present.domain.{GrantRejectReason, PaginationRejectReason, PresentClaimingState, PresentPersistence} import com.github.unchama.seichiassist.util.Util import com.github.unchama.targetedeffect.commandsender.MessageEffect import com.github.unchama.targetedeffect.{SequentialEffect, TargetedEffect} @@ -323,12 +323,15 @@ class PresentCommand(implicit val ioOnMainThread: OnMinecraftServerThread[IO]) { globalUUID2Name.keys else globalUUID2Name.filter { case (_, name) => restArg.contains(name) }.keys - errorIfNobody = if (target.isEmpty) Some(MessageEffect("対象のプレイヤーが存在しません!")) else None - _ <- persistence.grant(presentId, target.toSet) + errorIfNobody = Option.when(target.isEmpty) { MessageEffect("対象のプレイヤーが存在しません!") } + grantError <- persistence.grant(presentId, target.toSet) } yield - errorIfNobody.getOrElse(MessageEffect( + errorIfNobody.getOrElse(grantError.map { + case GrantRejectReason.NoSuchPresentID => + MessageEffect("指定されたプレゼントIDは存在しません!") + }.getOrElse(MessageEffect( s"プレゼント(id: $presentId)を受け取れるプレイヤーを追加しました。" - )) + ))) eff.toIO } else { diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/domain/GrantRejectReason.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/domain/GrantRejectReason.scala new file mode 100644 index 0000000000..97a6dc14f1 --- /dev/null +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/domain/GrantRejectReason.scala @@ -0,0 +1,7 @@ +package com.github.unchama.seichiassist.subsystems.present.domain + +sealed trait GrantRejectReason + +object GrantRejectReason { + case object NoSuchPresentID extends GrantRejectReason +} \ No newline at end of file diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/domain/PaginationRejectReason.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/domain/PaginationRejectReason.scala index 8aa1df34e7..110faf28d6 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/domain/PaginationRejectReason.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/domain/PaginationRejectReason.scala @@ -1,10 +1,7 @@ package com.github.unchama.seichiassist.subsystems.present.domain -import eu.timepit.refined.api.Refined -import eu.timepit.refined.numeric.Positive - sealed trait PaginationRejectReason object PaginationRejectReason { - case class TooLargePage(exceptedMax: Int Refined Positive) extends PaginationRejectReason -} \ No newline at end of file + case class TooLargePage(exceptedMax: Long) extends PaginationRejectReason +} diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/domain/PresentPersistence.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/domain/PresentPersistence.scala index 3e3d7c646c..6314f95360 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/domain/PresentPersistence.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/domain/PresentPersistence.scala @@ -38,7 +38,7 @@ trait PresentPersistence[F[_], ItemStack] { * @param players 受け取ることができるようにするプレイヤーのUUID * @return 永続化層への書き込みを行う作用 */ - def grant(presentID: PresentID, players: Set[UUID]): F[Unit] + def grant(presentID: PresentID, players: Set[UUID]): F[Option[GrantRejectReason]] /** * 指定したUUIDを持つプレイヤー群が`presentID`で指定されたプレゼントを受け取ることができないようにする。 diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/infrastructure/JdbcBackedPresentPersistence.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/infrastructure/JdbcBackedPresentPersistence.scala index 47069e1f99..15f422bc21 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/infrastructure/JdbcBackedPresentPersistence.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/infrastructure/JdbcBackedPresentPersistence.scala @@ -1,8 +1,9 @@ package com.github.unchama.seichiassist.subsystems.present.infrastructure +import cats.Applicative import cats.effect.Sync import com.github.unchama.seichiassist.subsystems.present.domain.OperationResult.DeleteResult -import com.github.unchama.seichiassist.subsystems.present.domain.{PaginationRejectReason, PresentClaimingState, PresentPersistence} +import com.github.unchama.seichiassist.subsystems.present.domain.{GrantRejectReason, PaginationRejectReason, PresentClaimingState, PresentPersistence} import eu.timepit.refined.api.Refined import eu.timepit.refined.auto._ import eu.timepit.refined.numeric.Positive @@ -46,33 +47,47 @@ class JdbcBackedPresentPersistence[F[_] : Sync] extends PresentPersistence[F, It } } - override def grant(presentID: PresentID, players: Set[UUID]): F[Unit] = { + override def grant(presentID: PresentID, players: Set[UUID]): F[Option[GrantRejectReason]] = { import cats.implicits._ for { - alreadyAddedPlayers <- Sync[F].delay { + exists <- Sync[F].delay { DB.readOnly { implicit session => + sql"""SELECT present_id FROM present""" + .map(x => x.long("present_id")) + .list() + .apply() + }.contains(presentID) + } + } yield { + if (exists) { + val alreadyAddedPlayers = DB.readOnly { implicit session => sql"""SELECT uuid FROM present_state WHERE present_id = $presentID""" .map(x => UUID.fromString(x.string("uuid"))) .list() .apply() } - } - } yield { - import scala.collection.Seq.iterableFactory - - val initialValues = players - // すでに存在しているプレゼントIDとプレイヤーの組をINSERT - // すると整合性違反になるためフィルタ - .filterNot { alreadyAddedPlayers contains _ } - .map { uuid => Seq(presentID, uuid.toString, false) } - .toSeq - - DB.localTx { implicit session => - sql"""INSERT INTO present_state VALUES (?, ?, ?)""" - .batch(initialValues: _*) - .apply() + + import scala.collection.Seq.iterableFactory + + val initialValues = players + // すでに存在しているプレゼントIDとプレイヤーの組をINSERT + // すると整合性違反になるためフィルタ + .filterNot { alreadyAddedPlayers contains _ } + .map { uuid => Seq(presentID, uuid.toString, false) } + .toSeq + + DB.localTx { implicit session => + sql"""INSERT INTO present_state VALUES (?, ?, ?)""" + .batch(initialValues: _*) + .apply() + } + + None + } else { + Some(GrantRejectReason.NoSuchPresentID) } } + } override def revoke(presentID: PresentID, players: Set[UUID]): F[Unit] = { @@ -83,7 +98,6 @@ class JdbcBackedPresentPersistence[F[_] : Sync] extends PresentPersistence[F, It .apply() } - import cats.Applicative existence.fold(Applicative[F].pure(())) { _ => Sync[F].delay { val scopeAsSQL = players.map(_.toString) @@ -129,13 +143,10 @@ class JdbcBackedPresentPersistence[F[_] : Sync] extends PresentPersistence[F, It import cats.implicits._ for { idSliceWithPagination <- idSliceWithPagination(perPage, page) + count <- computeValidPresentCount } yield { if (idSliceWithPagination.isEmpty) { - for { - entries <- fetchState(player) - } yield { - Left(PaginationRejectReason.TooLargePage(Math.ceil(entries.size.toDouble / perPage).toInt)) - } + Left(PaginationRejectReason.TooLargePage(Math.ceil(count.toDouble / perPage).toLong)) } else { // ページネーションはIDを列挙するときにすでに完了している val associatedEntries = DB.readOnly { implicit session => @@ -213,4 +224,14 @@ class JdbcBackedPresentPersistence[F[_] : Sync] extends PresentPersistence[F, It val globalEntries = validGlobalId.map(id => (id, PresentClaimingState.Unavailable)).toMap globalEntries ++ knownState } + + private def computeValidPresentCount: F[Long] = Sync[F].delay { + DB.readOnly { implicit session => + sql"""SELECT COUNT(*) AS c FROM present""" + .map(rs => rs.long("c")) + .first() + .apply() + .get // safe + } + } } From fdfb0e732393f50bea8ca43223e0f24ca781743b Mon Sep 17 00:00:00 2001 From: Kisaragi <48310258+KisaragiEffective@users.noreply.github.com> Date: Tue, 3 Aug 2021 20:44:32 +0900 Subject: [PATCH 42/73] Update src/main/scala/com/github/unchama/seichiassist/subsystems/present/domain/PresentPersistence.scala --- .../subsystems/present/domain/PresentPersistence.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/domain/PresentPersistence.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/domain/PresentPersistence.scala index 6314f95360..5a7a9f1576 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/domain/PresentPersistence.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/domain/PresentPersistence.scala @@ -9,7 +9,7 @@ import java.util.UUID /** * プレゼントシステムに関する永続化のインターフェースを規定するトレイト。 * 他で指定がない限り、以下の条件および制約を満たす。違反した時の動作は未定義である: - * - 引数で渡される`PresentID`は対応するプレゼントが存在し、その多重度は + * - 引数で渡される`PresentID`は対応するプレゼントが存在し、その多重度は1対1である * - 返り値としての`PresentID`は対応するプレゼントが存在する */ trait PresentPersistence[F[_], ItemStack] { From e22050539b893738e9cb14f8e8ac80a1fd2504b6 Mon Sep 17 00:00:00 2001 From: KisaragiEffective <kisaragi.effective@gmail.com> Date: Tue, 3 Aug 2021 21:20:28 +0900 Subject: [PATCH 43/73] [fix] DeleteResult.NotFound --- .../subsystems/present/bukkit/command/PresentCommand.scala | 2 +- .../subsystems/present/domain/OperationResult.scala | 2 +- .../present/infrastructure/JdbcBackedPresentPersistence.scala | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/bukkit/command/PresentCommand.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/bukkit/command/PresentCommand.scala index 22b96ce74a..e669166752 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/bukkit/command/PresentCommand.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/bukkit/command/PresentCommand.scala @@ -269,7 +269,7 @@ class PresentCommand(implicit val ioOnMainThread: OnMinecraftServerThread[IO]) { } yield result match { case DeleteResult.Done => MessageEffect(s"IDが${presentId}のプレゼントの消去は正常に行われました。") - case DeleteResult.NotFount => + case DeleteResult.NotFound => MessageEffect(s"IDが${presentId}のプレゼントは存在しませんでした。") } diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/domain/OperationResult.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/domain/OperationResult.scala index ddb926eeea..ea10305e35 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/domain/OperationResult.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/domain/OperationResult.scala @@ -4,6 +4,6 @@ object OperationResult { sealed trait DeleteResult object DeleteResult { case object Done extends DeleteResult - case object NotFount extends DeleteResult + case object NotFound extends DeleteResult } } diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/infrastructure/JdbcBackedPresentPersistence.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/infrastructure/JdbcBackedPresentPersistence.scala index 15f422bc21..1c7971bc28 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/infrastructure/JdbcBackedPresentPersistence.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/infrastructure/JdbcBackedPresentPersistence.scala @@ -43,7 +43,7 @@ class JdbcBackedPresentPersistence[F[_] : Sync] extends PresentPersistence[F, It .update() .apply() - if (deletedRows == 1) DeleteResult.Done else DeleteResult.NotFount + if (deletedRows == 1) DeleteResult.Done else DeleteResult.NotFound } } From f3a7cdd41a008436d2f335401d78154fa00601cb Mon Sep 17 00:00:00 2001 From: Kory <6561358+kory33@users.noreply.github.com> Date: Wed, 4 Aug 2021 22:09:28 +0900 Subject: [PATCH 44/73] =?UTF-8?q?[fix]=20docker-compose.yml=E3=81=A7?= =?UTF-8?q?=E3=81=AEport=E3=82=92=E5=85=A8=E3=81=A6quote=E3=81=99=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker-compose.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index f27ab626d7..884372aa0e 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -21,8 +21,8 @@ services: volumes: - spigot_a:/spigot/ ports: - - 25566:25565 - - 7091:7091 + - "25566:25565" + - "7091:7091" environment: - JMX_PORT=7091 - JMX_BINDING=0.0.0.0 @@ -47,8 +47,8 @@ services: volumes: - spigot_b:/spigot/ ports: - - 25567:25565 - - 7092:7091 + - "25567:25565" + - "7092:7091" environment: - JMX_PORT=7091 - JMX_BINDING=0.0.0.0 @@ -68,7 +68,7 @@ services: context: . dockerfile: ./docker/bungeecord/Dockerfile ports: - - 25565:25577 + - "25565:25577" networks: - seichi environment: @@ -84,7 +84,7 @@ services: context: . dockerfile: ./docker/bungeecord/Dockerfile ports: - - 25564:25577 + - "25564:25577" networks: - seichi environment: @@ -108,7 +108,7 @@ services: networks: - seichi ports: - - 8080:80 + - "8080:80" depends_on: - db redis: @@ -131,4 +131,4 @@ services: volumes: - db-data:/var/lib/mysql ports: - - 3306:3306 + - "3306:3306" From 14f24b1de00d1a933eb2556552b5ca1fb8eeaa17 Mon Sep 17 00:00:00 2001 From: Kory <6561358+kory33@users.noreply.github.com> Date: Thu, 5 Aug 2021 14:38:36 +0900 Subject: [PATCH 45/73] =?UTF-8?q?[update]=20/present=20list=E3=81=AE?= =?UTF-8?q?=E8=AA=AC=E6=98=8E=E6=96=87=E3=82=92=E3=82=88=E3=82=8A=E6=AD=A3?= =?UTF-8?q?=E7=A2=BA=E3=81=AB=E3=81=99=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../subsystems/present/bukkit/command/PresentCommand.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/bukkit/command/PresentCommand.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/bukkit/command/PresentCommand.scala index adb658a801..eb89b9016a 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/bukkit/command/PresentCommand.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/bukkit/command/PresentCommand.scala @@ -88,8 +88,8 @@ class PresentCommand(implicit val ioOnMainThread: OnMinecraftServerThread[IO]) { object ListSubCommand { val help: EchoExecutor = EchoExecutor(MessageEffect(List( - "/present list", - " 全てのプレゼントを表示します", + "/present list <ページ数>", + " 全てのプレゼントをページに分けて表示します", ))) /** From de43ee72984b0f68e007ea1be6d19d1bb62a6fda Mon Sep 17 00:00:00 2001 From: KisaragiEffective <kisaragi.effective@gmail.com> Date: Thu, 5 Aug 2021 19:14:38 +0900 Subject: [PATCH 46/73] [update] apply review --- .../bukkit/command/PresentCommand.scala | 20 +++-- .../present/domain/PresentPersistence.scala | 12 +-- .../present/domain/RevokeWarning.scala | 8 ++ .../JdbcBackedPresentPersistence.scala | 84 ++++++++++--------- 4 files changed, 70 insertions(+), 54 deletions(-) create mode 100644 src/main/scala/com/github/unchama/seichiassist/subsystems/present/domain/RevokeWarning.scala diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/bukkit/command/PresentCommand.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/bukkit/command/PresentCommand.scala index e669166752..ecd834367f 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/bukkit/command/PresentCommand.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/bukkit/command/PresentCommand.scala @@ -12,7 +12,7 @@ import com.github.unchama.minecraft.actions.OnMinecraftServerThread import com.github.unchama.seichiassist.commands.contextual.builder.BuilderTemplates.playerCommandBuilder import com.github.unchama.seichiassist.domain.actions.UuidToLastSeenName import com.github.unchama.seichiassist.subsystems.present.domain.OperationResult.DeleteResult -import com.github.unchama.seichiassist.subsystems.present.domain.{GrantRejectReason, PaginationRejectReason, PresentClaimingState, PresentPersistence} +import com.github.unchama.seichiassist.subsystems.present.domain.{GrantRejectReason, PaginationRejectReason, PresentClaimingState, PresentPersistence, RevokeWarning} import com.github.unchama.seichiassist.util.Util import com.github.unchama.targetedeffect.commandsender.MessageEffect import com.github.unchama.targetedeffect.{SequentialEffect, TargetedEffect} @@ -83,8 +83,7 @@ class PresentCommand(implicit val ioOnMainThread: OnMinecraftServerThread[IO]) { List("対象のプレゼントが存在しません") } else { List( - "対象のプレゼント一覧:", - "------------------" + s"${ChatColor.GRAY}${ChatColor.UNDERLINE}対象のプレゼント一覧:${ChatColor.RESET}", ) ::: presents } @@ -383,11 +382,18 @@ class PresentCommand(implicit val ioOnMainThread: OnMinecraftServerThread[IO]) { else globalUUID2Name.filter { case (_, name) => restArg.contains(name) }.keys errorIfNobody = if (target.isEmpty) Some(MessageEffect("対象のプレイヤーが存在しません!")) else None - _ <- persistence.revoke(presentId, target.toSet) + warning <- persistence.revoke(presentId, target.toSet) } yield { - errorIfNobody.getOrElse(MessageEffect( - s"プレゼント(id: $presentId)を受け取れるプレイヤーを削除しました。" - )) + errorIfNobody.getOrElse { + warning.map { + case RevokeWarning.NoSuchPresentID => MessageEffect("そのようなプレゼントIDはありません!") + case RevokeWarning.NoPlayers => MessageEffect("対象となるプレイヤーが存在しません!") + }.getOrElse { + MessageEffect( + s"プレゼント(id: $presentId)を受け取れるプレイヤーを削除しました。" + ) + } + } } eff.toIO } else { diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/domain/PresentPersistence.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/domain/PresentPersistence.scala index 5a7a9f1576..5d05d0f985 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/domain/PresentPersistence.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/domain/PresentPersistence.scala @@ -47,7 +47,7 @@ trait PresentPersistence[F[_], ItemStack] { * @param players 受け取ることができないようにするプレイヤーのUUID * @return 永続化層への書き込みを行う作用 */ - def revoke(presentID: PresentID, players: Set[UUID]): F[Unit] + def revoke(presentID: PresentID, players: Set[UUID]): F[Option[RevokeWarning]] /** * 永続化層でプレゼントを受け取ったことにする。 @@ -67,8 +67,8 @@ trait PresentPersistence[F[_], ItemStack] { /** * ページネーション付きでプレイヤーがプレゼントを受け取ることができるかどうか列挙する。 - * このときのページネーションは、[[PresentID]]が最も若いエントリから先に出現するように行われるが、 - * ページネーションされたMap内での各エントリの出現順序は未規定である。 + * このときのページネーションは、[[PresentID]]が最も若いエントリから先に出現するように行われる。 + * また、ページネーションされたListの中での出現順序も、[[PresentID]]が最も若いエントリから先に出現する。 * * 例として以下のような状況を仮定する: * - 既知のPresentIDとItemStackのエントリ: `List((1, aaa), (3, ccc), (6, fff), (4, ddd), (5, eee), (2, bbb))` @@ -79,7 +79,7 @@ trait PresentPersistence[F[_], ItemStack] { * * この時 `pp.mappingWithPagination(A, 1, 5)` を呼び出すと、作用の中で計算される結果は次のとおりになる: * - * `Map(1 -> Claimed, 2 -> Claimed, 3 -> Claimed, 4 -> NotClaimed, 5 -> Unavailable)` + * `List(1 -> Claimed, 2 -> Claimed, 3 -> Claimed, 4 -> NotClaimed, 5 -> Unavailable)` * * 備考: * - 実装によっては、[[fetchState]]などを呼び出して有効なエントリを全列挙する可能性がある。 @@ -96,7 +96,7 @@ trait PresentPersistence[F[_], ItemStack] { player: UUID, perPage: Int Refined Positive, page: Int Refined Positive - ): F[Either[PaginationRejectReason, Map[PresentID, PresentClaimingState]]] + ): F[Either[PaginationRejectReason, List[(PresentID, PresentClaimingState)]]] /** * プレイヤーがプレゼントを受け取ることができるかどうか列挙する。このとき、計算されるMapは次の性質を満たす: @@ -112,7 +112,7 @@ trait PresentPersistence[F[_], ItemStack] { def fetchState(player: UUID): F[Map[PresentID, PresentClaimingState]] /** - * 指定したプレゼントIDからプレゼントを引き出す。 + * 指定したプレゼントIDでプレゼントを検索する。 * * @param presentID プレゼントID * @return 存在する場合は`Some[ItemStack]`、存在しない場合は`None`を返す作用 diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/domain/RevokeWarning.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/domain/RevokeWarning.scala new file mode 100644 index 0000000000..a724c97ac1 --- /dev/null +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/domain/RevokeWarning.scala @@ -0,0 +1,8 @@ +package com.github.unchama.seichiassist.subsystems.present.domain + +sealed trait RevokeWarning + +object RevokeWarning { + case object NoSuchPresentID extends RevokeWarning + case object NoPlayers extends RevokeWarning +} \ No newline at end of file diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/infrastructure/JdbcBackedPresentPersistence.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/infrastructure/JdbcBackedPresentPersistence.scala index 1c7971bc28..8dcf41ab8f 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/infrastructure/JdbcBackedPresentPersistence.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/infrastructure/JdbcBackedPresentPersistence.scala @@ -3,7 +3,7 @@ package com.github.unchama.seichiassist.subsystems.present.infrastructure import cats.Applicative import cats.effect.Sync import com.github.unchama.seichiassist.subsystems.present.domain.OperationResult.DeleteResult -import com.github.unchama.seichiassist.subsystems.present.domain.{GrantRejectReason, PaginationRejectReason, PresentClaimingState, PresentPersistence} +import com.github.unchama.seichiassist.subsystems.present.domain.{GrantRejectReason, PaginationRejectReason, PresentClaimingState, PresentPersistence, RevokeWarning} import eu.timepit.refined.api.Refined import eu.timepit.refined.auto._ import eu.timepit.refined.numeric.Positive @@ -49,7 +49,7 @@ class JdbcBackedPresentPersistence[F[_] : Sync] extends PresentPersistence[F, It override def grant(presentID: PresentID, players: Set[UUID]): F[Option[GrantRejectReason]] = { import cats.implicits._ - for { + val program = for { exists <- Sync[F].delay { DB.readOnly { implicit session => sql"""SELECT present_id FROM present""" @@ -60,54 +60,58 @@ class JdbcBackedPresentPersistence[F[_] : Sync] extends PresentPersistence[F, It } } yield { if (exists) { - val alreadyAddedPlayers = DB.readOnly { implicit session => - sql"""SELECT uuid FROM present_state WHERE present_id = $presentID""" - .map(x => UUID.fromString(x.string("uuid"))) - .list() - .apply() - } - - import scala.collection.Seq.iterableFactory - - val initialValues = players - // すでに存在しているプレゼントIDとプレイヤーの組をINSERT - // すると整合性違反になるためフィルタ - .filterNot { alreadyAddedPlayers contains _ } - .map { uuid => Seq(presentID, uuid.toString, false) } - .toSeq - - DB.localTx { implicit session => - sql"""INSERT INTO present_state VALUES (?, ?, ?)""" - .batch(initialValues: _*) - .apply() + Sync[F].delay { + val alreadyAddedPlayers = DB.readOnly { implicit session => + sql"""SELECT uuid FROM present_state WHERE present_id = $presentID""" + .map(x => UUID.fromString(x.string("uuid"))) + .list() + .apply() + } + + import scala.collection.Seq.iterableFactory + + val initialValues = players + // すでに存在しているプレゼントIDとプレイヤーの組をINSERT + // すると整合性違反になるためフィルタ + .filterNot { alreadyAddedPlayers contains _ } + .map { uuid => Seq(presentID, uuid.toString, false) } + .toSeq + + DB.localTx { implicit session => + sql""" + INSERT INTO present_state VALUES (?, ?, ?) + ON DUPLICATE KEY UPDATE present_id=present_id + """ + .batch(initialValues: _*) + .apply() + } + + None } - - None } else { - Some(GrantRejectReason.NoSuchPresentID) + // 型推論 + Applicative[F].pure(Some(GrantRejectReason.NoSuchPresentID: GrantRejectReason)) } } + program.flatten } - override def revoke(presentID: PresentID, players: Set[UUID]): F[Unit] = { - val existence = DB.readOnly { implicit session => - sql"""SELECT present_state FROM present_state WHERE present_id = $presentID""" - .map(_ => ()) // avoid NoExtractor - .first() - .apply() - } - - existence.fold(Applicative[F].pure(())) { _ => + override def revoke(presentID: PresentID, players: Set[UUID]): F[Option[RevokeWarning]] = { + if (players.isEmpty) { + Applicative[F].pure(Some(RevokeWarning.NoPlayers)) + } else { Sync[F].delay { val scopeAsSQL = players.map(_.toString) - DB.localTx { implicit session => + val deleteCount = DB.localTx { implicit session => // https://discord.com/channels/237758724121427969/565935041574731807/824107651985834004 sql"""DELETE FROM present_state WHERE present_id = $presentID AND uuid IN ($scopeAsSQL)""" - .execute() + .update() .apply() } + + Option.when(deleteCount == 0) { RevokeWarning.NoSuchPresentID } } } } @@ -139,7 +143,7 @@ class JdbcBackedPresentPersistence[F[_] : Sync] extends PresentPersistence[F, It player: UUID, perPage: Int Refined Positive, page: Int Refined Positive - ): F[Either[PaginationRejectReason, Map[PresentID, PresentClaimingState]]] = { + ): F[Either[PaginationRejectReason, List[(PresentID, PresentClaimingState)]]] = { import cats.implicits._ for { idSliceWithPagination <- idSliceWithPagination(perPage, page) @@ -160,7 +164,6 @@ class JdbcBackedPresentPersistence[F[_] : Sync] extends PresentPersistence[F, It .map(wrapResultForState) .toList() .apply() - .toMap } Right(filledEntries(associatedEntries, idSliceWithPagination)) @@ -179,7 +182,6 @@ class JdbcBackedPresentPersistence[F[_] : Sync] extends PresentPersistence[F, It .map(wrapResultForState) .list() .apply() - .toMap } filledEntries(associatedEntries, validPresentIDs) @@ -220,7 +222,7 @@ class JdbcBackedPresentPersistence[F[_] : Sync] extends PresentPersistence[F, It ItemStackBlobProxy.blobToItemStack(rs.string("itemstack")) } - private def filledEntries(knownState: Map[PresentID, PresentClaimingState], validGlobalId: Iterable[PresentID]) = { + private def filledEntries(knownState: List[(PresentID, PresentClaimingState)], validGlobalId: Iterable[PresentID]) = { val globalEntries = validGlobalId.map(id => (id, PresentClaimingState.Unavailable)).toMap globalEntries ++ knownState } @@ -228,7 +230,7 @@ class JdbcBackedPresentPersistence[F[_] : Sync] extends PresentPersistence[F, It private def computeValidPresentCount: F[Long] = Sync[F].delay { DB.readOnly { implicit session => sql"""SELECT COUNT(*) AS c FROM present""" - .map(rs => rs.long("c")) + .map(_.long("c")) .first() .apply() .get // safe From 8b6e2f0f297d625889cfabfa3eb8c41510c255c8 Mon Sep 17 00:00:00 2001 From: KisaragiEffective <kisaragi.effective@gmail.com> Date: Fri, 6 Aug 2021 18:00:25 +0900 Subject: [PATCH 47/73] [fix] compile error --- .../JdbcBackedPresentPersistence.scala | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/infrastructure/JdbcBackedPresentPersistence.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/infrastructure/JdbcBackedPresentPersistence.scala index 8dcf41ab8f..d43786098a 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/infrastructure/JdbcBackedPresentPersistence.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/infrastructure/JdbcBackedPresentPersistence.scala @@ -86,11 +86,12 @@ class JdbcBackedPresentPersistence[F[_] : Sync] extends PresentPersistence[F, It .apply() } - None + // 型推論 + None: Option[GrantRejectReason] } } else { // 型推論 - Applicative[F].pure(Some(GrantRejectReason.NoSuchPresentID: GrantRejectReason)) + Applicative[F].pure(Some(GrantRejectReason.NoSuchPresentID: GrantRejectReason): Option[GrantRejectReason]) } } @@ -166,7 +167,7 @@ class JdbcBackedPresentPersistence[F[_] : Sync] extends PresentPersistence[F, It .apply() } - Right(filledEntries(associatedEntries, idSliceWithPagination)) + Right(filledEntries(associatedEntries, idSliceWithPagination).toList) } } } @@ -184,7 +185,7 @@ class JdbcBackedPresentPersistence[F[_] : Sync] extends PresentPersistence[F, It .apply() } - filledEntries(associatedEntries, validPresentIDs) + filledEntries(associatedEntries, validPresentIDs).toMap } } @@ -222,9 +223,9 @@ class JdbcBackedPresentPersistence[F[_] : Sync] extends PresentPersistence[F, It ItemStackBlobProxy.blobToItemStack(rs.string("itemstack")) } - private def filledEntries(knownState: List[(PresentID, PresentClaimingState)], validGlobalId: Iterable[PresentID]) = { - val globalEntries = validGlobalId.map(id => (id, PresentClaimingState.Unavailable)).toMap - globalEntries ++ knownState + private def filledEntries(knownState: List[(PresentID, PresentClaimingState)], validGlobalId: Iterable[PresentID]): Iterable[(PresentID, PresentClaimingState)] = { + val globalEntries = validGlobalId.map(id => (id, PresentClaimingState.Unavailable)) + (globalEntries ++ knownState) } private def computeValidPresentCount: F[Long] = Sync[F].delay { From 95f68c286cebf9408d77dab0136a37ed9dcf7de2 Mon Sep 17 00:00:00 2001 From: KisaragiEffective <kisaragi.effective@gmail.com> Date: Fri, 6 Aug 2021 21:19:57 +0900 Subject: [PATCH 48/73] [update] apply review (upsert) --- .../infrastructure/JdbcBackedPresentPersistence.scala | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/infrastructure/JdbcBackedPresentPersistence.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/infrastructure/JdbcBackedPresentPersistence.scala index d43786098a..f6d8160f26 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/present/infrastructure/JdbcBackedPresentPersistence.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/present/infrastructure/JdbcBackedPresentPersistence.scala @@ -71,16 +71,14 @@ class JdbcBackedPresentPersistence[F[_] : Sync] extends PresentPersistence[F, It import scala.collection.Seq.iterableFactory val initialValues = players - // すでに存在しているプレゼントIDとプレイヤーの組をINSERT - // すると整合性違反になるためフィルタ - .filterNot { alreadyAddedPlayers contains _ } .map { uuid => Seq(presentID, uuid.toString, false) } .toSeq DB.localTx { implicit session => + // upsert - これによってfilterなしで整合性違反を起こすことはなくなる sql""" INSERT INTO present_state VALUES (?, ?, ?) - ON DUPLICATE KEY UPDATE present_id=present_id + ON DUPLICATE KEY UPDATE present_id=present_id, uuid=uuid """ .batch(initialValues: _*) .apply() From 3a44230b155e19c823ff99c13e51f0bfd69e9828 Mon Sep 17 00:00:00 2001 From: KisaragiEffective <kisaragi.effective@gmail.com> Date: Sat, 7 Aug 2021 14:46:17 +0900 Subject: [PATCH 49/73] [update] close #1126 --- .../github/unchama/seichiassist/listener/EntityListener.scala | 1 + .../unchama/seichiassist/listener/PlayerBlockBreakListener.scala | 1 + 2 files changed, 2 insertions(+) diff --git a/src/main/scala/com/github/unchama/seichiassist/listener/EntityListener.scala b/src/main/scala/com/github/unchama/seichiassist/listener/EntityListener.scala index c54a52fcee..0e90dc4945 100644 --- a/src/main/scala/com/github/unchama/seichiassist/listener/EntityListener.scala +++ b/src/main/scala/com/github/unchama/seichiassist/listener/EntityListener.scala @@ -48,6 +48,7 @@ class EntityListener(implicit effectEnvironment: EffectEnvironment, //整地ワールドでは重力値によるキャンセル判定を行う(スキル判定より先に判定させること) if (BreakUtil.getGravity(player, block, isAssault = false) > 3) { + player.playSound(player.getLocation, Sound.BLOCK_ANVIL_FALL, 0.0F, -1.0F) player.sendMessage(ChatColor.RED + "整地ワールドでは必ず上から掘ってください。") return } 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 adcfd64d45..8d5f9d80c1 100644 --- a/src/main/scala/com/github/unchama/seichiassist/listener/PlayerBlockBreakListener.scala +++ b/src/main/scala/com/github/unchama/seichiassist/listener/PlayerBlockBreakListener.scala @@ -52,6 +52,7 @@ class PlayerBlockBreakListener(implicit effectEnvironment: EffectEnvironment, if (!MaterialSets.gravityMaterials.contains(block.getType) && !MaterialSets.cancelledMaterials.contains(block.getType) && gravity > 15) { + player.playSound(player.getLocation, Sound.BLOCK_ANVIL_FALL, 0.0F, -1.0F) player.sendMessage(s"${RED}整地ワールドでは必ず上から掘ってください。") event.setCancelled(true) return From be337e7b9f4e8461065e2c57d7661f4ce98621ba Mon Sep 17 00:00:00 2001 From: Lucky <lucky3028@users.noreply.github.com> Date: Mon, 9 Aug 2021 15:11:32 +0900 Subject: [PATCH 50/73] =?UTF-8?q?[Remove]=20ItemStack=E3=81=8CTITAN?= =?UTF-8?q?=E3=81=8B=E3=81=A9=E3=81=86=E3=81=8B=E5=88=A4=E5=AE=9A=E3=81=99?= =?UTF-8?q?=E3=82=8B=E9=96=A2=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../scala/com/github/unchama/seichiassist/util/Util.scala | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/main/scala/com/github/unchama/seichiassist/util/Util.scala b/src/main/scala/com/github/unchama/seichiassist/util/Util.scala index f95751edcd..250f496fe9 100644 --- a/src/main/scala/com/github/unchama/seichiassist/util/Util.scala +++ b/src/main/scala/com/github/unchama/seichiassist/util/Util.scala @@ -495,11 +495,6 @@ object Util { Some(block.getDrops.asScala.head.tap(_.setDurability(SkullType.PLAYER.ordinal.toShort))) } - def isLimitedTitanItem(itemstack: ItemStack): Boolean = { - itemstack.getType == Material.DIAMOND_AXE && - isContainedInLore(itemstack, "特別なタイタンをあなたに♡") - } - /** * 指定された`String`が指定された[[ItemStack]]のloreに含まれているかどうか * @@ -511,7 +506,6 @@ object Util { if (!itemStack.hasItemMeta || !itemStack.getItemMeta.hasLore) false else loreIndexOf(itemStack.getItemMeta.getLore.asScala.toList, sentence) >= 0 - /** * loreを捜査して、要素の中に`find`が含まれているかを調べる。 * From 6483ddccc795d2150077a0b44493642ef4f634e2 Mon Sep 17 00:00:00 2001 From: Lucky <lucky3028@users.noreply.github.com> Date: Mon, 9 Aug 2021 15:11:53 +0900 Subject: [PATCH 51/73] =?UTF-8?q?[Remove]=20=E4=BF=AE=E7=B9=95=E3=83=A1?= =?UTF-8?q?=E3=83=8B=E3=83=A5=E3=83=BC=E3=83=9C=E3=82=BF=E3=83=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../github/unchama/seichiassist/menus/stickmenu/SecondPage.scala | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/scala/com/github/unchama/seichiassist/menus/stickmenu/SecondPage.scala b/src/main/scala/com/github/unchama/seichiassist/menus/stickmenu/SecondPage.scala index e50aad1c45..1538c558fd 100644 --- a/src/main/scala/com/github/unchama/seichiassist/menus/stickmenu/SecondPage.scala +++ b/src/main/scala/com/github/unchama/seichiassist/menus/stickmenu/SecondPage.scala @@ -57,7 +57,6 @@ object SecondPage extends Menu { ChestSlotRef(0, 8) -> hubCommandButton, ChestSlotRef(3, 0) -> CommonButtons.openStickMenu, ChestSlotRef(3, 3) -> recycleBinButton, - ChestSlotRef(3, 7) -> titanConversionButton, ChestSlotRef(3, 8) -> appleConversionButton ) From 84461f31e6a42bdad1ed02ffd48c04fbbd6718a1 Mon Sep 17 00:00:00 2001 From: Lucky <lucky3028@users.noreply.github.com> Date: Mon, 9 Aug 2021 15:12:10 +0900 Subject: [PATCH 52/73] =?UTF-8?q?[Remove]=20=E4=BF=AE=E7=B9=95=E3=83=A1?= =?UTF-8?q?=E3=83=8B=E3=83=A5=E3=83=BC=E3=81=8C=E9=96=89=E3=81=98=E3=82=89?= =?UTF-8?q?=E3=82=8C=E3=81=9F=E6=99=82=E3=81=AE=E5=87=A6=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../listener/PlayerInventoryListener.scala | 41 ------------------- 1 file changed, 41 deletions(-) diff --git a/src/main/scala/com/github/unchama/seichiassist/listener/PlayerInventoryListener.scala b/src/main/scala/com/github/unchama/seichiassist/listener/PlayerInventoryListener.scala index 08f8f927f4..c5dcd9b25c 100644 --- a/src/main/scala/com/github/unchama/seichiassist/listener/PlayerInventoryListener.scala +++ b/src/main/scala/com/github/unchama/seichiassist/listener/PlayerInventoryListener.scala @@ -364,47 +364,6 @@ class PlayerInventoryListener(implicit effectEnvironment: EffectEnvironment, } - @EventHandler - def onTitanRepairEvent(event: InventoryCloseEvent): Unit = { - val player = event.getPlayer.asInstanceOf[Player] - //エラー分岐 - val inventory = event.getInventory - - //インベントリサイズが36でない時終了 - if (inventory.row != 4) { - return - } - if (inventory.getTitle == GOLD.toString + "" + BOLD + "修繕したい限定タイタンを入れてネ") { - //インベントリの中身を取得 - val item = inventory.getContents - - var count = 0 - //for文で1個ずつ対象アイテムか見る - //インベントリを一個ずつ見ていくfor文 - for (m <- item) { - if (m != null) { - if (m.getItemMeta.hasLore) { - if (Util.isLimitedTitanItem(m)) { - m.setDurability(1.toShort) - count += 1 - } - } - - if (!Util.isPlayerInventoryFull(player)) { - Util.addItem(player, m) - } else { - Util.dropItem(player, m) - } - } - } - if (count < 1) { - player.sendMessage(GREEN.toString + "限定タイタンを認識しませんでした。すべてのアイテムを返却します") - } else { - player.sendMessage(GREEN.toString + "限定タイタンを" + count + "個認識し、修繕しました。") - } - } - } - //投票ptメニュー @EventHandler def onVotingMenuEvent(event: InventoryClickEvent): Unit = { From ebb8c8ca87c064a540ec2346dd0926453bff53ac Mon Sep 17 00:00:00 2001 From: Kisaragi <48310258+KisaragiEffective@users.noreply.github.com> Date: Mon, 9 Aug 2021 22:56:42 +0900 Subject: [PATCH 53/73] =?UTF-8?q?[update]=20=E3=83=87=E3=83=90=E3=83=83?= =?UTF-8?q?=E3=82=B0=E9=AF=96=E3=81=AE=E3=82=A2=E3=83=89=E3=83=AC=E3=82=B9?= =?UTF-8?q?=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e39e8c3565..92b0a3980e 100644 --- a/README.md +++ b/README.md @@ -87,7 +87,7 @@ masterブランチは本番環境に反映されます。 ## AutoRelease - developブランチが更新されると、そのコードを基に実行用jarがビルドされ、デバッグ環境に配布されます。デバッグ環境はjarの配布を検知すると自動で再起動し、最新のjarを使用して稼働します。 - - デバッグ環境へは、Minecraft Java Editionで`play.seichi.click`に接続し、`T`キーでチャットを開き、`/server deb112`と入力して`Enter`を押すとアクセスできます。 + - デバッグ環境へは、Minecraft Java Editionで`play-debug.seichi.click`に接続し、`T`キーでチャットを開き、`/server deb112`と入力して`Enter`を押すとアクセスできます。 - masterブランチが更新されると、そのコードを基に実行用jarがビルドされ、本番環境に配布されます。本番環境は翌再起動時に自動で最新のjarを取り込んで稼働します。 - jar以外の自動リリースは未対応です(config.ymlなど)。運営チームへ更新を依頼する必要があります。 - 各サーバーや環境で共通で構わないパラメータはconfig.ymlを読まず、コードへの直接実装を推奨します。 From 54cb867eda0a9e0bf23b888bbcd270810daa08bd Mon Sep 17 00:00:00 2001 From: KisaragiEffective <kisaragi.effective@gmail.com> Date: Wed, 25 Aug 2021 22:28:55 +0900 Subject: [PATCH 54/73] =?UTF-8?q?[update]=20=E5=BB=BA=E7=AF=89=E3=82=B5?= =?UTF-8?q?=E3=83=BC=E3=83=90=E3=83=BC=E3=81=AF=E3=82=82=E3=81=86=E5=AD=98?= =?UTF-8?q?=E5=9C=A8=E3=81=97=E3=81=AA=E3=81=84=E3=81=AE=E3=81=A7=E3=82=B5?= =?UTF-8?q?=E3=83=BC=E3=83=90=E3=83=BC=E9=96=93=E7=A7=BB=E5=8B=95=E3=83=9C?= =?UTF-8?q?=E3=82=BF=E3=83=B3=E3=81=8B=E3=82=89=E8=A1=A8=E8=A8=98=E3=82=92?= =?UTF-8?q?=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../github/unchama/seichiassist/menus/stickmenu/FirstPage.scala | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/scala/com/github/unchama/seichiassist/menus/stickmenu/FirstPage.scala b/src/main/scala/com/github/unchama/seichiassist/menus/stickmenu/FirstPage.scala index a4dea4d0c9..4310efca48 100644 --- a/src/main/scala/com/github/unchama/seichiassist/menus/stickmenu/FirstPage.scala +++ b/src/main/scala/com/github/unchama/seichiassist/menus/stickmenu/FirstPage.scala @@ -549,7 +549,6 @@ object FirstPage extends Menu { def teleportServerButton(implicit ioCanOpenServerSwitchMenu: IO CanOpen ServerSwitchMenu.type): Button = { val buttonLore = List( s"$GRAY・各サバイバルサーバー", - s"$GRAY・建築サーバー", s"$GRAY・公共施設サーバー", s"${GRAY}間を移動する時に使います", s"$DARK_RED${UNDERLINE}クリックして開く" From 6a429658f547be353fc3a7273d000e2ccb225033 Mon Sep 17 00:00:00 2001 From: KisaragiEffective <kisaragi.effective@gmail.com> Date: Wed, 25 Aug 2021 22:55:27 +0900 Subject: [PATCH 55/73] =?UTF-8?q?[fix]=20Y5=E4=BA=8C=E6=AE=B5=E3=82=B9?= =?UTF-8?q?=E3=83=A9=E3=83=96=E3=81=AEY=E5=BA=A7=E6=A8=99=E5=88=A4?= =?UTF-8?q?=E5=AE=9A=E3=81=8C=E6=8A=9C=E3=81=91=E3=81=A6=E3=81=84=E3=81=9F?= =?UTF-8?q?=E3=81=9F=E3=82=81=E8=BF=BD=E5=8A=A0=20fix=20#1118?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../unchama/seichiassist/listener/Y5DoubleSlabCanceller.scala | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/scala/com/github/unchama/seichiassist/listener/Y5DoubleSlabCanceller.scala b/src/main/scala/com/github/unchama/seichiassist/listener/Y5DoubleSlabCanceller.scala index 16bb2c7256..4d9a6a493f 100644 --- a/src/main/scala/com/github/unchama/seichiassist/listener/Y5DoubleSlabCanceller.scala +++ b/src/main/scala/com/github/unchama/seichiassist/listener/Y5DoubleSlabCanceller.scala @@ -12,6 +12,7 @@ object Y5DoubleSlabCanceller extends Listener { * - プレイヤーが手に持っているブロックが焼き石のハーフブロックである * - 対象座標の改変後ブロックが焼き石の二段重ねハーフブロックである * - 対象座標が整地ワールドを指している + * - 対象ブロックのY座標が5である * @see https://github.com/GiganticMinecraft/SeichiAssist/issues/775 * @param event 対象イベント */ @@ -23,6 +24,7 @@ object Y5DoubleSlabCanceller extends Listener { if (event.getBlockPlaced.getType ne Material.DOUBLE_STEP) return if (event.getBlockPlaced.getData != 0) return if (!event.getBlockPlaced.getWorld.isSeichi) return + if (event.getBlockPlaced.getY != 5) return event.setCancelled(true) event.getPlayer.sendMessage("Y5のハーフブロックを二段重ねにすることはできません。") } From d7c001110bf4e24f0dab308498f437c55171daa3 Mon Sep 17 00:00:00 2001 From: KisaragiEffective <kisaragi.effective@gmail.com> Date: Wed, 25 Aug 2021 23:01:48 +0900 Subject: [PATCH 56/73] [fix] fix #1138 --- build.sbt | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/build.sbt b/build.sbt index a6401c3cba..6a370c0850 100644 --- a/build.sbt +++ b/build.sbt @@ -81,8 +81,8 @@ val dependenciesToEmbed = Seq( addCompilerPlugin("org.typelevel" %% "kind-projector" % "0.11.0" cross CrossVersion.full) // localDependenciesはprovidedとして扱い、jarに埋め込まない -assemblyExcludedJars in assembly := { - (fullClasspath in assembly).value +assembly / assemblyExcludedJars := { + (assembly / fullClasspath).value .filter { a => def directoryContainsFile(directory: File, file: File) = file.absolutePath.startsWith(directory.absolutePath) @@ -102,33 +102,33 @@ val filesToBeReplacedInResourceFolder = Seq("plugin.yml") val filteredResourceGenerator = taskKey[Seq[File]]("Resource generator to filter resources") -filteredResourceGenerator in Compile := +Compile / filteredResourceGenerator := filterResources( filesToBeReplacedInResourceFolder, tokenReplacementMap.value, - (resourceManaged in Compile).value, (resourceDirectory in Compile).value + (Compile / resourceManaged).value, (Compile / resourceDirectory).value ) -resourceGenerators in Compile += (filteredResourceGenerator in Compile) +Compile / resourceGenerators += (Compile / filteredResourceGenerator) -unmanagedResources in Compile += baseDirectory.value / "LICENSE" +Compile / unmanagedResources += baseDirectory.value / "LICENSE" // トークン置換を行ったファイルをunmanagedResourcesのコピーから除外する -excludeFilter in unmanagedResources := - filesToBeReplacedInResourceFolder.foldLeft((excludeFilter in unmanagedResources).value)(_.||(_)) +unmanagedResources / excludeFilter := + filesToBeReplacedInResourceFolder.foldLeft((unmanagedResources / excludeFilter).value)(_.||(_)) logLevel := Level.Debug // ScalaPBの設定 -PB.protoSources in Compile := Seq(baseDirectory.value / "protocol") -PB.targets in Compile := Seq(scalapb.gen() -> (sourceManaged in Compile).value / "scalapb") +Compile / PB.protoSources := Seq(baseDirectory.value / "protocol") +Compile / PB.targets := Seq(scalapb.gen() -> (Compile / sourceManaged).value / "scalapb") -testOptions in Test += Tests.Argument("-oS") +Compile / testOptions += Tests.Argument("-oS") lazy val root = (project in file(".")) .settings( name := "SeichiAssist", - assemblyOutputPath in assembly := baseDirectory.value / "target" / "build" / s"SeichiAssist.jar", + assembly / assemblyOutputPath := baseDirectory.value / "target" / "build" / s"SeichiAssist.jar", libraryDependencies := providedDependencies ++ testDependencies ++ dependenciesToEmbed, excludeDependencies := Seq( ExclusionRule(organization = "org.bukkit", name = "bukkit") From 9de049b9bc7a07df4a98582d366846c6f9db9262 Mon Sep 17 00:00:00 2001 From: KisaragiEffective <kisaragi.effective@gmail.com> Date: Mon, 30 Aug 2021 23:41:47 +0900 Subject: [PATCH 57/73] [fix] fix #1150 --- .../unchama/seichiassist/menus/ranking/RankingMenu.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/scala/com/github/unchama/seichiassist/menus/ranking/RankingMenu.scala b/src/main/scala/com/github/unchama/seichiassist/menus/ranking/RankingMenu.scala index a31d412b33..fbd9a4b80c 100644 --- a/src/main/scala/com/github/unchama/seichiassist/menus/ranking/RankingMenu.scala +++ b/src/main/scala/com/github/unchama/seichiassist/menus/ranking/RankingMenu.scala @@ -97,10 +97,10 @@ object RankingMenuTemplates { val vote: RankingMenuTemplate[VoteCount] = new RankingMenuTemplate[VoteCount] { override val rankingName: String = "投票神ランキング" override def recordDataLore(data: VoteCount): List[String] = List( - s"$RESET${GREEN}総投票回数:${data}回" + s"$RESET${GREEN}総投票回数:${data.value}回" ) override def combinedDataLore(data: VoteCount): List[String] = List( - s"$RESET${AQUA}全プレイヤー総投票回数: ${data}回" + s"$RESET${AQUA}全プレイヤー総投票回数: ${data.value}回" ) } } From ae9a91375a836474feaa3c3ed0bd878fa6782efd Mon Sep 17 00:00:00 2001 From: KisaragiEffective <kisaragi.effective@gmail.com> Date: Mon, 30 Aug 2021 23:47:59 +0900 Subject: [PATCH 58/73] [fix] fix #1148 --- .../unchama/seichiassist/listener/RegionInventoryListener.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/com/github/unchama/seichiassist/listener/RegionInventoryListener.scala b/src/main/scala/com/github/unchama/seichiassist/listener/RegionInventoryListener.scala index f4f3d4fce8..d9fe0e632e 100644 --- a/src/main/scala/com/github/unchama/seichiassist/listener/RegionInventoryListener.scala +++ b/src/main/scala/com/github/unchama/seichiassist/listener/RegionInventoryListener.scala @@ -282,7 +282,7 @@ object RegionInventoryListener { case Util.Direction.EAST => ( new Location(world, start_x - 15 * behindUnitAmount, 0.0, start_z + 15 * leftsideUnitAmount), - new Location(world, end_x + 15 * aheadUnitAmount, 256.0, end_z + 15 * rightsideUnitAmount) + new Location(world, end_x - 15 * aheadUnitAmount, 256.0, end_z + 15 * rightsideUnitAmount) ) case Util.Direction.SOUTH => From 96e2e9b4b901617268d06a493bbf5ee68fe388f1 Mon Sep 17 00:00:00 2001 From: KisaragiEffective <kisaragi.effective@gmail.com> Date: Fri, 3 Sep 2021 20:19:18 +0900 Subject: [PATCH 59/73] [fix] fix #1154 --- .../subsystems/ranking/domain/values/LoginTime.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/ranking/domain/values/LoginTime.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/ranking/domain/values/LoginTime.scala index 1dcef194e3..5f6836e566 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/ranking/domain/values/LoginTime.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/ranking/domain/values/LoginTime.scala @@ -5,7 +5,7 @@ import cats.kernel.{Monoid, Order} /** * TODO: rankingサブシステムから移す */ -case class LoginTime(inTick: Int) { +case class LoginTime(inTick: Long) { val formatted = s"${inTick / 3600 / 20}時間${inTick / 60 / 20 % 60}分${inTick / 20 % 60}秒" } From a50e729b8ff7894280abcead29b3666890109ac6 Mon Sep 17 00:00:00 2001 From: Moca3 <white@nagi.be> Date: Sat, 11 Sep 2021 21:45:18 +0900 Subject: [PATCH 60/73] =?UTF-8?q?[change]=E3=83=B4=E3=82=A7=E3=83=B3?= =?UTF-8?q?=E3=83=80=E3=83=BC=E3=82=B9=E3=82=AD=E3=83=AB=E3=81=AE=E8=AA=AC?= =?UTF-8?q?=E6=98=8E=E3=82=92=E5=A4=89=E6=9B=B4=E3=81=99=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../unchama/seichiassist/menus/skill/ActiveSkillMenu.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/com/github/unchama/seichiassist/menus/skill/ActiveSkillMenu.scala b/src/main/scala/com/github/unchama/seichiassist/menus/skill/ActiveSkillMenu.scala index 0de1867cee..6e60b03532 100644 --- a/src/main/scala/com/github/unchama/seichiassist/menus/skill/ActiveSkillMenu.scala +++ b/src/main/scala/com/github/unchama/seichiassist/menus/skill/ActiveSkillMenu.scala @@ -298,7 +298,7 @@ object ActiveSkillMenu extends Menu { List( requiredPointDescription, s"$RESET${DARK_RED}水凝固/熔岩凝固の双方を扱える者にのみ発現する上位凝固スキル", - s"$RESET${DARK_RED}アサルト・アーマーの発現には影響しない", + s"$RESET${DARK_RED}アサルト・アーマーの取得には必要ない", s"$RESET$AQUA${UNDERLINE}クリックで解除" ) case SeichiSkill.AssaultArmor => From e532201674b7965c5bd0959569dacd26a665d552 Mon Sep 17 00:00:00 2001 From: Tea <72652320+LargoGreenTea@users.noreply.github.com> Date: Wed, 15 Sep 2021 16:51:36 +0900 Subject: [PATCH 61/73] =?UTF-8?q?[add]#1027,#1159=20=E3=82=92=E9=81=A9?= =?UTF-8?q?=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../scala/com/github/unchama/seichiassist/MaterialSets.scala | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/scala/com/github/unchama/seichiassist/MaterialSets.scala b/src/main/scala/com/github/unchama/seichiassist/MaterialSets.scala index cee0207fce..b60f1dab0f 100644 --- a/src/main/scala/com/github/unchama/seichiassist/MaterialSets.scala +++ b/src/main/scala/com/github/unchama/seichiassist/MaterialSets.scala @@ -41,6 +41,9 @@ object MaterialSets { Material.WOODEN_DOOR, Material.ACACIA_DOOR, Material.BIRCH_DOOR, Material.DARK_OAK_DOOR, Material.JUNGLE_DOOR, Material.SPRUCE_DOOR, Material.SMOOTH_STAIRS, Material.BREWING_STAND, Material.WOOD_STEP, Material.TNT, + //#1027,#1159 + Material.WOOD_STEP, Material.WOOD_DOUBLE_STEP, + Material.DISPENSER, Material.PISTON_STICKY_BASE, Material.STRING ) ++ fortuneMaterials // これらのマテリアルを持つブロックは破壊を整地量に計上しない From 1ded53c547d174345fe7742ec9a55c4b724d71a8 Mon Sep 17 00:00:00 2001 From: KisaragiEffective <kisaragi.effective@gmail.com> Date: Mon, 20 Sep 2021 03:37:51 +0900 Subject: [PATCH 62/73] [update] bump sbt to 1.5.5 --- README.md | 2 +- project/build.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 92b0a3980e..597fc663b1 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ - [Intellij IDEA](https://www.jetbrains.com/idea/) などの統合開発環境 - [AdoptOpenJDK 1.8](https://adoptopenjdk.net/?variant=openjdk8&jvmVariant=hotspot) - [Scala 2.13](https://www.scala-lang.org/download/) -- [sbt 1.3.7](https://www.scala-sbt.org/1.x/docs/Setup.html) +- [sbt 1.5.5](https://www.scala-sbt.org/1.x/docs/Setup.html) - Spigot 1.12.2 ## 前提プラグイン diff --git a/project/build.properties b/project/build.properties index dbae93bcfd..10fd9eee04 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.4.9 +sbt.version=1.5.5 From 20c1150b66d67e4b2be3cd9d8a493ed458b4a4b9 Mon Sep 17 00:00:00 2001 From: Lucky <lucky3028@users.noreply.github.com> Date: Thu, 23 Sep 2021 21:17:45 +0900 Subject: [PATCH 63/73] =?UTF-8?q?[Add]=2021=E5=84=84=E4=BC=81=E7=94=BB?= =?UTF-8?q?=E5=A0=B1=E9=85=AC=E3=81=AE=E4=B8=80=E9=83=A8=E3=81=AE=E3=82=A2?= =?UTF-8?q?=E3=82=A4=E3=83=86=E3=83=A0=E3=81=AB=E8=80=90=E4=B9=85=E5=8A=9B?= =?UTF-8?q?5=E3=81=A8=E4=BF=AE=E7=B9=95=E3=82=A8=E3=83=B3=E3=83=81?= =?UTF-8?q?=E3=83=A3=E3=83=B3=E3=83=88=E3=82=92=E4=BB=98=E4=B8=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SeichiAssistItemMigrations.scala | 3 +- ...0_AddEnchantsTo2_1billionRewardItems.scala | 68 +++++++++++++++++++ 2 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 src/main/scala/com/github/unchama/seichiassist/subsystems/itemmigration/migrations/V1_4_0_AddEnchantsTo2_1billionRewardItems.scala diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/itemmigration/migrations/SeichiAssistItemMigrations.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/itemmigration/migrations/SeichiAssistItemMigrations.scala index 9401d0b895..1643aa25e2 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/itemmigration/migrations/SeichiAssistItemMigrations.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/itemmigration/migrations/SeichiAssistItemMigrations.scala @@ -17,7 +17,8 @@ object SeichiAssistItemMigrations { V1_0_0_MigrateMebiusToNewCodec.migration, V1_1_0_AddUnbreakableToNarutoRemake.migration, V1_2_0_FixTypoOf4thAnniversaryGT.migration, - V1_3_0_RemoveUnnecessaryLoreOfHalloweenItem.migration + V1_3_0_RemoveUnnecessaryLoreOfHalloweenItem.migration, + V1_4_0_AddEnchantsTo2_1billionRewardItems.migration )) } diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/itemmigration/migrations/V1_4_0_AddEnchantsTo2_1billionRewardItems.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/itemmigration/migrations/V1_4_0_AddEnchantsTo2_1billionRewardItems.scala new file mode 100644 index 0000000000..b8752e9d51 --- /dev/null +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/itemmigration/migrations/V1_4_0_AddEnchantsTo2_1billionRewardItems.scala @@ -0,0 +1,68 @@ +package com.github.unchama.seichiassist.subsystems.itemmigration.migrations + +import com.github.unchama.itemmigration.bukkit.util.MigrationHelper +import com.github.unchama.itemmigration.domain.{ItemMigration, ItemMigrationVersionNumber} +import org.bukkit.ChatColor._ +import org.bukkit.enchantments.Enchantment +import org.bukkit.inventory.ItemStack + +import scala.jdk.CollectionConverters._ + +/** + * 2021年に行われた5周年記念イベントの中の、21億企画の目標達成報酬として配布されたアイテムに修繕と耐久力5エンチャントを付与する + */ +object V1_4_0_AddEnchantsTo2_1billionRewardItems { + + // 年の判別用 + private val commonLore = s"${WHITE}21/07/22に開催された5周年記念企画" + + // アイテム名だけだと、21億企画報酬ではなく以前のイベントで交換可能だった当該アイテムも含んでしまいかねないので、説明文も確認する + private val titanReplicaName = Seq( + RED -> "T", + GOLD -> "I", + YELLOW -> "T", + GREEN -> "A", + BLUE -> "N ", // スペースは故意 + WHITE -> "Replica II" + ).map { case (color, str) => s"$color$BOLD$ITALIC$str" }.mkString + private val titanReplicaLore = s"${WHITE}30億/1日を突破した記念に配布されたものです。" + + private val gaeaReplicaName = Seq( + RED -> "G", + GOLD -> "A", + YELLOW -> "E", + GREEN -> "A ", // スペースは故意 + WHITE -> "Whiteday Replica" + ).map { case (color, str) => s"$color$BOLD$ITALIC$str" }.mkString + private val gaeaReplicaLore = s"${WHITE}35億/1日を突破した記念に配布されたものです。" + + def migration: ItemMigration = ItemMigration( + ItemMigrationVersionNumber(1, 4, 0), + MigrationHelper.delegateConversionForContainers(migrationFunction) + ) + + import eu.timepit.refined.auto._ + + def migrationFunction(itemStack: ItemStack): ItemStack = { + if (!is2_1billionRewardItems(itemStack)) return itemStack + + import scala.util.chaining._ + + itemStack.clone().addEnchantments(Map(Enchantment.MENDING -> 1, Enchantment.DURABILITY -> 5).asJava) + } + + def is2_1billionRewardItems(itemStack: ItemStack): Boolean = { + if (itemStack == null || !itemStack.hasItemMeta || !itemStack.getItemMeta.hasDisplayName || !itemStack.getItemMeta.hasLore) return false + isRewardGaeaReplica(itemStack) || isRewardTitanReplica(itemStack) + } + + def isRewardTitanReplica(item: ItemStack): Boolean = { + val lores = item.getItemMeta.getLore.asScala + item.getItemMeta.getDisplayName == titanReplicaName && lores.contains(titanReplicaLore) && lores.contains(commonLore) + } + + def isRewardGaeaReplica(item: ItemStack): Boolean = { + val lores = item.getItemMeta.getLore.asScala + item.getItemMeta.getDisplayName == gaeaReplicaName && lores.contains(gaeaReplicaLore) && lores.contains(commonLore) + } +} From d18f1f315ff1a32c76c59c58078f24ea8a2edf1a Mon Sep 17 00:00:00 2001 From: Lucky <lucky3028@users.noreply.github.com> Date: Thu, 23 Sep 2021 21:19:33 +0900 Subject: [PATCH 64/73] =?UTF-8?q?[Remove]=20=E4=B8=8D=E8=A6=81=E3=81=AAimp?= =?UTF-8?q?ort?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../migrations/V1_4_0_AddEnchantsTo2_1billionRewardItems.scala | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/itemmigration/migrations/V1_4_0_AddEnchantsTo2_1billionRewardItems.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/itemmigration/migrations/V1_4_0_AddEnchantsTo2_1billionRewardItems.scala index b8752e9d51..70bc52647d 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/itemmigration/migrations/V1_4_0_AddEnchantsTo2_1billionRewardItems.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/itemmigration/migrations/V1_4_0_AddEnchantsTo2_1billionRewardItems.scala @@ -46,8 +46,6 @@ object V1_4_0_AddEnchantsTo2_1billionRewardItems { def migrationFunction(itemStack: ItemStack): ItemStack = { if (!is2_1billionRewardItems(itemStack)) return itemStack - import scala.util.chaining._ - itemStack.clone().addEnchantments(Map(Enchantment.MENDING -> 1, Enchantment.DURABILITY -> 5).asJava) } From d2e57ded22059f8fe62f0b073943c558ba75eeda Mon Sep 17 00:00:00 2001 From: Lucky <lucky3028@users.noreply.github.com> Date: Thu, 23 Sep 2021 21:23:22 +0900 Subject: [PATCH 65/73] =?UTF-8?q?[Fix]=20import=E3=81=AE=E4=BD=8D=E7=BD=AE?= =?UTF-8?q?=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../V1_4_0_AddEnchantsTo2_1billionRewardItems.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/itemmigration/migrations/V1_4_0_AddEnchantsTo2_1billionRewardItems.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/itemmigration/migrations/V1_4_0_AddEnchantsTo2_1billionRewardItems.scala index 70bc52647d..61deb5410a 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/itemmigration/migrations/V1_4_0_AddEnchantsTo2_1billionRewardItems.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/itemmigration/migrations/V1_4_0_AddEnchantsTo2_1billionRewardItems.scala @@ -36,13 +36,13 @@ object V1_4_0_AddEnchantsTo2_1billionRewardItems { ).map { case (color, str) => s"$color$BOLD$ITALIC$str" }.mkString private val gaeaReplicaLore = s"${WHITE}35億/1日を突破した記念に配布されたものです。" + import eu.timepit.refined.auto._ + def migration: ItemMigration = ItemMigration( ItemMigrationVersionNumber(1, 4, 0), MigrationHelper.delegateConversionForContainers(migrationFunction) ) - import eu.timepit.refined.auto._ - def migrationFunction(itemStack: ItemStack): ItemStack = { if (!is2_1billionRewardItems(itemStack)) return itemStack From 8540862191ac722849c39b4bcf3da54c1211048e Mon Sep 17 00:00:00 2001 From: Lucky <lucky3028@users.noreply.github.com> Date: Thu, 23 Sep 2021 21:27:09 +0900 Subject: [PATCH 66/73] =?UTF-8?q?[Fix]=20=E3=82=B3=E3=83=B3=E3=83=91?= =?UTF-8?q?=E3=82=A4=E3=83=AB=E3=82=A8=E3=83=A9=E3=83=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../V1_4_0_AddEnchantsTo2_1billionRewardItems.scala | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/itemmigration/migrations/V1_4_0_AddEnchantsTo2_1billionRewardItems.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/itemmigration/migrations/V1_4_0_AddEnchantsTo2_1billionRewardItems.scala index 61deb5410a..67b7e048b4 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/itemmigration/migrations/V1_4_0_AddEnchantsTo2_1billionRewardItems.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/itemmigration/migrations/V1_4_0_AddEnchantsTo2_1billionRewardItems.scala @@ -46,7 +46,13 @@ object V1_4_0_AddEnchantsTo2_1billionRewardItems { def migrationFunction(itemStack: ItemStack): ItemStack = { if (!is2_1billionRewardItems(itemStack)) return itemStack - itemStack.clone().addEnchantments(Map(Enchantment.MENDING -> 1, Enchantment.DURABILITY -> 5).asJava) + import scala.util.chaining._ + + itemStack.clone().tap { item => + import item._ + addEnchantment(Enchantment.MENDING, 1) + addEnchantment(Enchantment.DURABILITY, 5) + } } def is2_1billionRewardItems(itemStack: ItemStack): Boolean = { From 9474ff235d4ddd85817bd4670fa8fe704eaadbdb Mon Sep 17 00:00:00 2001 From: Lucky <lucky3028@users.noreply.github.com> Date: Thu, 23 Sep 2021 22:32:16 +0900 Subject: [PATCH 67/73] =?UTF-8?q?[Fix]=20=E9=96=A2=E6=95=B0=E5=90=8D?= =?UTF-8?q?=E3=82=92=E3=82=8F=E3=81=8B=E3=82=8A=E3=82=84=E3=81=99=E3=81=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../V1_4_0_AddEnchantsTo2_1billionRewardItems.scala | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/itemmigration/migrations/V1_4_0_AddEnchantsTo2_1billionRewardItems.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/itemmigration/migrations/V1_4_0_AddEnchantsTo2_1billionRewardItems.scala index 67b7e048b4..ba1bbd33c6 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/itemmigration/migrations/V1_4_0_AddEnchantsTo2_1billionRewardItems.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/itemmigration/migrations/V1_4_0_AddEnchantsTo2_1billionRewardItems.scala @@ -44,7 +44,7 @@ object V1_4_0_AddEnchantsTo2_1billionRewardItems { ) def migrationFunction(itemStack: ItemStack): ItemStack = { - if (!is2_1billionRewardItems(itemStack)) return itemStack + if (!is21billionRewardItems(itemStack)) return itemStack import scala.util.chaining._ @@ -55,17 +55,17 @@ object V1_4_0_AddEnchantsTo2_1billionRewardItems { } } - def is2_1billionRewardItems(itemStack: ItemStack): Boolean = { + def is21billionRewardItems(itemStack: ItemStack): Boolean = { if (itemStack == null || !itemStack.hasItemMeta || !itemStack.getItemMeta.hasDisplayName || !itemStack.getItemMeta.hasLore) return false - isRewardGaeaReplica(itemStack) || isRewardTitanReplica(itemStack) + isRewardedGaeaReplica(itemStack) || isRewardedTitanReplica(itemStack) } - def isRewardTitanReplica(item: ItemStack): Boolean = { + def isRewardedTitanReplica(item: ItemStack): Boolean = { val lores = item.getItemMeta.getLore.asScala item.getItemMeta.getDisplayName == titanReplicaName && lores.contains(titanReplicaLore) && lores.contains(commonLore) } - def isRewardGaeaReplica(item: ItemStack): Boolean = { + def isRewardedGaeaReplica(item: ItemStack): Boolean = { val lores = item.getItemMeta.getLore.asScala item.getItemMeta.getDisplayName == gaeaReplicaName && lores.contains(gaeaReplicaLore) && lores.contains(commonLore) } From 56c6a37b077e5b7f264bc36b70a42d37f50d6d51 Mon Sep 17 00:00:00 2001 From: soundofhorizon <ooshiba0206@gmail.com> Date: Fri, 24 Sep 2021 11:04:30 +0900 Subject: [PATCH 68/73] =?UTF-8?q?[ADD]Season=20Achieve(10=E6=9C=88-12?= =?UTF-8?q?=E6=9C=88)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../achievement/NicknameMapping.scala | 13 +++++- .../seichiassist/achievement/Nicknames.scala | 13 +++++- .../achievement/SeichiAchievement.scala | 42 +++++++++++++++++-- .../group/AchievementGroupMenu.scala | 2 +- 4 files changed, 64 insertions(+), 6 deletions(-) diff --git a/src/main/scala/com/github/unchama/seichiassist/achievement/NicknameMapping.scala b/src/main/scala/com/github/unchama/seichiassist/achievement/NicknameMapping.scala index 2a409ac232..412becb5ab 100644 --- a/src/main/scala/com/github/unchama/seichiassist/achievement/NicknameMapping.scala +++ b/src/main/scala/com/github/unchama/seichiassist/achievement/NicknameMapping.scala @@ -196,7 +196,18 @@ object NicknameMapping { case No_9033 => NicknameCombination(Some(9033), Some(9903), Some(9033)) case No_9034 => NicknameCombination(Some(9034), None, Some(9034)) case No_9035 => NicknameCombination(Some(9035), Some(9905), Some(9035)) - case No_9036 => NicknameCombination(Some(9036), None, Some(9036)) + case No_9036 => NicknameCombination(Some(9036), Some(9903), Some(9036)) + case No_9037 => NicknameCombination(Some(9037), None, Some(9037)) + case No_9038 => NicknameCombination(Some(9038), None, Some(9038)) + case No_9039 => NicknameCombination(Some(9039), None, Some(9039)) + case No_9040 => NicknameCombination(Some(9040), None, Some(9040)) + case No_9041 => NicknameCombination(Some(9041), None, Some(9041)) + case No_9042 => NicknameCombination(Some(9042), Some(9905), Some(9042)) + case No_9043 => NicknameCombination(Some(9043), None, Some(9043)) + case No_9044 => NicknameCombination(Some(9044), Some(9044), Some(9044)) + case No_9045 => NicknameCombination(Some(9045), None, Some(9045)) + case No_9046 => NicknameCombination(Some(9046), None, None) + case No_9047 => NicknameCombination(Some(9047), None, Some(9047)) case No_8001 => NicknameCombination(Some(8001), Some(9905), Some(8001)) case No_8002 => NicknameCombination(Some(8002), Some(9905), Some(8002)) diff --git a/src/main/scala/com/github/unchama/seichiassist/achievement/Nicknames.scala b/src/main/scala/com/github/unchama/seichiassist/achievement/Nicknames.scala index 9f175aa053..00c10ecce8 100644 --- a/src/main/scala/com/github/unchama/seichiassist/achievement/Nicknames.scala +++ b/src/main/scala/com/github/unchama/seichiassist/achievement/Nicknames.scala @@ -194,7 +194,18 @@ object Nicknames { 9033 -> HeadTail(s"団子", s"団子"), 9034 -> HeadTail(s"全額", s"投資"), 9035 -> HeadTail(s"無尽蔵", s"気力"), - 9036 -> HeadTail(s"猛毒", s"直撃"), + 9036 -> HeadTail(s"兎", s"一緒に"), + 9037 -> HeadTail(s"月", s"うさぎ"), + 9038 -> HeadTail(s"美しい", s"装い"), + 9039 -> HeadTail(s"猛毒", s"直撃"), + 9040 -> HeadTail(s"衣", s"替え"), + 9041 -> HeadTail(s"体力", s"勝負"), + 9042 -> HeadTail(s"トパーズ", s"輝き"), + 9043 -> HeadTail(s"千歳", s"飴"), + 9044 -> FullSet(s"いい", s"肉の", s"日"), + 9045 -> HeadTail(s"大", s"掃除"), + 9046 -> HeadOnly(s"歳暮"), + 9047 -> HeadTail(s"聖なる", s"夜"), // 前後パーツ(購入用) 9801 -> HeadTail(s"お兄さん", s"お兄さん"), 9802 -> HeadTail(s"戦隊", s"戦隊"), diff --git a/src/main/scala/com/github/unchama/seichiassist/achievement/SeichiAchievement.scala b/src/main/scala/com/github/unchama/seichiassist/achievement/SeichiAchievement.scala index 5da244a286..01d44b4b17 100644 --- a/src/main/scala/com/github/unchama/seichiassist/achievement/SeichiAchievement.scala +++ b/src/main/scala/com/github/unchama/seichiassist/achievement/SeichiAchievement.scala @@ -1,19 +1,22 @@ package com.github.unchama.seichiassist.achievement -import java.time.{DayOfWeek, Month} - import cats.effect.IO import com.github.unchama.seichiassist.achievement.NamedHoliday.SpringEquinoxDay import enumeratum.{Enum, EnumEntry} import org.bukkit.entity.Player +import java.time.{DayOfWeek, Month} + sealed abstract class SeichiAchievement extends EnumEntry { val id: Int } object SeichiAchievement extends Enum[SeichiAchievement] { + sealed trait Unlockable + sealed trait AutoUnlocked + sealed trait ManuallyUnlocked sealed abstract class Normal[P] extends SeichiAchievement with Unlockable { @@ -224,17 +227,50 @@ object SeichiAchievement extends Enum[SeichiAchievement] { case object No_9023 extends NormalManual(9023, playedOn(Month.JUNE, 3, DayOfWeek.SUNDAY, "父の日")) case object No_9024 extends NormalManual(9024, playedOn(Month.JUNE, 29, "とある生誕の日")) case object No_9025 extends NormalManual(9025, playedIn(Month.JULY)) + case object No_9026 extends NormalManual(9026, playedOn(Month.JULY, 7, "七夕")) + case object No_9027 extends NormalManual(9027, playedOn(Month.JULY, 17, "とある東京の日")) + case object No_9028 extends NormalManual(9028, playedOn(Month.JULY, 29, "とある肉の日")) + case object No_9029 extends NormalManual(9029, playedIn(Month.AUGUST)) + case object No_9030 extends NormalManual(9030, playedOn(Month.AUGUST, 7, "とあるバナナの日")) + case object No_9031 extends NormalManual(9031, playedOn(Month.AUGUST, 21, "とあるJDの日")) + case object No_9032 extends NormalManual(9032, playedOn(Month.AUGUST, 29, "とある焼肉の日")) + case object No_9033 extends NormalManual(9033, playedIn(Month.SEPTEMBER)) + case object No_9034 extends NormalManual(9034, playedOn(Month.SEPTEMBER, 2, "とあるくじの日")) + case object No_9035 extends NormalManual(9035, playedOn(Month.SEPTEMBER, 12, "とあるマラソンの日")) - case object No_9036 extends NormalManual(9036, playedOn(Month.SEPTEMBER, 29, "とあるふぐの日")) + + case object No_9036 extends NormalManual(9036, playedOn(Month.SEPTEMBER, 15, "とある月見の日")) + + case object No_9037 extends NormalManual(9037, playedOn(Month.SEPTEMBER, 21, "とある中秋の日")) + + case object No_9038 extends NormalManual(9038, playedOn(Month.SEPTEMBER, 21, "とあるファッションショーの日")) + + case object No_9039 extends NormalManual(9039, playedOn(Month.SEPTEMBER, 29, "とあるふぐの日")) + + case object No_9040 extends NormalManual(9040, playedIn(Month.OCTOBER)) + + case object No_9041 extends NormalManual(9041, playedOn(Month.OCTOBER, 10, "とあるスポーツの日")) + + case object No_9042 extends NormalManual(9042, playedIn(Month.NOVEMBER)) + + case object No_9043 extends NormalManual(9043, playedOn(Month.NOVEMBER, 15, "とある七五三の日")) + + case object No_9044 extends NormalManual(9044, playedOn(Month.NOVEMBER, 29, "とある特上の肉の日")) + + case object No_9045 extends NormalManual(9045, playedIn(Month.DECEMBER)) + + case object No_9046 extends NormalManual(9046, playedOn(Month.DECEMBER, 1, "とある年の暮れの日")) + + case object No_9047 extends NormalManual(9047, playedOn(Month.DECEMBER, 25, "とあるクリスマスの日")) val values: IndexedSeq[SeichiAchievement] = findValues diff --git a/src/main/scala/com/github/unchama/seichiassist/menus/achievement/group/AchievementGroupMenu.scala b/src/main/scala/com/github/unchama/seichiassist/menus/achievement/group/AchievementGroupMenu.scala index 896b8519bb..bd75dea838 100644 --- a/src/main/scala/com/github/unchama/seichiassist/menus/achievement/group/AchievementGroupMenu.scala +++ b/src/main/scala/com/github/unchama/seichiassist/menus/achievement/group/AchievementGroupMenu.scala @@ -53,7 +53,7 @@ object AchievementGroupMenu { AchievementEntry.within(8001 to 8003) case Anniversaries => - AchievementEntry.within(9001 to 9036) + AchievementEntry.within(9001 to 9047) case MebiusBreeder => AchievementEntry.within(0 until 0) From d85c89805d6a467f8d17fffee9ca3cb2c8f29a1d Mon Sep 17 00:00:00 2001 From: soundofhorizon <ooshiba0206@gmail.com> Date: Fri, 24 Sep 2021 11:06:17 +0900 Subject: [PATCH 69/73] =?UTF-8?q?[REMOVE]=E4=B8=8D=E8=A6=81=E3=81=AA?= =?UTF-8?q?=E6=94=B9=E8=A1=8C=E3=82=92=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../achievement/SeichiAchievement.scala | 22 ------------------- 1 file changed, 22 deletions(-) diff --git a/src/main/scala/com/github/unchama/seichiassist/achievement/SeichiAchievement.scala b/src/main/scala/com/github/unchama/seichiassist/achievement/SeichiAchievement.scala index 01d44b4b17..0b078344f4 100644 --- a/src/main/scala/com/github/unchama/seichiassist/achievement/SeichiAchievement.scala +++ b/src/main/scala/com/github/unchama/seichiassist/achievement/SeichiAchievement.scala @@ -227,49 +227,27 @@ object SeichiAchievement extends Enum[SeichiAchievement] { case object No_9023 extends NormalManual(9023, playedOn(Month.JUNE, 3, DayOfWeek.SUNDAY, "父の日")) case object No_9024 extends NormalManual(9024, playedOn(Month.JUNE, 29, "とある生誕の日")) case object No_9025 extends NormalManual(9025, playedIn(Month.JULY)) - case object No_9026 extends NormalManual(9026, playedOn(Month.JULY, 7, "七夕")) - case object No_9027 extends NormalManual(9027, playedOn(Month.JULY, 17, "とある東京の日")) - case object No_9028 extends NormalManual(9028, playedOn(Month.JULY, 29, "とある肉の日")) - case object No_9029 extends NormalManual(9029, playedIn(Month.AUGUST)) - case object No_9030 extends NormalManual(9030, playedOn(Month.AUGUST, 7, "とあるバナナの日")) - case object No_9031 extends NormalManual(9031, playedOn(Month.AUGUST, 21, "とあるJDの日")) - case object No_9032 extends NormalManual(9032, playedOn(Month.AUGUST, 29, "とある焼肉の日")) - case object No_9033 extends NormalManual(9033, playedIn(Month.SEPTEMBER)) - case object No_9034 extends NormalManual(9034, playedOn(Month.SEPTEMBER, 2, "とあるくじの日")) - case object No_9035 extends NormalManual(9035, playedOn(Month.SEPTEMBER, 12, "とあるマラソンの日")) - case object No_9036 extends NormalManual(9036, playedOn(Month.SEPTEMBER, 15, "とある月見の日")) - case object No_9037 extends NormalManual(9037, playedOn(Month.SEPTEMBER, 21, "とある中秋の日")) - case object No_9038 extends NormalManual(9038, playedOn(Month.SEPTEMBER, 21, "とあるファッションショーの日")) - case object No_9039 extends NormalManual(9039, playedOn(Month.SEPTEMBER, 29, "とあるふぐの日")) - case object No_9040 extends NormalManual(9040, playedIn(Month.OCTOBER)) - case object No_9041 extends NormalManual(9041, playedOn(Month.OCTOBER, 10, "とあるスポーツの日")) - case object No_9042 extends NormalManual(9042, playedIn(Month.NOVEMBER)) - case object No_9043 extends NormalManual(9043, playedOn(Month.NOVEMBER, 15, "とある七五三の日")) - case object No_9044 extends NormalManual(9044, playedOn(Month.NOVEMBER, 29, "とある特上の肉の日")) - case object No_9045 extends NormalManual(9045, playedIn(Month.DECEMBER)) - case object No_9046 extends NormalManual(9046, playedOn(Month.DECEMBER, 1, "とある年の暮れの日")) - case object No_9047 extends NormalManual(9047, playedOn(Month.DECEMBER, 25, "とあるクリスマスの日")) val values: IndexedSeq[SeichiAchievement] = findValues From d0c98564f818ad6a826478d9dbcb04f2c80d651c Mon Sep 17 00:00:00 2001 From: Kory | Ryosuke Kondo <6561358+kory33@users.noreply.github.com> Date: Wed, 29 Sep 2021 01:28:52 +0100 Subject: [PATCH 70/73] =?UTF-8?q?[chore]=20=E3=82=AD=E3=83=A3=E3=83=83?= =?UTF-8?q?=E3=82=B7=E3=83=A5=E4=BB=98=E3=81=8D=E3=83=93=E3=83=AB=E3=83=89?= =?UTF-8?q?=E3=81=AE=E3=82=AD=E3=83=A3=E3=83=83=E3=82=B7=E3=83=A5=E3=82=92?= =?UTF-8?q?=E6=B6=88=E3=81=97=E9=A3=9B=E3=81=B0=E3=81=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/build_and_deploy.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build_and_deploy.yml b/.github/workflows/build_and_deploy.yml index a58457df6b..df16b8e9c6 100644 --- a/.github/workflows/build_and_deploy.yml +++ b/.github/workflows/build_and_deploy.yml @@ -23,7 +23,7 @@ jobs: uses: actions/cache@v2 env: cache-name: cache-build-dependencies - cache-version: v-2 + cache-version: v-3 with: # sbt等は$HOMEではなくユーザーディレクトリを見ているようで、 # GH Actionsでの ~ は /github/home/ に展開されるにもかかわらず @@ -47,7 +47,7 @@ jobs: uses: actions/cache@v2 env: cache-name: cache-build - cache-version: v-2 + cache-version: v-3 with: path: | target From 88a9830b76a6adf66e5293cad60d874ecc549688 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <github-actions[bot]@users.noreply.github.com> Date: Wed, 29 Sep 2021 09:13:29 +0000 Subject: [PATCH 71/73] [bump] 13 -> 14 --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 6a370c0850..81563f22b5 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 := "13" +ThisBuild / version := "14" ThisBuild / organization := "click.seichi" ThisBuild / description := "ギガンティック☆整地鯖の独自要素を司るプラグイン" From 7b4a3ce5d8d81f0c22e824461a740f37b5a1e6b8 Mon Sep 17 00:00:00 2001 From: Kory <6561358+kory33@users.noreply.github.com> Date: Wed, 29 Sep 2021 19:25:11 +0900 Subject: [PATCH 72/73] [fix] pass nmsWorldServer to World.getChunkAtCoordinate method --- .../unchama/util/nms/v1_12_2/world/WorldChunkSaving.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/com/github/unchama/util/nms/v1_12_2/world/WorldChunkSaving.scala b/src/main/scala/com/github/unchama/util/nms/v1_12_2/world/WorldChunkSaving.scala index 898648c509..4e4625a1ef 100644 --- a/src/main/scala/com/github/unchama/util/nms/v1_12_2/world/WorldChunkSaving.scala +++ b/src/main/scala/com/github/unchama/util/nms/v1_12_2/world/WorldChunkSaving.scala @@ -159,7 +159,7 @@ object WorldChunkSaving { val entityChunkZ = Entity.chunkZ(entity) if (Entity.loadedToAChunk(entity) && World.isChunkLoaded(nmsWorldServer)(entityChunkX, entityChunkZ)) { - val chunk = World.getChunkAtCoordinate(world)(entityChunkX, entityChunkZ) + val chunk = World.getChunkAtCoordinate(nmsWorldServer)(entityChunkX, entityChunkZ) Chunk.untrackEntity(chunk)(entity) } From 962463ed0cf7eb8daa0f4b651de3ef82f27aebee Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <github-actions[bot]@users.noreply.github.com> Date: Wed, 29 Sep 2021 10:27:42 +0000 Subject: [PATCH 73/73] [bump] 14 -> 15 --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 81563f22b5..77e8ac7498 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 := "14" +ThisBuild / version := "15" ThisBuild / organization := "click.seichi" ThisBuild / description := "ギガンティック☆整地鯖の独自要素を司るプラグイン"