上次講到BuildCraft的機器人會因為chunk unload而消失的問題, 果然是BUG!
在官網的 6.3.0 Beta 版更新記錄有寫到:
[#2201] SMP Robots break to item or disapear when a chunk is unloaded (hea3ven)
不過, 我現在還不敢使用機器人, 因為我自己用生存模式在玩的, 鑽石沒那麼好挖, 做一台機器人要用到1顆鑽石, 如果還繼續來這種BUG, 我吃不消.
而且, 流體導管目前還是有一個外觀BUG存在, 在某些時候, 輸送長距離的流體時, 如果流體輸送完了, 有可能在管路的中段看到有殘留的流體停在那裡, 重開遊戲後就不會看到了, 這算是伺服端沒有把資料完全傳送到客端所導致的情形, 這種問題以前我在寫模組時也遇過, 不知道BC的維護人員是否有注意到這問題.
現在都用最基本的玩法, 較少使用BC了, 頂多是拿泵浦來抽岩漿給我的超大容量容器使用而已. 不過, 只是要抽流體這功能卻要裝BC, 讓我感到有點麻煩, 有點想自己製作一台流體抽取機, 至少我已經了解BC的泵浦運作原理(懂原理要做什麼都會很簡單), 要寫的話是可以做到.
最近完成的「大容量單體倉庫」終於幫我解決了生存模式裡最頭痛的問題, 就是
"同一類方塊太多, 麥塊的大箱子也不夠裝", 現在我可以帶著單體倉庫到地底開心的挖礦, 不用擔心背包空間不足放鵝卵石. 挖礦裡最常遇到大量的方塊有鵝卵石、煤礦、鐵礦這三類, 如果沒使用老外做的Backpack模組(我也沒在用
), 三不五時就要跑回家一趟放道具.
在改良"大容量單體倉庫"時, 我需要一種功能, 能把
目前座標的面向找出想要的面向所在座標, 在Forge源碼裡應該有這種函式(旋轉矩陣)可以用, 但我看不懂
, 所以我自己寫了一個,
簡單易懂易使用.
這個自製函式的功能白話來講就是 "不論目前面向轉向哪裡, 都能求出指定的面向所在座標".
/**
* 自訂面向轉換座標 (以北為基準方向)
* @author unoya
*
*/
public class DirectionTransfer {
private int tPosX = 0;
private int tPosY = 0;
private int tPosZ = 0;
/**
* 轉換輸入的座標與面向, 求出指定座標
* @param x 原始X座標
* @param y 原始Y座標
* @param z 原始Z座標
* @param sourceface 來源面向 (0代表面朝南, 1代表面朝西, 2代表面朝北, 3代表面朝東)
* @param side 求出位於方塊面的座標 (0代表下面, 1代表上面, 2代表前方, 3代表後方, 4代表左方, 5代表右方)
*/
public DirectionTransfer(int x, int y , int z, int sourceface, int side){
int transside = -1;
switch(sourceface){
case 0:
transside = side == 2 ? 3 : side == 3 ? 2 : side == 4 ? 5 : side == 5 ? 4 : side == 1 ? 1 : 0;
break;
case 1:
transside = side == 2 ? 4 : side == 3 ? 5 : side == 4 ? 3 : side == 5 ? 2 : side == 1 ? 1 : 0;
break;
case 2:
transside = side == 2 ? 2 : side == 3 ? 3 : side == 4 ? 4 : side == 5 ? 5 : side == 1 ? 1 : 0;
break;
case 3:
transside = side == 2 ? 5 : side == 3 ? 4 : side == 4 ? 2 : side == 5 ? 3 : side == 1 ? 1 : 0;
break;
default:
}
switch(transside){
case 0:
this.tPosX = x;
this.tPosY = --y;
this.tPosZ = z;
break;
case 1:
this.tPosX = x;
this.tPosY = ++y;
this.tPosZ = z;
break;
case 2:
this.tPosX = x;
this.tPosY = y;
this.tPosZ = --z;
break;
case 3:
this.tPosX = x;
this.tPosY = y;
this.tPosZ = ++z;
break;
case 4:
this.tPosX = --x;
this.tPosY = y;
this.tPosZ = z;
break;
case 5:
this.tPosX = ++x;
this.tPosY = y;
this.tPosZ = z;
break;
default: // 當來源面向指定錯誤時,三座標都傳回0
this.tPosX = 0;
this.tPosY = 0;
this.tPosZ = 0;
}
}
/**
* 傳回目標的X座標
* @return 整數值
*/
public int getPosX(){
return this.tPosX;
}
/**
* 傳回目標的Y座標
* @return 整數值
*/
public int getPosY(){
return this.tPosY;
}
/**
* 傳回目標的Z座標
* @return 整數值
*/
public int getPosZ(){
return this.tPosZ;
}
}
例如現在有一個方塊座標在 x=10, y=64, z=15, 它的面向是朝南(也就是面對著我), 我想求出它在原座標旋轉面向到朝東(依然面對著我)的時候, 它的後面(也就是此方塊的前方)有什麼方塊, 在求出此目標方塊之前, 當然就是要求出原方塊後方的座標是多少.
使用方式可以這麼做:
DirectionTransfer dt = new DirectionTransfer(10, 64, 15, 3, 2);
Block testblock = world, getBlock(dt.getPosX, dt.getPosY, dt.getPosZ);
就這樣子兩行程式碼解決了我想求出的答案!
第一段程式碼是先宣告一個DirectionTransfer實例, 並定義X座標為10, Y座標為64, Z座標為15, 來源面向朝東(3), 目標方塊位置在背後(2).
當實例產生後會立即求出指定面向的座標, 可以利用get來取出座標值, 我是定義為 getPosX, getPosY, getPosZ 這三個.
第二段程式碼是使用Forge的函式, 依照座標去求出該座標有什麼方塊, 如果沒有任何方塊存在, testblock 會是 Blocks.Air 的型態. 但通常我會在下面加這一段:
if (testblock == null || testblock == Blocks.Air) return;
這句語法代表, 如果testblock是空的, 或者是Blocks.Air型態, 就不繼續執行下去, 直接結束此函式的運作.
因為麥塊的內建熔爐基本上在擺放時只有 4 種面向(朝東,朝西,朝南,朝北), 當我要使用"超大容量容器"來輸入岩漿做燃料時, 因為我限定容器只能在左側或右側輸入燃料, 所以我需要判斷容器現在的面向的左右兩側有沒有熔爐, 這個自訂函式就能應用在這裡了.
我相信Forge裡有很多可以節省模組開發時間的函式
(有是有, 但難理解), 但我還沒學會使用, 所以有些東西我還是得自己寫才會容易做容易瞭解.