本教程默认您已经配置好开发环境,下面开始代码
在dogegg.infected(我的包,因为我想编写一个僵尸模组)中新建包item
新建Items.java
package dogegg.infected.item;
import dogegg.infected.Main;
import dogegg.infected.entity.EntityInit;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.ArrowItem;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.CreativeModeTab;
import net.minecraft.world.item.Item;
import net.minecraftforge.accesstransformer.generated.AtParser;
import net.minecraftforge.common.ForgeSpawnEggItem;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.RegistryObject;
import java.util.function.Supplier;
public class ItemInit {
public static final DeferredRegister<Item> ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, Main.MODID);
public static final RegistryObject<Item> EXZ = ITEMS.register("exz",
()->new ExzItem(new Item.Properties().tab(Main.TUTORIAL_TAB)));
}
在item包中新建ExzItem.java
package dogegg.infected.item;
import net.minecraft.world.item.Item;
public class ExzItem extends Item {
public ExzItem(Properties properties){super(properties);}
}
新建block包,新建Blocks.java
新建InfectedBlock.java(感染方块),AntiCorrosiveBlock.java(防腐蚀方块)
由于我希望InfectedBlock能够在玩家站在上面时给予伤害,因此可参照岩浆方块的代码
package dogegg.infected.block;
import dogegg.infected.core.particles.ParticleInit;
import dogegg.infected.entity.CreeperInfect;
import dogegg.infected.entity.Infected;
import dogegg.infected.entity.SpiderInfect;
import dogegg.infected.entity.WardenInfect;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.particles.ParticleOptions;
import net.minecraft.core.particles.ParticleType;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.util.RandomSource;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.monster.Monster;
import net.minecraft.world.entity.monster.Zombie;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.enchantment.EnchantmentHelper;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.*;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
import java.util.List;
public class InfectedBlock extends SpreadingSnowyDirtBlock {
public InfectedBlock(BlockBehaviour.Properties p_54800_) {
super(p_54800_);
}
public void stepOn(Level p_153777_, BlockPos p_153778_, BlockState p_153779_, Entity p_153780_) {
if (!p_153780_.isSteppingCarefully() && p_153780_ instanceof LivingEntity) {
p_153780_.hurt(DamageSource.HOT_FLOOR, 1.0F);
}
}
public void tick(BlockState p_221415_, ServerLevel p_221416_, BlockPos p_221417_, RandomSource p_221418_) {
BubbleColumnBlock.updateColumn(p_221416_, p_221417_.above(), p_221415_);
}
public BlockState updateShape(BlockState p_54811_, Direction p_54812_, BlockState p_54813_, LevelAccessor p_54814_, BlockPos p_54815_, BlockPos p_54816_) {
if (p_54812_ == Direction.UP && p_54813_.is(Blocks.WATER)) {
p_54814_.scheduleTick(p_54815_, this, 20);
}
return super.updateShape(p_54811_, p_54812_, p_54813_, p_54814_, p_54815_, p_54816_);
}
public void randomTick(BlockState p_221420_, ServerLevel p_221421_, BlockPos p_221422_, RandomSource p_221423_) {
BlockPos blockpos = p_221422_.above();
if (p_221421_.getFluidState(p_221422_).canExtinguish(p_221421_, p_221422_)) {
p_221421_.playSound((Player) null, p_221422_, SoundEvents.FIRE_EXTINGUISH, SoundSource.BLOCKS, 0.5F, 2.6F + (p_221421_.random.nextFloat() - p_221421_.random.nextFloat()) * 0.8F);
p_221421_.sendParticles(ParticleTypes.LARGE_SMOKE, (double) blockpos.getX() + 0.5D, (double) blockpos.getY() + 0.25D, (double) blockpos.getZ() + 0.5D, 8, 0.5D, 0.25D, 0.5D, 0.0D);
}
}
public void onPlace(BlockState p_54823_, Level p_54824_, BlockPos p_54825_, BlockState p_54826_, boolean p_54827_) {
p_54824_.scheduleTick(p_54825_, this, 20);
}
}
stepOn方法用于对活着的实体(LivingEntity)造成伤害。
AntiCorrosiveBlock则可以直接使用Block类,不需要新的类。
Blocks.java
package dogegg.infected.block;
import dogegg.infected.Main;
import dogegg.infected.item.Items;
import net.minecraft.core.BlockPos;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.CreativeModeTab;
import net.minecraft.world.item.DyeColor;
import net.minecraft.world.item.Item;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.GrassBlock;
import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.block.StainedGlassBlock;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.Material;
import net.minecraft.world.level.material.MaterialColor;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.RegistryObject;
import java.util.function.Function;
import java.util.function.Supplier;
public class BlockInit {
public static DeferredRegister<Block> BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, Main.MODID);
public static final DeferredRegister<Item> ITEMS = Items.ITEMS;
public static final RegistryObject<Block> INFECTED_BLOCK = register("infected_block",
() -> new InfectedBlock(BlockBehaviour.Properties.of(Material.GRASS).randomTicks().strength(2.6F,2).sound(SoundType.GRASS).requiresCorrectToolForDrops()),
object -> () -> new BlockItem(object.get(), new Item.Properties().tab(Main.TUTORIAL_TAB)));
public static final RegistryObject<Block> ANTI_CORROSIVE_BLOCK = register("anti_corrosive_block",
() -> new Block(BlockBehaviour.Properties.of(Material.GRASS).randomTicks().strength(5F,3).sound(SoundType.CORAL_BLOCK).requiresCorrectToolForDrops()),
object -> () -> new BlockItem(object.get(), new Item.Properties().tab(Main.TUTORIAL_TAB)));
private static <T extends Block> RegistryObject<T> registerBlock(final String name,
final Supplier<? extends T> block) {
return BLOCKS.register(name, block);
}
private static <T extends Block> RegistryObject<T> register(final String name, final Supplier<? extends T> block,
Function<RegistryObject<T>, Supplier<? extends Item>> item) {
RegistryObject<T> obj = registerBlock(name, block);
ITEMS.register(name, item.apply(obj));
return obj;
}
private static <T extends Block> RegistryObject<T> registerBlock(String name, Supplier<T> block, CreativeModeTab tab) {
RegistryObject<T> toReturn = BLOCKS.register(name, block);
registerBlockItem(name, toReturn, tab);
return toReturn;
}
private static <T extends Block> RegistryObject<Item> registerBlockItem(String name, RegistryObject<T> block,
CreativeModeTab tab) {
return ItemInit.ITEMS.register(name, () -> new BlockItem(block.get(),
new Item.Properties().tab(tab)));
}
private static <T extends Block> RegistryObject<T> registerBlockWithoutBlockItem(String name, Supplier<T> block) {
return BLOCKS.register(name, block);
}
public static Supplier<Block> createStainedGlassFromColor(DyeColor color) {
return () -> new StainedGlassBlock(color, BlockBehaviour.Properties.of(Material.GLASS, color).strength(0.3F)
.sound(SoundType.GLASS).noOcclusion().isValidSpawn(BlockInit::never).isRedstoneConductor(BlockInit::never).isSuffocating(BlockInit::never).isViewBlocking(BlockInit::never));
}
public static boolean always(BlockState state, BlockGetter reader, BlockPos pos) {
return true;
}
public static boolean never(BlockState state, BlockGetter reader, BlockPos pos) {
return false;
}
public static boolean always(BlockState state, BlockGetter reader, BlockPos pos, EntityType<?> entityType) {
return true;
}
public static boolean never(BlockState state, BlockGetter reader, BlockPos pos, EntityType<?> entityType) {
return false;
}
}
在Main.java(dogegg.infected)中的Main方法改为:
public Main() {
IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();
modEventBus.addListener(this::commonSetup);
// Register the Deferred Register to the mod event bus so blocks get registered
Blocks.BLOCKS.register(modEventBus);
// Register the Deferred Register to the mod event bus so items get registered
Items.ITEMS.register(modEventBus);
// Register ourselves for server and other game events we are interested in
MinecraftForge.EVENT_BUS.register(this);
}
然后在类中添加一个物品栏常量
public static final CreativeModeTab TUTORIAL_TAB = new CreativeModeTab(MODID) {
@Override
public ItemStack makeIcon() {
//物品栏的图标
return new ItemStack(Blocks.INFECTED_BLOCK.get());
}
};
在resources中新建目录assets.infected在其中新建目录blockstates,lang,models,textures
在blockstates中添加json文件
anti_corrosive_block.json
{ "variants": { "": { "model": "infected:block/anti_corrosive_block" } } }
infected_block.json
{ "variants": { "": { "model": "infected:block/infected_block" } } }
在lang中添加en_us.json
{ "item.infected.exz": "Exz", "block.infected.infected_block": "Infected Block", "block.infected.anti_corrosive_block": "Anti Corrosive Block", "itemGroup.infected": "Egg Items" }
也可以添加中文语言文件zh_cn.json
然后在models中新建目录item,block
item/exz.json
{ "parent": "item/generated", "textures": { "layer0": "infected:item/exz" } }
item/anti_corrosive_block.json
{ "parent": "infected:block/anti_corrosive_block" }
item/infected_block.json
{ "parent": "infected:block/infected_block" }
block/anti_corrosive_block.json
{ "parent": "block/cube_all", "textures": { "all": "infected:block/anti_corrosive_block" } }
block/infected_block.json
{ "parent": "block/cube_all",
"textures": {
"all": "infected:block/infected_block"
}
}
在textures中新建block,item在其中添加png图片最为材质,文件名前缀与之前相同。
好了,就是这样