Skip to content
This repository has been archived by the owner on Jul 8, 2018. It is now read-only.

注解载入器 Annotation Loader

Mouse edited this page Jul 13, 2017 · 2 revisions

在开发中,我们需要不断提高开发者的效率,以使开发进度加快。为此,我们在ChinaCraft2中实现了一个注解载入器。

为什么使用注解呢?俗话说得好:“反射,反射,程序员的欢乐。”使用注解确实便于阅读和修改,下面来看ChinaCraft2中的注册例子。

    @RegBlock(value = {"copper", "ore"}, oreDict = {"oreCopper"})
    Block COPPER_ORE = new BlockCCOre().setHarvestLevelReturnBlock("pickaxe", 1);

该代码是cn.mccraft.chinacraft.initCCBlocks类中的代码,可以看到在COPPER_ORE字段上我们使用了RegBlock注解,该注解表示COPPER_ORE是一个需要注册的方块,确实是十分方便阅读和修改。下面我们来看一看RegBlock的实现。

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface RegBlock {
    /**
     * 该参数将自动设置方块的registryName和unlocalizedName
     * The params to build registryName and unlocalizedName.
     * @see cn.mccraft.chinacraft.util.NameBuilder
     */
    String[] value();

    /**
     * 添加矿物词典
     * All {@link net.minecraftforge.oredict.OreDictionary} values to be registered.
     */
    String[] oreDict() default {};

    /**
     * 设置方块的ItemBlock类
     */
    Class<? extends Item> itemClass() default ItemBlock.class;

    /**
     * 是否自动注册ItemBlock
     */
    boolean isRegisterItemBlock() default true;

    /**
     * 是否自动注册渲染器
     */
    boolean isRegisterRender() default true;

而如何自动注册这些方块呢?我们在cn.mccraft.chinacraft.block.BlockLoader中实现了自动注册的方法,代码如下:

/**
 * Auto loader of all blocks annotated with {@link RegBlock} in {@link CCBlocks}.
 * 自动加载{@link CCBlocks}中被{@link RegBlock}注释的方块。
 */
@SuppressWarnings("unused")
public class BlockLoader implements ILoader { //ILoader接口是我们自己实现的加载器接口,与方块注册无关系
    @Load //该注解是我们自己实现的加载器注解,与方块注册无关系
    public void registerBlocks() { //注册CCBlocks中的所有方块
        for (Field field : CCBlocks.class.getFields()) {
            field.setAccessible(true);
            RegBlock anno = field.getAnnotation(RegBlock.class);
            if (anno==null) continue;

            try {
                Block block = (Block) field.get(null);
                GameRegistry.register(block.setRegistryName(NameBuilder.buildRegistryName(anno.value())).setUnlocalizedName(NameBuilder.buildUnlocalizedName(anno.value()))); //设置方块注册名和未本地化名并注册

                //Register item block.
                //注册方块物品
                if(anno.isRegisterItemBlock()) {
                    Class<? extends Item> itemClass = anno.itemClass();
                    Constructor<? extends Item> con = itemClass.getConstructor(Block.class);
                    con.setAccessible(true);
                    GameRegistry.register(con.newInstance(block).setRegistryName(block.getRegistryName()).setUnlocalizedName(block.getUnlocalizedName()));
                }

                Arrays.asList(anno.oreDict()).forEach(s -> OreDictionary.registerOre(s, block)); //添加矿物词典
            } catch (Exception e) {
                ChinaCraft.getLogger().warn("Un-able to register block " + field.toGenericString(), e);
            }
        }
    }

    @Load(side = Side.CLIENT)
    @SideOnly(Side.CLIENT)
    public void registerRenders() { //渲染器和方块注册要分开,因为服务端并不需要注册渲染器
        for (Field field : CCBlocks.class.getFields()) {
            field.setAccessible(true);
            RegBlock anno = field.getAnnotation(RegBlock.class);
            if (anno==null) continue;

            if(!anno.isRegisterRender()||!anno.isRegisterItemBlock()) continue;

            try {
                Block block = (Block) field.get(null);
                registerRender(block,0);
            } catch (Exception e) {
                ChinaCraft.getLogger().warn("Un-able to register block " + field.toGenericString(), e);
            }
        }
    }

    @SideOnly(Side.CLIENT)
    private void registerRender(Block block, int meta)
    {
        Item item = Item.getItemFromBlock(block);
        ModelLoader.setCustomModelResourceLocation(item, meta, new ModelResourceLocation(block.getRegistryName(), "inventory"));
    }
}

以上就是ChinaCraft2中方块的注解载入器的内容。同样的,我们也实现了物品载入器,有兴趣的读者可以阅读cn.mccraft.chinacraft.item.ItemLoadercn.mccraft.chinacraft.util.loader.annotation.RegItem的源码。

Clone this wiki locally