使用一个类命名来自任何元区块的子块?

时间:2016-02-02 00:53:27

标签: java minecraft-forge

我试图这样做只需要一个类来命名来自任何使用此类注册的元区块的子块,即将它们命名为参数值,但不使用一个。

虽然这围绕着一个API(Minecraft Forge),但我认为它是一个Java问题,所以我在这里快速解释一下我打算如何工作。

元区块由子块组成,子块是同一块的变体(例如,相同的块但仅改变纹理和名称)。每个子块都需要一个名称来标识它。这些名称列在ExampleItemBlock的班级String[]中,然后以MetablockName.SubBlockName格式命名(例如:ExampleMetablock.blueExampleMetablock.green等。) ,使用

// ExampleItemBlock Class

public static final String[] SUBNAMES = new String[] {"blue", "green", "yellow"};

@Override
public String getUnlocalizedName(ItemStack itemStack) 
{
    int i = itemStack.getItemDamage();
    return getUnlocalizedName() + "." + SUBNAMES[i];
}

然后,元区块ExampleMetablock被实例化并使用

注册
// Class where the registrations are made  

public static Block ExampleMetablock = new ExampleMetablock(); 

GameRegistry.registerBlock(ExampleMetablock, ExampleItemBlock.class, "ExampleMetablock");

在此之后,一切都没有问题,但是我必须为我制作的每个新元区块创建一个新的* ItemBlock类,我不认为这是一个好的或适当的事情,我认为最好创建一个将由任何未来元区块使用的单个类。

由于它很明显,GameRegistry.registerBlock()方法的第二个参数(来自API的方法)需要类型为Class的值。这就是问题所在:如何在不使用实例的情况下将ExampleItemBlock类动态化?

我甚至尝试在ExampleItemBlock构造函数中添加一个String []参数,然后使用名称代替类的实例,但正如预期的那样,它表示类型不匹配。

为了达到这个目的,我到处寻找,但我只发现了两种方式:

1。为每个新的元区块创建一个ItemBlock类;
2。SUBNAMES[i]中的getUnlocalizedName()更改为iitemStack.getItemDamage(),这会导致子块被命名为数字而不是名称(例如: ExampleMetablock.0ExampleMetablock.1等),不需要使用String []或任何东西,并使其成为通用类。然而,这种方式也是非常不切实际的,因为在识别哪个子块时,这会很复杂。

我还在GitHub上搜索了一些mod,但是在代码中没有找到与此相关的内容(我知道)。

所以我的问题是:是否有人制作一个通用* ItemBlock类,但仍然用名称(单词)命名子块?

课程内容:ExampleMetablockExampleItemBlock

2 个答案:

答案 0 :(得分:0)

我建议制作一个能够完成所有功能的基类。

public class BaseItemMetaBlock {
    .....
}

这个具有元块渲染内容的所有功能,但不会分配给任何块。

然后,有一个块

public class MySuperAwesomeBlockItem extends BaseItemMetaBlock {
    public MySuperAwesomeBlockItem(Block block) {
       super(block);
    }
}

因为ItemBlock与块本身相关联,所以你可以做一些编程魔术来获取定义块状态的枚举以返回你想要的名称。

我所做的是给我的块一个特殊的接口,所以我可以在将它们转换为通用的intface后调用我自己的方法

 @Override
 public String getUnlocalizedName(ItemStack stack) {
    return super.getUnlocalizedName(stack) + "." + ((IMetaBlockName)this.block).getSpecialName(stack);
  }

无论如何都是这样的。

答案 1 :(得分:0)

我最终发现解决方案是Forge本身,可以看出here

但是出于信息的原因,我将解释解决方案。

我不知道,但方法GameRegistry.registerBlock()也接受第Object[]类型的第四个参数。因此,只需将名称列表放在Object[]中,只需从String[]创建ExampleMetablock字段,并将定义的Object[]参数值传递给{ {1}}字段。像这样:

String[]

我不建议在public static String[] SUBNAMES; private IIcon[] icon; public ExampleMetaBlock(Material material, String name, CreativeTabs tab, String[] subnames) { super(material, name, tab); SUBNAMES = subnames; } 参数中使用单独创建的类ExampleItemBlock,而是建议您在Minecraft代码中使用已存在的类,其作用与{{几乎相同1}},这是Class类(如果ExampleItemBlock类中没有其他任何附加内容,则为此类)。看这样的注册:

ItemMultiTexture

然而,这不会编译。错误ItemMultiTexture将出现在注册行(public static final String[] SubNames = new String[] {"blue", "green", "yellow", "red"}; public static Block ExampleMetablock = new ExampleMetablock(Material.rock, "ExampleMetablock", Tabs.ExampleModTab, SubNames); GameRegistry.registerBlock(ExampleMetablock, ItemMultiTexture.class, "ExampleMetablock", new Object[]{SubNames}); ....)。

NoSuchMethodException类构造函数采用GameRegistry.registerBlock方法参数中与其构造函数参数类型匹配的设置值,即ItemMultiTexture

提供了registerBlock()?是。提供了Block, Block, String[]?是。提供了第二个String[]?没有。"没有这样的方法",Block没有带参数Block的构造函数。

这是因为,如上所述,来自ItemMultiTexture的构造函数需要两个Block, String[]值。

要解决这个问题,只需创建一个新的类(或编辑ItemMultiTexture),扩展Block ExemploItemBlock两个ItemMultiTexture参数。像这样:

super

Block就像这样:

public class ItemMultiTextureHelper extends ItemMultiTexture
{
    public ItemMultiTextureHelper(Block block, String[] names)
    {
        super(block, block, names);
    }
}

最后一件事,但同样重要:registerBlock()删除 GameRegistry.registerBlock(ExampleMetablock, ItemMultiTextureHelper.class, "ExampleMetablock", new Object[]{SubNames}); 修饰符,否则会导致您的新元区块完全混乱,例如所有元区块和#39; s子块的名称与创建的第一个元区块,重复子块等的名称相同。
(我刚才遇到了这些问题,并修复了删除static。)所以正确的是这样:

SUBNAMES