iT邦幫忙

2024 iThome 鐵人賽

DAY 11
0

3D模型匯出

昨天我們將3D模型做好,今天我們可以匯出模型了
https://ithelp.ithome.com.tw/upload/images/20240909/20161797RQyaIO5iwu.png
選擇匯出模型,我們會得到一個JSON檔。
https://ithelp.ithome.com.tw/upload/images/20240909/201617979gRsYTWQYB.png
同時我們也要儲存PNG檔
https://ithelp.ithome.com.tw/upload/images/20240909/20161797JABQcnIKzi.png

我們將匯出的JSON檔命名為staff_of_nature_3d,然後把它放到assets/como/models/item裡面。
png檔丟到texture裡面。

我們的JSON檔看起來會像是這樣
https://ithelp.ithome.com.tw/upload/images/20240909/20161797spxUO9XNus.png

"credit": "Made with Blockbench",
	"texture_size": [32, 32],
	"textures": {
		"0": "como:item/staff_of_nature_3d",
		"particle": "como:item/staff_of_nature_3d"
	},

中間這一段需要改成自己的模型名稱,通常一開始只會有staff_of_nature_3d這一段而已

MIXIN

接下來就是重頭戲,我們的Mixin,Mixin是甚麼,簡單來說就是將你的程式碼注入到遊戲原始碼的某個部分,這就是為什麼較Mix-in。
想要Mixin注入你的程式碼你可以在Mixin中指定注入哪個class中的甚麼方法,並且在方法的頭部、回傳時或是某個程式段落進行注入,因為Mixin注入的時候程式已經經過Java編譯成ByteCode了,所以你也需要通過告訴他你想要的注入點的ByteCode才能成功。
IntelliJ中有查看class的bytecode的方法,在view中的 show bytecode
https://ithelp.ithome.com.tw/upload/images/20240909/20161797jdtRXnHdas.png

接下來的程式碼主要來自這裡,我只做了一點名稱上的修改,解釋這些程式碼的目的是為之後的村民對話框使用到Mixin的部分鋪路。
現在我們需要幾個Mixin,先在java/net/como中建立一個mixin資料夾,其中我們加入ModelLoaderMixin、ItemRendererMixin兩個class,以及一個叫ItemRendererAccessor的Interface
在modelLoaderMixin中我們這樣寫

@Mixin(ModelLoader.class)
public abstract class ModelLoaderMixin {
    @Shadow
    protected abstract void addModel(ModelIdentifier modelId);

    @Inject(method = "<init>", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/model/ModelLoader;addModel(Lnet/minecraft/client/util/ModelIdentifier;)V", ordinal = 3, shift = At.Shift.AFTER))
    public void addStaffofNature(BlockColors blockColors, Profiler profiler, Map<Identifier, JsonUnbakedModel> jsonUnbakedModels, Map<Identifier, List<ModelLoader.SourceTrackedData>> blockStates, CallbackInfo ci) {
        this.addModel(new ModelIdentifier(TheClassicofMountainsandOceans.MOD_ID, "staff_of_nature_3d", "inventory"));
    }
}

@Mixin(ModelLoader.class)代表我們現在要注入的class,而Shadow則是標記了我們會覆蓋的方法,addModel 方法在 ModelLoader 中負責添加模型,因此在這裡標記為 protected abstract,意味著 Mixin 將會使用這個方法來操作模型,但並不需要自己實現它,而是直接使用 ModelLoader 原始類中的實現。
Inject是插入自定義程式碼的意思,Lnet/minecraft/client/render/model/ModelLoader;addModel(Lnet/minecraft/client/util/ModelIdentifier;)V是注射點的Bytecode,ordinal = 3代表他會在ModelLoader 構造方法中第三次調用 addModel 後插入代碼,shift = At.Shift.AFTER:表示將代碼插入到方法調用之後。

下面的addStaffofNature會在Modloader初始化時觸發執行
this.addModel會把我們的模型加入到模組加載器中。

ItemRendererMixin這樣寫

@Mixin(ItemRenderer.class)
public abstract class ItemRendererMixin {
    @ModifyVariable(method = "renderItem", at = @At(value = "HEAD"), argsOnly = true)
    public BakedModel useRubyStaffModel(BakedModel value, ItemStack stack, ModelTransformationMode renderMode, boolean leftHanded, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, int overlay) {
        if (stack.isOf(ModItems.RUBY_STAFF) && renderMode != ModelTransformationMode.GUI) {
            return ((ItemRendererAccessor) this).mccourse$getModels().getModelManager().getModel(new ModelIdentifier(TutorialMod.MOD_ID, "ruby_staff_3d", "inventory"));
        }
        return value;
    }
}

前面是類似的功能,我們加入程式碼到ItemRenderer class中的renderItem的頭部,其中的if判斷如果渲染的物品是自定義的 Ruby Staff 並且當前的渲染模式不是 GUI 模式,就會執行模型替換邏輯。替換邏輯中使用 ItemRendererAccessor 來訪問 ItemRenderer 類中的模型管理器,然後從模型管理器中獲取自定義的 3D 模型 ruby_staff_3d,這個模型會在渲染 Ruby Staff 時使用。

@Mixin(ItemRenderer.class)
public interface ItemRendererAccessor {

    @Accessor("models")
    ItemModels mccourse$getModels();
}

這個interface提供了Accersor功能來讓我們可以訪問原本是被保護或private的變量,在這裡我們訪問的是models變量。

現在我們需要在resources中的.mixins.json檔中加入我們剛剛建立的三個Mixin,

{
	"required": true,
	"package": "net.como.mixin",
	"compatibilityLevel": "JAVA_17",
	"mixins": [
		"ExampleMixin",
		"TradeRenderMixin"
	],
	"client": [
		"ItemRendererAccessor",
		"ItemRendererMixin",
		"ModelLoaderMixin",

	],
	"injectors": {
		"defaultRequire": 1
	}
}

因為我們這裡的Mixin是改變客戶端的模型渲染的部分,記得將三個檔案都加入倒client中。

這樣我們就完成3D模型的部分了,我們可以來看看效果

成果

Yes


上一篇
Minecraft Fabric Mod 模組製作 DAY10
下一篇
Minecraft Fabric Mod 模組製作 DAY12
系列文
Minecraft JAVA Fabric 模組製作 : 成為真正的創世神28
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言