本篇教程由作者设定未经允许禁止转载。
由于目前 [QωQ Library] 并没有传到像 Curseforge 或者 Modrinth 这样的网站上,所以要使用本库较好的方法是从本地引用。
在你的 build.gradle 中找到 dependencies ,并添加以下代码:
modImplementation fileTree(dir: 'src/main/libs', includes: ['*.jar'])
并且把你下载到的 jar 文件(使用开发版和发布版均可)放在 src/main/libs 文件夹下。
重新构建后,你应该已经发现 QωQ 成功导入了。
QωQ 提供了一套较为简单注册像物品这样对象的方法,如下所示:
public class ItemInit {
public static final Registration<Item> ITEMS = new Registration<>(Registry.ITEM, MOD_ID);
public static final Item EXAMPLE_ITEM = ITEMS.register("example_item", () -> new Item(new Item.Settings()));
}
方块之类的对象与这类似。
当然别忘了将下面这条语句加到你的主类中去:
@Override
public void onInitialize() {
ItemInit.ITEMS.register();
}
当然,QωQ 还添加了一套类似于 Forge 的事件订阅系统,如果你想要订阅一个事件,你像下面这么做:
@ModEvent
public class OnEventHandle {
@SubscribeEvent
public static void onEvent(IEvent event) {
//todo
}
// 如果入参不等于1个,QωQ 会抛出警告并不会订阅这个方法
@SubscribeEvent
public static void onEvent(IEvent event1, IEvent event2) {
//todo
}
// 未添加 @SubscribeEvent 的注解的方法不会被 QωQ 加载
public static void onEvent() {
//todo
}
}
请不要忘记了在事件中检查客户端,当然你也不应该使用@Environment()注解,这都有可能使程序出问题!
由于 QωQ 一些机制的问题,它并不能完全地自动订阅事件,你必须告诉程序,你到底把你的事件放在了哪个文件夹里,像这样:
@Override
public void onInitialize() {
ItemInit.ITEMS.register();
EventLoader.initEvent("org.abstruck.qwq.init.event");
}
当然,如果你把你的事件放在了 std.init.event 文件夹下,你可以不必告诉程序你存放事件的位置,因为该文件夹中的类 QωQ 会自动读取。
注意,不要把带有 @Mixin 注释的类和放在被订阅的文件夹下,它会报错的!!!
如果你想使用某个事件,但你发现 QωQ 并没有实现它时,你可以选择自己添加,下面这个例子实现了 Block 中的 afterBreak 事件:
// 记得继承 IEvent 的接口!
public class AfterBreakEvent implements IEvent{
private World world;
private PlayerEntity player;
private BlockPos pos;
private BlockState state;
private BlockEntity blockEntity;
private ItemStack stack;
public AfterBreakEvent(World world, PlayerEntity player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack stack) {
this.world = world;
this.player = player;
this.pos = pos;
this.state = state;
this.blockEntity = blockEntity;
this.stack = stack;
}
public PlayerEntity getPlayer() {
return player;
}
public BlockPos getPos() {
return pos;
}
public BlockState getState(){
reutrn state;
}
public World getWorld() {
return world;
}
public BlockEntity getBlockEntity() {
return blockEntity;
}
public ItemStack getStack() {
return stack;
}
}
当然,仅添加这一代码并不能实现添加新的事件,我们不得不使用 Mixin 来完成这一操作,如下所示:
@Mixin(Block.class)
public abstract class BlockMixin {
@Inject(method = "afterBreak", at = @At("RETURN"))
public void afterBreak(World world, PlayerEntity player, BlockPos pos, BlockState state, BlockEntity blockEntity, ItemStack stack, CallbackInfo ci) {
Block self = (Block) (Object) this;
EventManager.onEventAction(() -> new AfterBreakEvent(world, player, pos, state, blockEntity, stack));
}
}
我们喜欢 Mixin ,但它越少越好对吧?
像这样,就可以简单地新建一个事件了。
当然还有个更简单的方法,就是往这发 Issue ,我会尽可能的添加 Issue 中的所有事件请求。
Q&A
Q:为什么 QωQ 一定要告诉程序事件所在的文件夹?
A:QωQ 订阅事件的原理是扫描某个文件夹下的所有类文件,但如果扫描到了像带有 @Mixin 这种特殊类,便会报很奇怪的错误,目前并没有想到什么解决方法。
Q:QωQ 自带的事件太少了,我可以 Pull Requests 吗?
A:当然,非常欢迎。
Q:QωQ 可以加入 XXX 么?
A:可在评论区或者 Issue 里告诉我