概要
本当は UI 上に表示したかったのですが表示方法がわからなかったのでチャットメッセージを送ってみました
環境
- macOS 15.2
- Java 21.0.5
- forrge MDK 1.20.6-50.1.32
- minecraft 1.20.6
コード全体
- vim src/main/java/com/example/examplemod/LaserGunItem.java
package com.example.examplemod;
import java.util.List;
import net.minecraft.ChatFormatting;
import net.minecraft.core.BlockPos;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResultHolder;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.entity.projectile.ProjectileUtil;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.TooltipFlag;
import net.minecraft.world.level.ClipContext;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.EntityHitResult;
import net.minecraft.world.phys.HitResult;
import net.minecraft.world.phys.Vec3;
public class LaserGunItem extends Item {
private float amountOfdamage = 100.0F; // ダメージ量
private String countKey = "laserGunKills"; // カウントのキー
public LaserGunItem(Properties properties) {
super(properties);
}
@Override
public InteractionResultHolder<ItemStack> use(
Level world, Player player, InteractionHand hand) {
// クライアント側のみでエフェクトを表示
if (world.isClientSide()) {
// ビームエフェクトを生成
spawnLaserBeam(player);
} else {
// サーバー側でダメージ処理
fireLaser(world, player);
}
return InteractionResultHolder.sidedSuccess(
player.getItemInHand(hand), world.isClientSide());
}
@Override
public void appendHoverText(
ItemStack stack,
Item.TooltipContext context,
List<Component> tooltip,
TooltipFlag flag) {
super.appendHoverText(stack, context, tooltip, flag);
// ダメージ情報を追加
tooltip.add(
Component.translatable("item.examplemod.laser_gun.damage", amountOfdamage)
.withStyle(ChatFormatting.GREEN));
// 他の情報も追加可能
tooltip.add(
Component.translatable("item.examplemod.laser_gun.description")
.withStyle(ChatFormatting.GRAY));
}
@Override
public boolean onEntityItemUpdate(ItemStack stack, ItemEntity entity) {
// 特殊な処理が必要であればここで行う(今回は不要なのでデフォルト動作に任せます)
// アイテムが q で捨てられたときにアイテムとして残すための設定
return super.onEntityItemUpdate(stack, entity);
}
private void spawnLaserBeam(Player player) {
// クライアント側エフェクト(例:パーティクル)
player.level()
.addParticle(
ParticleTypes.END_ROD,
player.getX(),
player.getEyeY(),
player.getZ(),
player.getLookAngle().x,
player.getLookAngle().y,
player.getLookAngle().z);
}
private void fireLaser(Level world, Player player) {
// 音の再生
if (world instanceof ServerLevel serverLevel) {
serverLevel.playSound(
null, // プレイヤー(nullにすると全員が聞こえる)
player.blockPosition(), // 再生位置
ExampleMod.LASER_FIRE_SOUND.get(), // サウンドイベント
SoundSource.PLAYERS, // サウンドの種類(PLAYERS, BLOCKS, AMBIENT など)
1.0f, // 音量
1.0f // 音の高さ(ピッチ)
);
}
// 発射用の座標と距離の設定
Vec3 start = player.getEyePosition(1.0F);
Vec3 direction = player.getLookAngle();
double range = 50.0D; // 50ブロック先をターゲット
Vec3 end = start.add(direction.scale(range));
// ブロックとのヒット判定
HitResult blockHit =
world.clip(
new ClipContext(
start,
end,
ClipContext.Block.OUTLINE,
ClipContext.Fluid.NONE,
player));
// エンティティとのヒット判定
EntityHitResult entityHit =
ProjectileUtil.getEntityHitResult(
world,
player,
start,
end,
player.getBoundingBox().expandTowards(direction.scale(range)).inflate(1.0D),
entity -> entity instanceof LivingEntity && entity != player);
// 優先的にエンティティを処理
if (entityHit != null) {
System.out.println("Hit entity!");
Entity hitEntity = entityHit.getEntity();
if (hitEntity instanceof LivingEntity livingEntity) {
// 敵にダメージを与える
livingEntity.hurt(
livingEntity.damageSources().playerAttack(player), amountOfdamage);
// 倒したか確認
if (livingEntity.isDeadOrDying()) {
// カウントを増やす
incrementKillCount(player);
sendChatMessage(player);
}
}
} else if (blockHit != null && blockHit.getType() == HitResult.Type.BLOCK) {
// ブロックにヒットした場合
System.out.println("Hit block at: " + ((BlockHitResult) blockHit).getBlockPos());
BlockHitResult blockResult = (BlockHitResult) blockHit;
BlockPos hitPos = blockResult.getBlockPos();
// ヒット位置に火をつける例
world.setBlockAndUpdate(hitPos, Blocks.FIRE.defaultBlockState());
} else {
// 何にも当たらなかった場合
System.out.println("Missed!");
}
}
private void incrementKillCount(Player player) {
CompoundTag tag = player.getPersistentData(); // プレイヤーのデータを取得
int currentCount = tag.getInt(countKey); // 現在のカウント
tag.putInt(countKey, currentCount + 1); // カウントを増加
}
private void sendChatMessage(Player player) {
CompoundTag tag = player.getPersistentData(); // プレイヤーのデータを取得
int currentCount = tag.getInt(countKey);
if (currentCount % 10 == 0) {
player.sendSystemMessage(
Component.translatable("Killed %d mobs with laser gun.".formatted(currentCount))
.withStyle(ChatFormatting.GREEN));
}
}
}
ポイント
チャットメッセージを送っている主な部分は以下です
今回はモブを倒した数を管理しておりその数が10で割り切れる数になったらプレイヤーにチャットメッセージを送信する内容になっています
チャットメッセージは player.sendSystemMessage
を使います
送信するメッセージはマイクラ内で送信できる Component というクラスに変換して送信します
Component には色など装飾することもできます
private void sendChatMessage(Player player) {
CompoundTag tag = player.getPersistentData(); // プレイヤーのデータを取得
int currentCount = tag.getInt(countKey);
if (currentCount % 10 == 0) {
player.sendSystemMessage(
Component.translatable("Killed %d mobs with laser gun.".formatted(currentCount))
.withStyle(ChatFormatting.GREEN));
}
}
動作確認
-
./gradlew build && ./gradlew runClient
討伐してメッセージが表示されることを確認してください
最後に
forge Mod でチャットメッセージを送信する方法を紹介しました
本当は画面上にテキストメッセージを表示したかったのですが RenderGuiEvent や RenderGuiOverlayEvent 等のイベントを使って描画したかったのですがどうやら 1.20.6 では使えなくなっているようでダメでした
0 件のコメント:
コメントを投稿