Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: マナが無くなったら掘れなくするパッシブスキルを追加 #2370

Open
wants to merge 15 commits into
base: 1_18
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
1fc70ab
feat: パッシブスキルメニューにマナが無くなったら掘れなくするスキルのトグルボタンを追加
kuroma6666 Sep 15, 2024
09a17d6
feat: マナを消費しきった際の分岐処理を追加
kuroma6666 Sep 15, 2024
924113e
chore: V1.19.0 ブロック破壊の抑制トリガー設定を保存するマイグレーションファイルを追加
kuroma6666 Sep 15, 2024
9f45f42
feat: breakskilltriggerconfigサブシステムの追加
kuroma6666 Sep 15, 2024
e7c7cd3
feat: ブロック破壊時、「マナ切れ」かどうか判定する処理を追加
kuroma6666 Sep 15, 2024
6725736
fix: `isBreakBlockManaFullyConsumed`を`breakskilltriggerconfig`サブシステムに実装
kuroma6666 Sep 16, 2024
c043e8d
fix: スキル発動分のマナ不足のとき、ブロック破壊処理を終了するようにする
kuroma6666 Sep 21, 2024
f1e0599
fix: 消費マナ不足処理の修正
kuroma6666 Sep 21, 2024
66d94e1
fix: `PlayerBlockBreakListener`へマナ切れブロック破壊停止設定取得処理を移動
kuroma6666 Sep 21, 2024
acb3cf8
fix: マナ消費できるかどうか判断する関数を修正
kuroma6666 Sep 21, 2024
9753a7a
fix: `isBreakBlockManaFullyConsumed`関数を`PlayerBlockBreakListener`へ定義
kuroma6666 Sep 22, 2024
05c80c1
chore: importするパッケージの修正
kuroma6666 Sep 22, 2024
d79bad1
fix: 消費マナ不足判定処理とブロック破壊時処理を明確にした
kuroma6666 Sep 22, 2024
ad5b883
chore: scalafmt
kuroma6666 Sep 22, 2024
02c9368
chore: `BreakSkillTriggerSettings`の削除
kuroma6666 Sep 22, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
USE seichiassist;

CREATE TABLE player_break_trigger_preference(
uuid CHAR(36) NOT NULL,
trigger_category ENUM('ManaFullyConsumed') NOT NULL,
do_not_break BOOL NOT NULL DEFAULT FALSE,
PRIMARY KEY(uuid, trigger_category),
INDEX index_player_break_trigger_preference_on_uuid (uuid)
);
Comment on lines +3 to +9
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

このテーブルで扱うデータは「マナがないときにスキルの発動を抑制するかどうか」ということだけなので、trigger_category カラムが ENUM で複数の値を持つことができる必要がないと思います(あくまで設定が有効か無効かの2値のみを扱うので)
なので、以下のようなテーブルにすると良いと思います。

