Java 接口(进阶)
用车包就不需要这一页。写成附属模组的好处是能和自己模组的其他内容放在一起,资源和车包完全一样(只是放在模组的 src/main/resources 里)。示例工程是 VetturaExample。
准备工程
- 复制
VetturaExample整个文件夹,改gradle.properties里的mod_id、mod_name、mod_group_id,再把 Java 包名和assets/vettura_example、data/vettura_example文件夹改成你的模组 ID。 gradle.properties里的vettura_repo和vextris_repo指向两个库的 Maven 仓库(示例里是本地文件夹;正式发布后改成线上地址)。build.gradle用implementation fg.deobf(...)依赖 Vettura 和 Vextris:开发环境里它们作为独立模组加载,不要把它们打进你的 jar。META-INF/mods.toml要声明依赖vettura,ordering="AFTER"。- 开发环境需要的两行 mixin 属性已经写在示例的
build.gradle里(mixin.env.remapRefMap、mixin.env.refMapRemappingFile),不要删。
编译:.\gradlew.bat build。启动客户端:.\gradlew.bat runClient。
注册(四件东西)
示例代码在 src/main/java/com/example/vetturaexample/VetturaExample.java,顺序不能乱:
java
// 1. 车型:物理参数、车身布局、声音、损伤界面的玻璃位置。必须在实体类型创建之前注册
public static final VehicleType COUPE = VehicleType.builder(COUPE_ID)
.spec(coupeSpec())
.layout(coupeLayout())
.hudPanes(...) // 可选
.sounds(...) // 可选,不写就用 T15 的柴油机声音
.fuel(Fuel.PETROL) // 可选,不写是柴油
.keyless() // 可选:一键启动(钥匙带在身上,按住启动键);不写是插钥匙、拧钥匙
.paints(List.of(new VehicleSpawnerItem.Paint("my_red", 0xA51616, 0xA51616), ...)) // 可选:出厂漆色(主色、副色),至少两种
.handbrake(null, null) // 可选:手刹拉起、放下的声音;null 表示不响(电子手刹);不写是 T15 的棘轮手刹
.shiftSound(null) // 可选:换挡声;null 表示不响(自动挡);不写是 T15 的换挡杆声
.register();
// 2. 实体类型:就是 Vettura 的载具实体,ID 和车型相同
ENTITY_TYPES.register("whitebox_coupe",
() -> EntityType.Builder.<PickupTruckEntity>of(PickupTruckEntity::new, MobCategory.MISC)
.sized(1.9F, 1.4F).clientTrackingRange(10).build("whitebox_coupe"));
// 3. 生成器和钥匙
ITEMS.register("whitebox_coupe", () -> new VehicleSpawnerItem(new Item.Properties().stacksTo(1), COUPE_ENTITY));
ITEMS.register("whitebox_coupe_key", () -> new VehicleKeyItem(new Item.Properties().stacksTo(1), COUPE_ID));
// 4. 客户端:用 Vettura 的渲染器
event.registerEntityRenderer(COUPE_ENTITY.get(), PickupTruckRenderer::new);实体通过实体类型的 ID 找到车型(VehicleType.of),所以两者的 ID 必须一致。实体的 sized 只影响原版的选取框和寻路,真正的碰撞来自车身布局和碰撞外壳。

