有了昨天的基礎架構後,我們接下來就可以開始整理我們的程式碼了!
Proxy
功能,我們接下來要實際使用它。首先我們先把IProxy
介面填充基本的@EventHandler
三階段方法:
package com.ithome.mymod.proxy;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
public interface IProxy {
/**
* 準備Minecraft的所有物體。舉凡讀取設定檔、建立方塊、物品,註冊物體到Minecraft等。
*
* @param event 事件
*/
void preInit(FMLPreInitializationEvent event);
/**
* 模組設置。例如註冊事件處理、註冊資源、建立配方(合成、燒煉與釀造)。
*
* @param event 事件
*/
void init(FMLInitializationEvent event);
/**
* 與其他模組互動。如果有任何其他需要處理的的功能,或是要建立與其他模組的相依關係。
*
* @param event 事件
*/
void postInit(FMLPostInitializationEvent event);
}
ClientProxy
與ServerProxy
類別會出現紅色底線。在[Day3]也有提到,可以透過Alt+Enter
來讓IDE自動幫我們除錯並填寫缺少的程式碼;這邊的錯誤是因為類別需要實作介面的方法。MyMod
檔案,首先需要將@EventHandler
標註主要會用到的三階段初始化方法加在proxy
變數後面:
@EventHandler
public void preInit(FMLPreInitializationEvent event) {
proxy.preInit(event);
}
@EventHandler
public void init(FMLInitializationEvent event) {
proxy.init(event);
}
@EventHandler
public void postInit(FMLPostInitializationEvent event) {
proxy.postInit(event);
}
這裡我們不需要理會proxy
執行的是ClientProxy還是ServerProxy裡的方法;Forge會依據當前執行時的需求自己去尋找!init()
方法內,這個昨天有提到;另外事件的處理是屬於Client端的程式碼,所以我們需要將這部分的邏輯搬到ClientProxy
檔案內。
com.ithome.mymod.events
套件目錄,並且將BlockBreakEvent
檔案移動到這個目錄下:BlockBreakEvent
從主程式中移除,但我們之後會有另外一種自定義設定的方式來處理同性質的事件要如何變成可以在遊戲內選擇,這邊就先全部都加回來。public class BlockBreakEvent {
@SubscribeEvent
public void sendMessage(BreakEvent event) {
...(略)
}
@SubscribeEvent
public void explodeOre(BreakEvent event) {
...(略)
}
}
register
搬移。我們直接到Client端ClientProxy
檔案的init()
動作內加上:
@Override
public void init(FMLInitializationEvent event) {
MinecraftForge.EVENT_BUS.register(new BlockBreakEvent());
}
註冊我們Client端會使用到的事件。TNTExplosions
檔案到events
目錄下,並且在ClientProxy
中註冊:package com.ithome.mymod.events;
import net.minecraft.entity.Entity;
import net.minecraft.entity.item.EntityTNTPrimed;
import net.minecraft.util.BlockPos;
import net.minecraft.util.Vec3;
import net.minecraftforge.event.entity.EntityJoinWorldEvent;
import net.minecraftforge.event.world.ExplosionEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import java.util.List;
public class TNTExplosions {
// 威力使用20格
private float power = 20;
@SubscribeEvent
public void explodeHead(EntityJoinWorldEvent event) {
// 只處理加入到世界的實體是TNT : 這裡即是指TNT方塊被啟動後閃爍的TNT"實體"
if (event.entity instanceof EntityTNTPrimed) {
Entity entity = event.entity;
// 建立我們想要的爆炸威力
event.entity.worldObj.createExplosion(
entity,
entity.posX,
entity.posY,
entity.posZ,
power,
true
);
}
}
@SubscribeEvent
public void explodeTunnel(ExplosionEvent.Detonate event) {
if (event.world.isRemote) {
return;
}
Vec3 eventPos = event.explosion.getPosition();
event.getAffectedBlocks().clear();
int height = 6;
int depth = 20;
toCave(event.getAffectedBlocks(), eventPos, height, depth);
}
private void toCave(List<BlockPos> affectBlocks, Vec3 originPos, int height, int depth) {
for (int x = -height; x <= height; x++) {
for (int y = -height; (y <= x && x <= 0) || (Math.abs(y) >= x && x > 0); y++) {
int trueY = height - Math.abs(y);
for (int z = 0; z <= depth; z++) {
BlockPos b = new BlockPos(originPos.xCoord + x, originPos.yCoord + trueY, originPos.zCoord + z);
affectBlocks.add(b);
}
}
}
}
}
ClientProxy.java
package com.ithome.mymod.proxy;
import com.ithome.mymod.events.BlockBreakEvent;
import com.ithome.mymod.events.TNTExplosions;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
public class ClientProxy implements IProxy {
@Override
public void preInit(FMLPreInitializationEvent event) {
}
@Override
public void init(FMLInitializationEvent event) {
MinecraftForge.EVENT_BUS.register(new BlockBreakEvent());
MinecraftForge.EVENT_BUS.register(new TNTExplosions());
}
@Override
public void postInit(FMLPostInitializationEvent event) {
}
}
SuperJump
與在ClientProxy
內註冊事件。好了,最後你的結構應該會比較乾淨一些了:
檔案結構
ClientProxy的init()方法
@Override
public void init(FMLInitializationEvent event) {
MinecraftForge.EVENT_BUS.register(new BlockBreakEvent());
MinecraftForge.EVENT_BUS.register(new TNTExplosions());
MinecraftForge.EVENT_BUS.register(new PigDroppingItems());
MinecraftForge.EVENT_BUS.register(new ZombieKnights());
MinecraftForge.EVENT_BUS.register(new SuperJump());
FMLCommonHandler.instance().bus().register(new SuperJump());
}