たくさんの自由帳
Androidのお話
たくさんの自由帳
投稿日 : | 0 日前
文字数(だいたい) : 2407
どうもこんばんわ。
Minecraft 1.21.5
がリリースされたので自作MOD
を対応させました。
わんちゃんの柄が増えた?
https://takusan.negitoro.dev/posts/minecraft_mod_1_21_4_migration/
今回も今回とてFabric
チームがまとめてくれているので読みます
https://fabricmc.net/2025/03/24/1215.html
Fabric
とForge
は8.12.1
になってます。NeoForge
は8.12
そして代替メソッドが見つからない、それっぽい名前のはあるんだけど全く引数が違う。。
https://wiki.fabricmc.net/tutorial:tooltip#adding_tooltips_in_1215
どうやらデータコンポーネント(耐久、付いているエンチャント、金床のコスト)の中にツールチップに関する処理が移動した?
その上、ツールチップの表示処理を見ると、バニラのデータコンポーネントだけが列挙されてて、自作した所でデータコンポーネントを差し込む所が見つけられなかった。。。
Fabric
の場合はFabric API
が独自のツールチップ追加イベントを飛ばしてくれるので、そのタイミングでやればいいらしい。
このイベントをMOD
初期化時に一回呼べば良い(@Mod
がついてるクラスのコンストラクタとかで)
というわけで適当にイベント登録する関数を作って、
/** ツールチップイベントを拾う */
object ClickManaitaTooltipEventCallback {
/** ツールチップ表示イベントを登録する */
fun registerTooltipEventCallback() {
// ツールチップの実装が変わってしまったので対応
// https://wiki.fabricmc.net/tutorial:tooltip#adding_tooltips_in_1215
ItemTooltipCallback.EVENT.register tooltipCallback@{ itemStack, _, _, list ->
val tooltipText = when (val item = itemStack.item) {
is ClickManaitaBaseItem -> item.getTooltipText()
is ClickManaitaCustomItem -> item.getTooltipText(itemStack)
else -> return@tooltipCallback
}
list.add(tooltipText)
}
}
}
@Mod
が付いたクラスのコンストラクタで呼び出す。
Kotlin
で書いているので(Fabric Language Kotlin
なので)コンストラクタじゃなくて関数だけど、、
@Suppress("unused")
fun init() {
// 以下省略...
// イベント登録
ClickManaitaTooltipEventCallback.registerTooltipEventCallback() // これ
}
ちなみにgetTooltipText()
はこれ。MutableText
を返している。
class ClickManaitaBaseItem(settings: Settings?, private val dropSize: Int = 2) : Item(settings) {
/** ツールチップの文言を返す */
fun getTooltipText(): MutableText {
return MutableText.of(PlainTextContent.of("x$dropSize")).setStyle(Style.EMPTY.withColor(Formatting.AQUA))
}
}
NeoForge
もソースコード見てたら見つけました。Fabric
と同様にイベントを初期化時に一発購読すれば取れます。
まずはイベントを受け取るため、イベント受け取り用のクラスを作って、メソッドを作ります。
Fabric
と違い、@SubscribeEvent
を付けると受け取れます。
どこからも呼び出されない関数なので、静的解析(IDEA
)がこれ使ってないやん消せるって言ってきますが、実行中に呼び出されるので@SuppressWarnings("unused")
を付けておきます。
警告が消えるとかのレベルなんですが。
ツールチップの上書きイベントを受け取る場合、引数の数、型 (シグネチャ) を合わせておく必要があります。名前は多分なんでも良い。
今回の場合はItemTooltipEvent
を一つだけ取るメソッドを用意しておけば良いはず。
public class ClickManaitaPlayerEvent {
/**
* ツールチップを出すメソッドが非推奨になってしまったので
*/
@SuppressWarnings("unused")
@SubscribeEvent
public void onItemTooltip(ItemTooltipEvent event) {
ItemStack itemStack = event.getItemStack();
List<Component> toolTip = event.getToolTip();
MutableComponent text = switch (itemStack.getItem()) {
case ClickManaitaBaseItem baseItem -> baseItem.getHoverText(itemStack);
case ClickManaitaBlockItem blockItem -> blockItem.getHoverText();
default -> null;
};
if (text != null) {
toolTip.add(text);
}
}
}
このクラスを、MOD
初期化時に一発呼べば良いはず。
@Mod
が付いたクラスのコンストラクタが良いかな。
@Mod(ClickManaita.MOD_ID)
public class ClickManaita {
/**
* MODのID
*/
public static final String MOD_ID = "clickmanaita";
/**
* コンストラクタ
*/
public ClickManaita(IEventBus modEventBus, ModContainer modContainer) {
// 省略...
NeoForge.EVENT_BUS.register(new ClickManaitaPlayerEvent()); // これ
}
}
ちなみにgetHoverText()
はMutableComponent
を返しているだけです。
public MutableComponent getHoverText(ItemStack itemStack) {
MutableComponent text = Component.literal(toolTipText);
text.setStyle(Style.EMPTY.withColor(TextColor.parseColor(toolTipColor).getOrThrow()));
return text;
}
Forge
も同様にイベントがあります。ので購読すれば良さそう。
NeoForge
とほぼ同じなのでコードだけ貼ります。NeoForge
で書いたものを、IDEA
のブランチ間差分でForge
側にコピペしただけなので、、、
public class ClickManaitaPlayerEvent {
/**
* ツールチップを出すメソッドが非推奨になってしまったので
*/
@SuppressWarnings("unused")
@SubscribeEvent
public void onItemTooltip(ItemTooltipEvent event) {
ItemStack itemStack = event.getItemStack();
List<Component> toolTip = event.getToolTip();
MutableComponent text = switch (itemStack.getItem()) {
case ClickManaitaBaseItem baseItem -> baseItem.getHoverText(itemStack);
case ClickManaitaBlockItem blockItem -> blockItem.getHoverText();
default -> null;
};
if (text != null) {
toolTip.add(text);
}
}
}
@Mod(ClickManaita.MOD_ID)
public class ClickManaita {
/**
* MODのID
*/
public static final String MOD_ID = "clickmanaita";
/**
* コンストラクタ
*/
public ClickManaita(FMLJavaModLoadingContext context) {
// 以下省略...
// プレイヤーイベント
MinecraftForge.EVENT_BUS.register(new ClickManaitaPlayerEvent());
}
}
つるはしクラスと、剣クラスが消えた。斧とかは残ってる。
代わりにnew Item()
の際にItem.Settings().pickaxe()
とかを付けるようになった?
見た感じ引数を直して、中身はItemScatterer.onStateReplaced(state, world, pos)
を呼び出すだけ?
はい
Kotlin
の言語レベルのnull安全
に慣れすぎてOptional<T>
が何もわからない。。。
Optional#map
するくらいなら早期return
してく、、れ。nullable を引き回すのは、、、