使用一个 class 从任何元区块命名子区块?
Naming subblocks from any metablock using one single class?
我正在尝试只需要一个 class 来命名使用此 class 注册的任何元区块的子区块,即,将它们命名为参数值, 但不使用一个。
尽管这是围绕 API(Minecraft Forge)展开的,但我认为这是一个 Java 问题,所以我在这里快速解释一下我打算如何工作。
元区块由子块组成,子块是同一块的变体(例如,同一块,但仅纹理和名称发生变化)。每个子块都需要一个名称来标识它。这些名称列在class ExampleItemBlock
中一个String[]
,然后以MetablockName.SubBlockName
的格式命名(例如:ExampleMetablock.blue
、ExampleMetablock.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 class,我认为这不是一件好事或不合适的事情,而且我认为最好创建一个单独的 class 供未来任何元区块使用。
值得注意的是,GameRegistry.registerBlock()
方法(即来自 API 的方法)的第二个参数需要类型为 Class
的值。这就是问题所在:如何在不使用实例的情况下将 ExampleItemBlock
class 动态化?
我什至尝试在 ExampleItemBlock
构造函数中添加一个 String[] 参数,然后使用名称代替 class 的实例,但正如预期的那样,它表明类型不匹配。
我到处寻找实现它的方法,但我只找到了两种方法:
1. 为每个新元区块创建一个 ItemBlock class;
2.将getUnlocalizedName()
中的SUBNAMES[i]
改成i
或itemStack.getItemDamage()
,这样子块的名称就会变成数字而不是名称(例如:ExampleMetablock.0
、ExampleMetablock.1
等),不需要使用 String[] 或任何东西,并使其成为通用的 class。但是,这种方式也很不切实际,因为这在识别哪个子块是哪个时变得非常复杂。
我也在 GitHub 上搜索了一些模组,但在代码中没有发现任何与此相关的内容(据我所知)。
所以我的问题是:有没有办法制作一个通用的 *ItemBlock class,但仍然用名称(单词)命名子块?
我的建议是制作一个基础 class 来完成您的所有功能。
public class BaseItemMetaBlock {
.....
}
这个有你所有的元块渲染功能,但没有分配给任何块。
然后,有一个块
public class MySuperAwesomeBlockItem extends BaseItemMetaBlock {
public MySuperAwesomeBlockItem(Block block) {
super(block);
}
}
因为 ItemBlock 与方块本身相关联,所以您可以通过一些编程魔术来获取定义方块状态的枚举 return 您想要的名称。
我所做的是为我的块提供一个特殊的接口,这样我就可以在将它们转换为通用接口后调用我自己的方法
@Override
public String getUnlocalizedName(ItemStack stack) {
return super.getUnlocalizedName(stack) + "." + ((IMetaBlockName)this.block).getSpecialName(stack);
}
反正就是这样。
我最终发现解决方案就在 Forge 本身,正如可以看到的那样 here。
但为了提供信息,我将解释解决方案。
我不知道,方法 GameRegistry.registerBlock()
还接受第四个参数,类型为 Object[]
。所以只需要将名称列表放在 Object[]
中,只需从 ExampleMetablock
创建 String[]
字段,并将定义的 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;
}
建议您在 Class
参数中使用单独创建的 class class ExampleItemBlock
,而不是使用已经存在的 [=75] =] 在 Minecraft 代码中做与 ExampleItemBlock
几乎相同的事情,即 ItemMultiTexture
class(这是为了防止 ItemMultiTexture
class).看注册是这样的:
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
class 构造函数在 registerBlock()
方法参数中获取与其构造函数参数类型匹配的设置值,即 Block, Block, String[]
。
是否提供了 String[]
?是的。是否提供了 Block
?是的。是否提供了第二个 Block
?号 "There is no such method",ItemMultiTexture
中没有参数为 Block, String[]
的构造函数。
发生这种情况是因为,如前所述,来自 ItemMultiTexture
的构造函数需要两个 Block
值。
要解决这个问题,只需创建一个新的 class(或编辑 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});
还有最后一件事,但同样重要:从 SUBNAMES
中删除 修饰符 static
,否则这将导致您的新设备一团糟元区块,就像所有元区块的子区块都被命名为与创建的第一个元区块、重复的子区块等相同的名称。
(我刚才遇到了这些问题,并修复了删除static
。)所以正确的是:
public String[] SUBNAMES;
我正在尝试只需要一个 class 来命名使用此 class 注册的任何元区块的子区块,即,将它们命名为参数值, 但不使用一个。
尽管这是围绕 API(Minecraft Forge)展开的,但我认为这是一个 Java 问题,所以我在这里快速解释一下我打算如何工作。
元区块由子块组成,子块是同一块的变体(例如,同一块,但仅纹理和名称发生变化)。每个子块都需要一个名称来标识它。这些名称列在class ExampleItemBlock
中一个String[]
,然后以MetablockName.SubBlockName
的格式命名(例如:ExampleMetablock.blue
、ExampleMetablock.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 class,我认为这不是一件好事或不合适的事情,而且我认为最好创建一个单独的 class 供未来任何元区块使用。
值得注意的是,GameRegistry.registerBlock()
方法(即来自 API 的方法)的第二个参数需要类型为 Class
的值。这就是问题所在:如何在不使用实例的情况下将 ExampleItemBlock
class 动态化?
我什至尝试在 ExampleItemBlock
构造函数中添加一个 String[] 参数,然后使用名称代替 class 的实例,但正如预期的那样,它表明类型不匹配。
我到处寻找实现它的方法,但我只找到了两种方法:
1. 为每个新元区块创建一个 ItemBlock class;
2.将getUnlocalizedName()
中的SUBNAMES[i]
改成i
或itemStack.getItemDamage()
,这样子块的名称就会变成数字而不是名称(例如:ExampleMetablock.0
、ExampleMetablock.1
等),不需要使用 String[] 或任何东西,并使其成为通用的 class。但是,这种方式也很不切实际,因为这在识别哪个子块是哪个时变得非常复杂。
我也在 GitHub 上搜索了一些模组,但在代码中没有发现任何与此相关的内容(据我所知)。
所以我的问题是:有没有办法制作一个通用的 *ItemBlock class,但仍然用名称(单词)命名子块?
我的建议是制作一个基础 class 来完成您的所有功能。
public class BaseItemMetaBlock {
.....
}
这个有你所有的元块渲染功能,但没有分配给任何块。
然后,有一个块
public class MySuperAwesomeBlockItem extends BaseItemMetaBlock {
public MySuperAwesomeBlockItem(Block block) {
super(block);
}
}
因为 ItemBlock 与方块本身相关联,所以您可以通过一些编程魔术来获取定义方块状态的枚举 return 您想要的名称。
我所做的是为我的块提供一个特殊的接口,这样我就可以在将它们转换为通用接口后调用我自己的方法
@Override
public String getUnlocalizedName(ItemStack stack) {
return super.getUnlocalizedName(stack) + "." + ((IMetaBlockName)this.block).getSpecialName(stack);
}
反正就是这样。
我最终发现解决方案就在 Forge 本身,正如可以看到的那样 here。
但为了提供信息,我将解释解决方案。
我不知道,方法 GameRegistry.registerBlock()
还接受第四个参数,类型为 Object[]
。所以只需要将名称列表放在 Object[]
中,只需从 ExampleMetablock
创建 String[]
字段,并将定义的 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;
}
建议您在 Class
参数中使用单独创建的 class class ExampleItemBlock
,而不是使用已经存在的 [=75] =] 在 Minecraft 代码中做与 ExampleItemBlock
几乎相同的事情,即 ItemMultiTexture
class(这是为了防止 ItemMultiTexture
class).看注册是这样的:
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
class 构造函数在 registerBlock()
方法参数中获取与其构造函数参数类型匹配的设置值,即 Block, Block, String[]
。
是否提供了 String[]
?是的。是否提供了 Block
?是的。是否提供了第二个 Block
?号 "There is no such method",ItemMultiTexture
中没有参数为 Block, String[]
的构造函数。
发生这种情况是因为,如前所述,来自 ItemMultiTexture
的构造函数需要两个 Block
值。
要解决这个问题,只需创建一个新的 class(或编辑 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});
还有最后一件事,但同样重要:从 SUBNAMES
中删除 修饰符 static
,否则这将导致您的新设备一团糟元区块,就像所有元区块的子区块都被命名为与创建的第一个元区块、重复的子区块等相同的名称。
(我刚才遇到了这些问题,并修复了删除static
。)所以正确的是:
public String[] SUBNAMES;