【寿司職人になろう】オリジナルのアイテムを追加しよう
springmodディレクトリにModBlocks.javaを作成し、以下をコピー。
package mark.sushi.sushimod;
import net.fabricmc.fabric.api.item.v1.FabricItemSettings;
package mark.spring.springmod;
import net.fabricmc.fabric.api.item.v1.FabricItemSettings;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import net.minecraft.block.Block;
import net.minecraft.block.Blocks;
import net.minecraft.item.BlockItem;
import net.minecraft.registry.Registries;
import net.minecraft.registry.Registry;
import net.minecraft.util.Identifier;
public class ModBlocks {
private static Block registerBlock(String name, Block block) {
Block registeredBlock = Registry.register(Registries.BLOCK, new Identifier(Springmod.MOD_ID, name), block);
// ブロックアイテムの登録
Registry.register(Registries.ITEM, new Identifier(Springmod.MOD_ID, name),
new BlockItem(registeredBlock, new FabricItemSettings()));
return registeredBlock;
}
public static void registerModBlocks() {
Springmod.LOGGER.info("Registering Mod Blocks for " + Springmod.MOD_ID);
}
}
アイテムの追加のため以下のコードを追加(黄色の部分)
public class ModBlocks {
public static final Block CHIRASHI_SUSHI = registerBlock("chirashi_sushi",new CustomCakeBlock(FabricBlockSettings.copyOf(Blocks.CAKE).strength(0.5F).nonOpaque()));
private static Block registerBlock(String name, Block block) {
Block registeredBlock = Registry.register(Registries.BLOCK, new Identifier(Springmod.MOD_ID, name), block);
// ブロックアイテムの登録
Registry.register(Registries.ITEM, new Identifier(Springmod.MOD_ID, name),
new BlockItem(registeredBlock, new FabricItemSettings()));
return registeredBlock;
}
public static void registerModBlocks() {
Springmod.LOGGER.info("Registering Mod Blocks for " + Springmod.MOD_ID);
}
}
Springmod.javaを編集(黄色の部分)
package mark.spring.springmod;
import net.fabricmc.api.ModInitializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Springmod implements ModInitializer {
public static final String MOD_ID = "springmod";
public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID);
@Override
public void onInitialize() {
ModItems.registerModItems();
ModItemGroup.registerItemGroups();
ModBlocks.registerModBlocks();
LOGGER.info("Hello Fabric world!");
}
}
ModItemGroup.javaを編集(黄色の部分)
package mark.sushi.sushimod;
import net.fabricmc.fabric.api.itemgroup.v1.FabricItemGroup;
package mark.spring.springmod;
import net.fabricmc.fabric.api.itemgroup.v1.FabricItemGroup;
import net.minecraft.item.ItemGroup;
import net.minecraft.item.ItemStack;
import net.minecraft.registry.Registries;
import net.minecraft.registry.Registry;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
public class ModItemGroup {
public static final ItemGroup SPRING_GROUP = Registry.register(Registries.ITEM_GROUP,
new Identifier(Springmod.MOD_ID, "spring"),
FabricItemGroup.builder().displayName(Text.translatable("itemgroup.spring"))
.icon(() -> new ItemStack(ModItems.ODANGO)).entries((displayContext, entries) -> {
entries.add(ModItems.ODANGO);
entries.add(ModBlocks.CHIRASHI_SUSHI);
}).build());
public static void registerItemGroups() {
Springmod.LOGGER.info("Registering Item Groups for " + Springmod.MOD_ID);
}
}
springmodディレクトリにCustomCakeBlock.javaを作成し、以下をコピー。
package mark.spring.springmod;
import net.minecraft.block.*;
import net.minecraft.entity.ai.pathing.NavigationType;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.registry.tag.ItemTags;
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvents;
import net.minecraft.stat.Stats;
import net.minecraft.state.StateManager;
import net.minecraft.state.property.IntProperty;
import net.minecraft.state.property.Properties;
import net.minecraft.state.property.Property;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;
import net.minecraft.world.WorldAccess;
import net.minecraft.world.WorldView;
import net.minecraft.world.event.GameEvent;
public class CustomCakeBlock extends CakeBlock {
public static final int MAX_BITES = 6;
public static final IntProperty BITES;
public static final int DEFAULT_COMPARATOR_OUTPUT;
protected static final float field_31047 = 1.0F;
protected static final float field_31048 = 2.0F;
protected static final VoxelShape[] BITES_TO_SHAPE;
public CustomCakeBlock(AbstractBlock.Settings settings) {
super(settings);
this.setDefaultState((BlockState)((BlockState)this.stateManager.getDefaultState()).with(BITES, 0));
}
@Override
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
return BITES_TO_SHAPE[(Integer)state.get(BITES)];
}
@Override
public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
ItemStack itemStack = player.getStackInHand(hand);
Item item = itemStack.getItem();
if (itemStack.isIn(ItemTags.CANDLES) && (Integer)state.get(BITES) == 0) {
Block block = Block.getBlockFromItem(item);
if (block instanceof CandleBlock) {
if (!player.isCreative()) {
itemStack.decrement(1);
}
world.playSound((PlayerEntity)null, pos, SoundEvents.BLOCK_CAKE_ADD_CANDLE, SoundCategory.BLOCKS, 1.0F, 1.0F);
world.setBlockState(pos, CandleCakeBlock.getCandleCakeFromCandle(block));
world.emitGameEvent(player, GameEvent.BLOCK_CHANGE, pos);
player.incrementStat(Stats.USED.getOrCreateStat(item));
return ActionResult.SUCCESS;
}
}
if (world.isClient) {
if (tryEat(world, pos, state, player).isAccepted()) {
return ActionResult.SUCCESS;
}
if (itemStack.isEmpty()) {
return ActionResult.CONSUME;
}
}
return tryEat(world, pos, state, player);
}
protected static ActionResult tryEat(WorldAccess world, BlockPos pos, BlockState state, PlayerEntity player) {
if (!player.canConsume(false)) {
return ActionResult.PASS;
} else {
player.incrementStat(Stats.EAT_CAKE_SLICE);
player.getHungerManager().add(2, 0.1F);
int i = (Integer)state.get(BITES);
world.emitGameEvent(player, GameEvent.EAT, pos);
if (i < 6) {
world.setBlockState(pos, (BlockState)state.with(BITES, i + 1), 3);
} else {
world.removeBlock(pos, false);
world.emitGameEvent(player, GameEvent.BLOCK_DESTROY, pos);
}
return ActionResult.SUCCESS;
}
}
@Override
public BlockState getStateForNeighborUpdate(BlockState state, Direction direction, BlockState neighborState, WorldAccess world, BlockPos pos, BlockPos neighborPos) {
return direction == Direction.DOWN && !state.canPlaceAt(world, pos) ? Blocks.AIR.getDefaultState() : super.getStateForNeighborUpdate(state, direction, neighborState, world, pos, neighborPos);
}
@Override
public boolean canPlaceAt(BlockState state, WorldView world, BlockPos pos) {
return world.getBlockState(pos.down()).isSolid();
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
builder.add(new Property[]{BITES});
}
@Override
public int getComparatorOutput(BlockState state, World world, BlockPos pos) {
return getComparatorOutput((Integer)state.get(BITES));
}
public static int getComparatorOutput(int bites) {
return (7 - bites) * 2;
}
@Override
public boolean hasComparatorOutput(BlockState state) {
return true;
}
@Override
public boolean canPathfindThrough(BlockState state, BlockView world, BlockPos pos, NavigationType type) {
return false;
}
static {
BITES = Properties.BITES;
DEFAULT_COMPARATOR_OUTPUT = getComparatorOutput(0);
BITES_TO_SHAPE = new VoxelShape[]{Block.createCuboidShape((double)1.0F, (double)0.0F, (double)1.0F, (double)15.0F, (double)8.0F, (double)15.0F), Block.createCuboidShape((double)3.0F, (double)0.0F, (double)1.0F, (double)15.0F, (double)8.0F, (double)15.0F), Block.createCuboidShape((double)5.0F, (double)0.0F, (double)1.0F, (double)15.0F, (double)8.0F, (double)15.0F), Block.createCuboidShape((double)7.0F, (double)0.0F, (double)1.0F, (double)15.0F, (double)8.0F, (double)15.0F), Block.createCuboidShape((double)9.0F, (double)0.0F, (double)1.0F, (double)15.0F, (double)8.0F, (double)15.0F), Block.createCuboidShape((double)11.0F, (double)0.0F, (double)1.0F, (double)15.0F, (double)8.0F, (double)15.0F), Block.createCuboidShape((double)13.0F, (double)0.0F, (double)1.0F, (double)15.0F, (double)8.0F, (double)15.0F)};
}
}
テクスチャーを追加しよう
1-2 : ディレクトリを作成しよう!
sushimod/texturesディレクトリをクリック
blockディレクトリを作成
blockディレクトリに以下ファイル名でダウンロードしたテクスチャをアップロードしよう!
・chirashi_sushi_bottom.png
・chirashi_sushi_inner.png
・chirashi_sushi_side.png
・chirashi_sushi_top.png
2-1 : モデルファイルの作成
sushimod/modelsディレクトリをクリック
blockディレクトリを作成
models/blockディレクトリにファイル作成をクリックしてchirashi_sushi.jsonを作成し以下のように編集。
{
"textures": {
"particle": "springmod:block/chirashi_sushi_side",
"bottom": "springmod:block/chirashi_sushi_bottom",
"top": "springmod:block/chirashi_sushi_top",
"side": "springmod:block/chirashi_sushi_side"
},
"elements": [
{ "from": [ 1, 0, 1 ],
"to": [ 15, 8, 15 ],
"faces": {
"down": { "texture": "#bottom", "cullface": "down" },
"up": { "texture": "#top" },
"north": { "texture": "#side" },
"south": { "texture": "#side" },
"west": { "texture": "#side" },
"east": { "texture": "#side" }
}
}
]
}
同じディレクトリでファイル作成をクリックして、食べた回数に応じて見た目が変わる6種類分のモデルファイルを作成し以下のように編集:
・chirashi_sushi_slice_1.json
{
"textures": {
"particle": "springmod:block/chirashi_sushi_side",
{
"textures": {
"particle": "springmod:block/chirashi_sushi_side",
"bottom": "springmod:block/chirashi_sushi_bottom",
"top": "springmod:block/chirashi_sushi_top",
"side": "springmod:block/chirashi_sushi_side",
"inside": "springmod:block/chirashi_sushi_inner"
},
"elements": [
{ "from": [ 3, 0, 1 ],
"to": [ 15, 8, 15 ],
"faces": {
"down": { "texture": "#bottom", "cullface": "down" },
"up": { "texture": "#top" },
"north": { "texture": "#side" },
"south": { "texture": "#side" },
"west": { "texture": "#inside" },
"east": { "texture": "#side" }
}
}
]
}
・chirashi_sushi_slice_2.json
{
"textures": {
"particle": "springmod:block/chirashi_sushi_side",
{
"textures": {
{
"textures": {
"particle": "springmod:block/chirashi_sushi_side",
"bottom": "springmod:block/chirashi_sushi_bottom",
"top": "springmod:block/chirashi_sushi_top",
"side": "springmod:block/chirashi_sushi_side",
"inside": "springmod:block/chirashi_sushi_inner"
},
"elements": [
{ "from": [ 5, 0, 1 ],
"to": [ 15, 8, 15 ],
"faces": {
"down": { "texture": "#bottom", "cullface": "down" },
"up": { "texture": "#top" },
"north": { "texture": "#side" },
"south": { "texture": "#side" },
"west": { "texture": "#inside" },
"east": { "texture": "#side" }
}
}
]
}
・chirashi_sushi_slice_3.json
{
"textures": {
"particle": "springmod:block/chirashi_sushi_side",
"bottom": "springmod:block/chirashi_sushi_bottom",
"top": "springmod:block/chirashi_sushi_top",
"side": "springmod:block/chirashi_sushi_side",
"inside": "springmod:block/chirashi_sushi_inner"
},
"elements": [
{ "from": [ 7, 0, 1 ],
"to": [ 15, 8, 15 ],
"faces": {
"down": { "texture": "#bottom", "cullface": "down" },
"up": { "texture": "#top" },
"north": { "texture": "#side" },
"south": { "texture": "#side" },
"west": { "texture": "#inside" },
"east": { "texture": "#side" }
}
}
]
}
・chirashi_sushi_slice_4.json
{
"textures": {
"particle": "springmod:block/chirashi_sushi_side",
"bottom": "springmod:block/chirashi_sushi_bottom",
"top": "springmod:block/chirashi_sushi_top",
"side": "springmod:block/chirashi_sushi_side",
"inside": "springmod:block/chirashi_sushi_inner"
},
"elements": [
{ "from": [ 9, 0, 1 ],
"to": [ 15, 8, 15 ],
"faces": {
"down": { "texture": "#bottom", "cullface": "down" },
"up": { "texture": "#top" },
"north": { "texture": "#side" },
"south": { "texture": "#side" },
"west": { "texture": "#inside" },
"east": { "texture": "#side" }
}
}
]
}
・chirashi_sushi_slice_5.json
{
"textures": {
"particle": "springmod:block/chirashi_sushi_side",
"bottom": "springmod:block/chirashi_sushi_bottom",
"top": "springmod:block/chirashi_sushi_top",
"side": "springmod:block/chirashi_sushi_side",
"inside": "springmod:block/chirashi_sushi_inner"
},
"elements": [
{ "from": [ 11, 0, 1 ],
"to": [ 15, 8, 15 ],
"faces": {
"down": { "texture": "#bottom", "cullface": "down" },
"up": { "texture": "#top" },
"north": { "texture": "#side" },
"south": { "texture": "#side" },
"west": { "texture": "#inside" },
"east": { "texture": "#side" }
}
}
]
}
・chirashi_sushi_slice_6.json
{
"textures": {
"particle": "springmod:block/chirashi_sushi_side",
"bottom": "springmod:block/chirashi_sushi_bottom",
"top": "springmod:block/chirashi_sushi_top",
{
"textures": {
"particle": "springmod:block/chirashi_sushi_side",
"bottom": "springmod:block/chirashi_sushi_bottom",
"top": "springmod:block/chirashi_sushi_top",
"side": "springmod:block/chirashi_sushi_side",
"inside": "springmod:block/chirashi_sushi_inner"
},
"elements": [
{ "from": [ 13, 0, 1 ],
"to": [ 15, 8, 15 ],
"faces": {
"down": { "texture": "#bottom", "cullface": "down" },
"up": { "texture": "#top" },
"north": { "texture": "#side" },
"south": { "texture": "#side" },
"west": { "texture": "#inside" },
"east": { "texture": "#side" }
}
}
]
}
3-1 : モデルファイルの作成
models/itemディレクトリにファイル作成をクリックしてchirashi_sushi.jsonを作成し以下のように編集。
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "springmod:item/chirashi_sushi"
}
}
textures/itemディレクトリにchirashi_sushi.pngというファイル名でダウンロードしたテクスチャをアップロードしよう!
4-1 : ディレクトリの作成
assets/springmodディレクトリをクリック
blockstatesディレクトリを作成
作成したblockstatesディレクトリにファイル作成をクリックしてchirashi_sushi.jsonを作成し以下のように編集。
{
{
"variants": {
"bites=0": {
"model": "springmod:block/chirashi_sushi"
},
"bites=1": {
"model": "springmod:block/chirashi_sushi_slice_1"
},
"bites=2": {
"model": "springmod:block/chirashi_sushi_slice_2"
},
"bites=3": {
"model": "springmod:block/chirashi_sushi_slice_3"
},
"bites=4": {
"model": "springmod:block/chirashi_sushi_slice_4"
},
"bites=5": {
"model": "springmod:block/chirashi_sushi_slice_5"
},
"bites=6": {
"model": "springmod:block/chirashi_sushi_slice_6"
}
}
}