0

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

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

元块由子块组成,子块是同一块的变体(例如,同一块但只有纹理和名称改变)。每个子块都需要一个名称来标识它。ExampleItemBlock这些名称在 a中的类中列出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 类,我认为这不是一件好事或适当的事情,我认为创建一个更好任何未来元块都将使用的单个类。

很明显,method 的第二个参数GameRegistry.registerBlock()(即 API 中的方法)需要 type 的值Class。这就是问题所在:如何在ExampleItemBlock不使用实例的情况下使类动态化?

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

我到处寻找某种方式来实现这一目标,但我只找到了两种方法:

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

我还在 GitHub 上搜索了一些 mods,但在代码中没有找到任何与此相关的内容(据我所知)。

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

类内容:ExampleMetablockExampleItemBlock

4

2 回答 2

0

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

public class BaseItemMetaBlock {
    .....
}

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

然后,有一个块

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

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

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

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

反正是这样的。

于 2016-02-02T14:11:53.287 回答
0

我最终发现解决方案在 Forge 本身中,正如可以在此处看到的那样。

但为了提供信息,我将解释解决方案。


我不知道,但该方法GameRegistry.registerBlock()还接受类型为 的第四个参数Object[]。所以只需要把名字列表放在里面Object[],只需要从 中创建String[]字段ExampleMetablock,并将定义Object[]的参数的值传递给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单独创建的类 class ,而是使用 Minecraft 代码中已经存在的类,它与t 在课堂上)。看起来像这样的注册:ClassExampleItemBlockItemMultiTextureItemMultiTexture

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[]

发生这种情况是因为,如前所述,构造函数 fromItemMultiTexture需要两个Block值。

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

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});

最后一件事,但同样重要:从中删除static修饰符SUBNAMES,否则这将导致您的新元块完全混乱,就像所有元块的子块都以与创建的第一个元块中的子块相同的名称命名,重复子-blocks等
(我刚刚遇到了这些问题,并修复了删除static。)所以正确的实际上是这样的:

public String[] SUBNAMES;
于 2016-02-05T00:48:23.253 回答