Suggested change
CREATE TABLE player_break_trigger_preference(
uuid CHAR(36) NOT NULL,
trigger_category ENUM('ManaFullyConsumed') NOT NULL,
do_not_break BOOL NOT NULL DEFAULT FALSE,
PRIMARY KEY(uuid, trigger_category),
INDEX index_player_break_trigger_preference_on_uuid (uuid)
);
CREATE TABLE player_break_suppression_preference(
uuid CHAR(36) NOT NULL,
do_break_suppression_due_to_mana BOOL NOT NULL DEFAULT FALSE,
FOREIGN KEY fk_player_break_suppression_preference_uuid REFERENCES playerdata(uuid)
);

Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ import com.github.unchama.seichiassist.subsystems.autosave.application.SystemCon
import com.github.unchama.seichiassist.subsystems.breakcount.{BreakCountAPI, BreakCountReadAPI}
import com.github.unchama.seichiassist.subsystems.breakcountbar.BreakCountBarAPI
import com.github.unchama.seichiassist.subsystems.breakskilltargetconfig.BreakSkillTargetConfigAPI
import com.github.unchama.seichiassist.subsystems.breakskilltriggerconfig.BreakSkillTriggerConfigAPI
import com.github.unchama.seichiassist.subsystems.buildcount.BuildCountAPI
import com.github.unchama.seichiassist.subsystems.discordnotification.DiscordNotificationAPI
import com.github.unchama.seichiassist.subsystems.donate.DonatePremiumPointAPI
Expand Down Expand Up @@ -495,6 +496,10 @@ class SeichiAssist extends JavaPlugin() {
lazy val breakSkillTargetConfigSystem: subsystems.breakskilltargetconfig.System[IO, Player] =
subsystems.breakskilltargetconfig.System.wired[IO, SyncIO].unsafeRunSync()

lazy val breakSkillTriggerConfigSystem
: subsystems.breakskilltriggerconfig.System[IO, Player] =
subsystems.breakskilltriggerconfig.System.wired[IO, SyncIO].unsafeRunSync()

/* TODO: mineStackSystemは本来privateであるべきだが、mineStackにアイテムを格納するAPIが現状の
BreakUtilの実装から呼び出されている都合上やむを得ずpublicになっている。*/
lazy val mineStackSystem: subsystems.minestack.System[IO, Player, ItemStack] =
Expand Down Expand Up @@ -562,6 +567,7 @@ class SeichiAssist extends JavaPlugin() {
openirontrapdoor.System.wired,
gridRegionSystem,
breakSkillTargetConfigSystem,
breakSkillTriggerConfigSystem,
joinAndQuitMessenger,
elevatorSystem,
blockLiquidStreamSystem,
Expand Down Expand Up @@ -746,6 +752,8 @@ class SeichiAssist extends JavaPlugin() {
implicit val gridRegionAPI: GridRegionAPI[IO, Player, Location] = gridRegionSystem.api
implicit val breakSkillTargetConfigAPI: BreakSkillTargetConfigAPI[IO, Player] =
breakSkillTargetConfigSystem.api
implicit val breakSkillTriggerConfigAPI: BreakSkillTriggerConfigAPI[IO, Player] =
breakSkillTriggerConfigSystem.api
implicit val playerHeadSkinAPI: PlayerHeadSkinAPI[IO, Player] = playerHeadSkinSystem.api

val menuRouter = TopLevelRouter.apply
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,20 @@ import com.github.unchama.minecraft.actions.OnMinecraftServerThread
import com.github.unchama.seichiassist.ManagedWorld._
import com.github.unchama.seichiassist.MaterialSets.{BlockBreakableBySkill, BreakTool}
import com.github.unchama.seichiassist.concurrent.PluginExecutionContexts
import com.github.unchama.seichiassist.data.{AxisAlignedCuboid}
import com.github.unchama.seichiassist.data.syntax._
import com.github.unchama.seichiassist.seichiskill.ActiveSkillRange.MultiArea
import com.github.unchama.seichiassist.seichiskill.SeichiSkillUsageMode.Disabled
import com.github.unchama.seichiassist.seichiskill.{BlockSearching, BreakArea}
import com.github.unchama.seichiassist.subsystems.breakcount.domain.level.SeichiExpAmount
import com.github.unchama.seichiassist.subsystems.breakskilltriggerconfig.domain.BreakSkillTriggerConfigKey
import com.github.unchama.seichiassist.subsystems.mana.ManaApi
import com.github.unchama.seichiassist.subsystems.mana.domain.ManaAmount
import com.github.unchama.seichiassist.subsystems.minestack.MineStackAPI
import com.github.unchama.seichiassist.util.BreakUtil
import com.github.unchama.seichiassist.{MaterialSets, SeichiAssist}
import com.github.unchama.targetedeffect.player.FocusedSoundEffect
import com.github.unchama.targetedeffect.player.ActionBarMessageEffect
import com.github.unchama.util.bukkit.ItemStackUtil
import com.github.unchama.util.effect.BukkitResources
import com.github.unchama.util.external.WorldGuardWrapper
Expand Down Expand Up @@ -101,20 +105,70 @@ class PlayerBlockBreakListener(
return
}

// 追加マナ獲得
manaApi
.manaAmount(player)
.restoreAbsolute(ManaAmount(BreakUtil.calcManaDrop(player)))
.unsafeRunSync()

// 選択したスキル
val selectedSkill = skillState
.activeSkill
.getOrElse(
return
)

if (!selectedSkill.range.isInstanceOf[MultiArea] || skillState.usageMode == Disabled) return

// プレイヤーのY座標
val playerLocY = player.getLocation.getBlockY - 1
// スキル破壊範囲
val skillArea = BreakArea(selectedSkill, skillState.usageMode)
// 破壊エリアリスト
val breakAreaList = skillArea.makeBreakArea(player).unsafeRunSync()
// 複数種類ブロック同時破壊設定
val isMultiTypeBreakingSkillEnabled =
BreakUtil.performsMultipleIDBlockBreakWhenUsingSkills(player).unsafeRunSync()
// 破壊範囲のブロック計算
val totalBreakRangeVolume = {
val breakLength = skillArea.breakLength
breakLength.x * breakLength.y * breakLength.z * skillArea.breakNum
}
// ブロック探索結果
val blockSearchResult
: AxisAlignedCuboid => (List[BlockBreakableBySkill], List[Block], List[Block]) = {
breakArea: AxisAlignedCuboid =>
val BlockSearching.Result(breakBlocks, waterBlocks, lavaBlocks) =
BlockSearching
.searchForBlocksBreakableWithSkill(player, breakArea.gridPoints(), block)
.unsafeRunSync()
.filterSolids(targetBlock =>
isMultiTypeBreakingSkillEnabled || BlockSearching
.multiTypeBreakingFilterPredicate(block)(targetBlock)
)
.filterAll(targetBlock =>
player.isSneaking || targetBlock
.getLocation
.getBlockY > playerLocY || targetBlock == block
)
(breakBlocks, waterBlocks, lavaBlocks)
}

// 消費マナが不足しているか判定
breakAreaList.foreach { breakArea =>
val (breakBlocks, _, _) = blockSearchResult(breakArea)
// 破壊範囲で消費されるマナ計算
val manaToConsumeOnBreakArea = ManaAmount {
(gravity + 1) * selectedSkill.manaCost * (breakBlocks.size + 1).toDouble / totalBreakRangeVolume
}
// 消費マナが不足している場合は処理を終了
manaApi.manaAmount(player).canAcquire(manaToConsumeOnBreakArea).unsafeRunSync() match {
case false if isBreakBlockManaFullyConsumed(player) =>
event.setCancelled(true)
return
case _ =>
}
}

// 追加マナ獲得
manaApi
.manaAmount(player)
.restoreAbsolute(ManaAmount(BreakUtil.calcManaDrop(player)))
.unsafeRunSync()

Comment on lines +116 to +171
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ここの差分は、実際のワールドの探索などのコードを含んでいることと、レガシーコードなこともあり正確な読み取りが難しい(大きな変更をするとバグが出る可能性が高い)ので、(まとめで定義したい気持ちはとても良くわかりますが)似たようなコードが複製されていてもいいので、この PR の目的の差分以外が出ない状態にしていただけると大変助かります🙇‍♂️🙇‍♂️

// 破壊不可能ブロックの時処理を終了
if (!BreakUtil.canBreakWithSkill(player, block)) {
event.setCancelled(true)
Expand All @@ -123,21 +177,8 @@ class PlayerBlockBreakListener(

event.setCancelled(true)

// ブロック破壊時に行う処理
{
// プレイヤーの足のy座標を取得
val playerLocY = player.getLocation.getBlockY - 1

val skillArea = BreakArea(selectedSkill, skillState.usageMode)
val breakAreaList = skillArea.makeBreakArea(player).unsafeRunSync()

val isMultiTypeBreakingSkillEnabled =
BreakUtil.performsMultipleIDBlockBreakWhenUsingSkills(player).unsafeRunSync()

val totalBreakRangeVolume = {
val breakLength = skillArea.breakLength
breakLength.x * breakLength.y * breakLength.z * skillArea.breakNum
}

// エフェクト用に壊されるブロック全てのリストデータ
val multiBreakList = new ArrayBuffer[Set[BlockBreakableBySkill]]
// 壊される溶岩の全てのリストデータ
Expand All @@ -154,22 +195,7 @@ class PlayerBlockBreakListener(
val b = new Breaks
b.breakable {
breakAreaList.foreach { breakArea =>
import com.github.unchama.seichiassist.data.syntax._

val BlockSearching.Result(breakBlocks, waterBlocks, lavaBlocks) =
BlockSearching
.searchForBlocksBreakableWithSkill(player, breakArea.gridPoints(), block)
.unsafeRunSync()
.filterSolids(targetBlock =>
isMultiTypeBreakingSkillEnabled || BlockSearching
.multiTypeBreakingFilterPredicate(block)(targetBlock)
)
.filterAll(targetBlock =>
player.isSneaking || targetBlock
.getLocation
.getBlockY > playerLocY || targetBlock == block
)

val (breakBlocks, waterBlocks, lavaBlocks) = blockSearchResult(breakArea)
// このチャンクで消費されるマナ
val manaToConsumeOnThisChunk = ManaAmount {
(gravity + 1) * selectedSkill.manaCost * (breakBlocks.size + 1).toDouble / totalBreakRangeVolume
Expand Down Expand Up @@ -373,4 +399,24 @@ class PlayerBlockBreakListener(
event.setCancelled(true)
player.sendMessage(s"${RED}Y-59以下に敷かれたハーフブロックは破壊不可能です。")
}

/**
* ブロック破壊時、「マナ切れブロック破壊停止設定」を取得する。
* マナ切れブロック破壊設定が `true` になっている場合、プレイヤーに破壊抑制メッセージを送信する。
* @param player マナ切れブロック破壊停止設定を取得するプレイヤー
*/
def isBreakBlockManaFullyConsumed(player: Player): Boolean = {

val isBreakBlockManaFullyConsumed = SeichiAssist
.instance
.breakSkillTriggerConfigSystem
.api
.breakSkillTriggerConfig(player, BreakSkillTriggerConfigKey.ManaFullyConsumed)
.unsafeRunSync()

if (isBreakBlockManaFullyConsumed) {
ActionBarMessageEffect(s"${RED}マナ切れでブロック破壊を止めるスキルは有効化されています").run(player).unsafeRunSync()
}
isBreakBlockManaFullyConsumed
}
Comment on lines +408 to +421
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def isBreakBlockManaFullyConsumed(player: Player): Boolean = {
val isBreakBlockManaFullyConsumed = SeichiAssist
.instance
.breakSkillTriggerConfigSystem
.api
.breakSkillTriggerConfig(player, BreakSkillTriggerConfigKey.ManaFullyConsumed)
.unsafeRunSync()
if (isBreakBlockManaFullyConsumed) {
ActionBarMessageEffect(s"${RED}マナ切れでブロック破壊を止めるスキルは有効化されています").run(player).unsafeRunSync()
}
isBreakBlockManaFullyConsumed
}
def isBreakBlockManaFullyConsumed(player: Player): IO[Boolean] = {
for {
isBreakBlockManaFullyConsumed <- SeichiAssist
.instance
.breakSkillTriggerConfigSystem
.api
.breakSkillTriggerConfig(player, BreakSkillTriggerConfigKey.ManaFullyConsumed)
_ <- ActionBarMessageEffect(s"${RED}マナ切れでブロック破壊を止めるスキルは有効化されています")
.run(player)
.whenA(isBreakBlockManaFullyConsumed)
} yield isBreakBlockManaFullyConsumed
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ 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.breakskilltargetconfig.BreakSkillTargetConfigAPI
import com.github.unchama.seichiassist.subsystems.breakskilltriggerconfig.BreakSkillTriggerConfigAPI
import com.github.unchama.seichiassist.subsystems.buildcount.domain.playerdata.BuildAmountData
import com.github.unchama.seichiassist.subsystems.discordnotification.DiscordNotificationAPI
import com.github.unchama.seichiassist.subsystems.donate.DonatePremiumPointAPI
Expand Down Expand Up @@ -104,6 +105,7 @@ object TopLevelRouter {
fairySpeechAPI: FairySpeechAPI[IO, Player],
gridRegionAPI: GridRegionAPI[IO, Player, Location],
breakSkillTargetConfigAPI: BreakSkillTargetConfigAPI[IO, Player],
breakSkillTriggerConfigAPI: BreakSkillTriggerConfigAPI[IO, Player],
playerHeadSkinAPI: PlayerHeadSkinAPI[IO, Player]
): TopLevelRouter[IO] = new TopLevelRouter[IO] {
import assortedRankingApi._
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import com.github.unchama.seichiassist.menus.stickmenu.FirstPage
import com.github.unchama.seichiassist.subsystems.breakcount.BreakCountAPI
import com.github.unchama.seichiassist.subsystems.breakskilltargetconfig.BreakSkillTargetConfigAPI
import com.github.unchama.seichiassist.subsystems.breakskilltargetconfig.domain.BreakSkillTargetConfigKey
import com.github.unchama.seichiassist.subsystems.breakskilltriggerconfig.BreakSkillTriggerConfigAPI
import com.github.unchama.seichiassist.subsystems.breakskilltriggerconfig.domain.BreakSkillTriggerConfigKey
import com.github.unchama.seichiassist.subsystems.playerheadskin.PlayerHeadSkinAPI
import com.github.unchama.targetedeffect._
import com.github.unchama.targetedeffect.commandsender.MessageEffect
Expand All @@ -34,6 +36,7 @@ object PassiveSkillMenu extends Menu {
class Environment(
implicit val breakCountApi: BreakCountAPI[IO, SyncIO, Player],
implicit val breakSkillTargetConfigAPI: BreakSkillTargetConfigAPI[IO, Player],
implicit val breakSkillTriggerConfigAPI: BreakSkillTriggerConfigAPI[IO, Player],
val ioCanOpenFirstPage: IO CanOpen FirstPage.type,
implicit val playerHeadSkinAPI: PlayerHeadSkinAPI[IO, Player]
)
Expand Down Expand Up @@ -62,6 +65,7 @@ object PassiveSkillMenu extends Menu {
val dynamicPartComputation = List(
ChestSlotRef(0, 0) -> computeToggleMultipleBlockTypeDestructionButton,
ChestSlotRef(0, 1) -> computeToggleChestBreakButton,
ChestSlotRef(0, 2) -> computeToggleManaFullyConsumedBreakStopButton,
ChestSlotRef(1, 0) -> computeGiganticBerserkButton,
ChestSlotRef(1, 1) -> computeToggleNetherQuartzBlockButton
).traverse(_.sequence)
Expand Down Expand Up @@ -231,6 +235,49 @@ object PassiveSkillMenu extends Menu {
)
})

val computeToggleManaFullyConsumedBreakStopButton: IO[Button] = RecomputedButton(for {
originalBreakStopConfig <- breakSkillTriggerConfigAPI
.breakSkillTriggerConfig(player, BreakSkillTriggerConfigKey.ManaFullyConsumed)
} yield {
val baseLore = List(s"${YELLOW}マナ切れでブロック破壊を止めるスキル")
val statusLore = if (originalBreakStopConfig) {
List(s"${GREEN}ON (マナが切れるとブロック破壊を止めます。)", s"${DARK_RED}クリックでOFF")
} else {
List(s"${RED}OFF (マナが切れてもブロック破壊を続けます。)", s"${DARK_GREEN}クリックでON")
}

Button(
new IconItemStackBuilder(Material.LAPIS_LAZULI)
.tap { builder =>
if (originalBreakStopConfig)
builder.enchanted()
}
.title(s"$WHITE$UNDERLINE${BOLD}マナ切れでブロック破壊を止めるスキル切り替え")
.lore(baseLore ++ statusLore)
.build(),
LeftClickButtonEffect {
SequentialEffect(
breakSkillTriggerConfigAPI.toggleBreakSkillTriggerConfig(
BreakSkillTriggerConfigKey.ManaFullyConsumed
),
DeferredEffect(IO {
if (!originalBreakStopConfig) {
SequentialEffect(
MessageEffect(s"${GREEN}マナが切れたらブロック破壊を止めるスキルを有効化しました。"),
FocusedSoundEffect(Sound.BLOCK_STONE_BUTTON_CLICK_ON, 1f, 1f)
)
} else {
SequentialEffect(
MessageEffect(s"${RED}マナが切れたらブロック破壊を止めるスキルを無効化しました。"),
FocusedSoundEffect(Sound.BLOCK_STONE_BUTTON_CLICK_ON, 1f, 0.5f)
)
}
})
)
}
)
})

val computeGiganticBerserkButton: IO[Button] = RecomputedButton {
environment
.breakCountApi
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.github.unchama.seichiassist.subsystems.breakskilltriggerconfig

import cats.data.Kleisli
import com.github.unchama.seichiassist.subsystems.breakskilltriggerconfig.domain.BreakSkillTriggerConfigKey

trait BreakSkillTriggerConfigAPI[F[_], Player] {

/**
* @return 破壊トリガをトグルする作用
*/
def toggleBreakSkillTriggerConfig(
configKey: BreakSkillTriggerConfigKey
): Kleisli[F, Player, Unit]

/**
* @return 現在の破壊トリガを取得する作用
*/
def breakSkillTriggerConfig(player: Player, configKey: BreakSkillTriggerConfigKey): F[Boolean]

}

object BreakSkillTriggerConfigAPI {

def apply[F[_], Player](
implicit ev: BreakSkillTriggerConfigAPI[F, Player]
): BreakSkillTriggerConfigAPI[F, Player] = ev

}
Loading