たくさんの自由帳
Androidのお話
たくさんの自由帳
投稿日 : | 0 日前
文字数(だいたい) : 2407
どうもこんばんわ。
Minecraft 1.21.5がリリースされたので自作MODを対応させました。
わんちゃんの柄が増えた?
今回も今回とてFabricチームがまとめてくれているので読みます
FabricとForgeは8.12.1になってます。NeoForgeは8.12
そして代替メソッドが見つからない、それっぽい名前のはあるんだけど全く引数が違う。。
どうやらデータコンポーネント(耐久、付いているエンチャント、金床のコスト)の中にツールチップに関する処理が移動した?
その上、ツールチップの表示処理を見ると、バニラのデータコンポーネントだけが列挙されてて、自作した所でデータコンポーネントを差し込む所が見つけられなかった。。。
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 を引き回すのは、、、