「Modding/TurtleUpgrade」の編集履歴(バックアップ)一覧はこちら
追加された行は緑色になります。
削除された行は赤色になります。
ComputerCraftにTurtleアップグレードを追加するModの製作について解説する。
&color(red){対象:Minecraft Forgeを利用して独自のレシピを追加できるようなModding初級者以上。}
参考資料:
-[[Minecraft Midding Wiki>http://minecraftjp.info/modding/index.php/Minecraft_Modding_Wiki]]
--[[チュートリアル一覧: MinecraftForgeUniversal>http://minecraftjp.info/modding/index.php/%E3%83%81%E3%83%A5%E3%83%BC%E3%83%88%E3%83%AA%E3%82%A2%E3%83%AB%E4%B8%80%E8%A6%A7#MinecraftForgeUniversal]]
-[[ComputerCraft Forums: Peripherals and Turtle Upgrades>http://www.computercraft.info/forums2/index.php?/forum/17-]]
--[[Creating Peripherals and Turtle Upgrades>http://www.computercraft.info/forums2/index.php?/topic/606-]]
-[[ComputerCraft Wiki: Turtle Upgrade IDs>http://www.computercraft.info/wiki/index.php?title=Turtle_Upgrade_IDs]]
-[[Minecraft Forge: Tutorials>http://www.minecraftforge.net/wiki/Category:Tutorials]]
執筆時のバージョン:
-ComputerCraft 1.52 for Minecraft 1.5.1
----
#contents
----
*Turtleアップグレード追加Modの概要
Turtleアップグレードとは、Digging TurtleやCrafty Turtleのように、Turtleにアイテムやブロックを装着(クラフト)することによって機能を追加することができるシステムである。
**アップグレードの実装
TurtleアップグレードはITurtleUpgradeインターフェイスの実装クラスとして機能を実装し、その実装クラスをComputerCraftに登録することによってTurtleに装着できるようになる。機能追加に関するAPIも用意されているため、簡単に作ることができる。
**アップグレードのタイプ
Turtleアップグレードには以下の2タイプがある。
-[[turtle.digやturtle.attack>API/Turtle]]で作動する&bold(){Tool}タイプ(例:ダイヤシャベルでDigging Turtle)
-[[Peripheral API>API/Peripheral]]で作動する&bold(){Peripheral}タイプ(例:作業台でCrafty Turtle)
Turtleアップグレードを製作するときは、どちらか一方のタイプを選択する必要がある。今のところ1つのTurtleには、1つのToolタイプと1つのPeripheralタイプ、または2つのPeripheralタイプを装着することができる(例:ダイヤクワ(Tool)とWireless Modem(Peripheral)でWireless Farming Turtle)。
**アップグレードID
Turtleアップグレードには他のTurtleアップグレードと重複しないID番号を割り当てる必要がある。Mod製作者が割り当て可能なIDの範囲は【-1.52】では64~255、【1.53-】では64~32767である。既に配布されているModが使用しているTurtleアップグレードIDは[[ComputerCraft Wiki>http://www.computercraft.info/wiki/index.php?title=Turtle_Upgrade_IDs]]で確認することができる。
*基本的なTurtleアップグレード追加Modの例
ToolタイプとPeripheralタイプのTurtleアップグレードを追加する。
このサンプルは以下の4クラスからなる。
-BasicUpgrades
-TurtleBasicTool
-TurtleBasicPeripheral
-PeripheralTurtleBasicPeripheral
簡略化のため[[Proxyシステム>http://minecraftjp.info/modding/index.php/%E3%83%97%E3%83%AD%E3%82%AD%E3%82%B7%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6]]は利用していない。
なお、このサンプルmodの前提modは【MinecraftForge】と【ComputerCraft】である。
**BasicUpgrades.java
Modのメインクラス。@ModアノテーションによりForgeModLoaderにロードされる。
#highlight(java){{
package sample.upgrade;
import net.minecraftforge.common.Configuration;
import net.minecraftforge.common.Property;
import cpw.mods.fml.common.Loader;
import cpw.mods.fml.common.Mod;
import cpw.mods.fml.common.event.FMLInitializationEvent;
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
import cpw.mods.fml.common.network.NetworkMod;
import dan200.turtle.api.TurtleAPI;
@Mod(modid="BasicUpgrades", name="BasicUpgrades", version="0.0.0", dependencies="after:CCTurtle")
@NetworkMod(clientSideRequired=true, serverSideRequired=false)
public class BasicUpgrades {
public static int basicToolUpgradeID;
public static int basicPeripheralUpgradeID;
@Mod.PreInit
public void preInit(FMLPreInitializationEvent event)
{
Property Prop;
Configuration cfg = new Configuration(event.getSuggestedConfigurationFile());
cfg.load();
Prop = cfg.get("upgrade", "basicToolUpgradeID", 110);
basicToolUpgradeID = Prop.getInt();
Prop = cfg.get("upgrade", "basicPeripheralUpgradeID", 111);
basicPeripheralUpgradeID = Prop.getInt();
cfg.save();
}
@Mod.Init
public void init(FMLInitializationEvent event)
{
TurtleAPI.registerUpgrade(new TurtleBasicTool());
TurtleAPI.registerUpgrade(new TurtleBasicPeripheral());
}
} }}
@Modアノテーションを付加したクラスがForge Mod Loaderにロードされる。ここでModの情報も登録している。特筆すべきは&bold(){dependencies="after:CCTurtle"}という値で、これはこのModをComputerCraftよりも後に読み込ませる効果がある。
@Mod.PreInitアノテーションを付加したメソッド&bold(){preInit}(@Mod.Initメソッドの前に呼び出される)でコンフィグファイルを読み込み、TurtleアップグレードIDのブロックIDを取得している。ToolアップグレードIDのデフォルト値は&bold(){110}、PeripheralアップグレードIDのデフォルト値は&bold(){111}。
@Mod.Initアノテーションを付加したメソッド&bold(){init}(初期化時に呼び出される)でComputerCraftにTurtleアップグレードを登録している。TurtleアップブレードのクラスをTurtleAPI.registerUpgrade()で登録することにより、そのTurtleアップグレードがゲーム中で使用可能になる。
**TurtleBasicTool.java
ITurtleUpgradeの実装クラスでToolタイプのTurtleアップグレードを実装している。このクラスで、アップグレードをTurtleに装着するためのアイテム(装着レシピはComputerCraftによる自動追加)や、装着後の外観、採掘・攻撃時の動作などを指定することができる。
このサンプルでは、簡単な採掘と攻撃ができるようになっている。
#highlight(java){{
package sample.upgrade;
import java.util.ArrayList;
import java.util.Iterator;
import net.minecraft.block.Block;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Facing;
import net.minecraft.util.Icon;
import net.minecraft.util.Vec3;
import net.minecraft.world.World;
import dan200.computer.api.IHostedPeripheral;
import dan200.turtle.api.ITurtleAccess;
import dan200.turtle.api.ITurtleUpgrade;
import dan200.turtle.api.TurtleSide;
import dan200.turtle.api.TurtleUpgradeType;
import dan200.turtle.api.TurtleVerb;
public class TurtleBasicTool implements ITurtleUpgrade
{
public ItemStack upgradeItem = new ItemStack(Item.pickaxeGold);
@Override
public int getUpgradeID()
{
return BasicUpgrades.basicToolUpgradeID;
}
@Override
public String getAdjective()
{
return "Tool";
}
@Override
public TurtleUpgradeType getType()
{
return TurtleUpgradeType.Tool;
}
@Override
public ItemStack getCraftingItem()
{
return upgradeItem;
}
@Override
public boolean isSecret()
{
return false;
}
@Override
public IHostedPeripheral createPeripheral(ITurtleAccess turtle,
TurtleSide side)
{
return null;
}
@Override
public boolean useTool(ITurtleAccess turtle, TurtleSide side,
TurtleVerb verb, int direction)
{
switch( verb )
{
case Dig:
return dig(turtle, direction);
case Attack:
return attack(turtle, direction);
}
return false;
}
private boolean dig(ITurtleAccess turtle, int dir)
{
World world = turtle.getWorld();
Vec3 position = turtle.getPosition();
if (position == null)
{
return false;
}
int newX = (int)position.xCoord + Facing.offsetsXForSide[dir];
int newY = (int)position.yCoord + Facing.offsetsYForSide[dir];
int newZ = (int)position.zCoord + Facing.offsetsZForSide[dir];
if ( (newY < 0) || (newY >= world.getHeight()) )
{
return false;
}
int blockID = world.getBlockId(newX, newY, newZ);
Block block = Block.blocksList[blockID];
if ( (blockID == 0)
|| (blockID == Block.bedrock.blockID)
|| (block.getBlockHardness(world, newX, newY, newZ) <= -1.0F)
)
{
return false;
}
int matadata = world.getBlockMetadata(newX, newY, newZ);
ArrayList items = block.getBlockDropped(world, newX, newY, newZ, matadata, 0);
Iterator it = items.iterator();
while (it.hasNext())
{
ItemStack item = (ItemStack)it.next();
if ( !turtle.storeItemStack(item) )
{
int[] oppositeSide = { 1, 0, 3, 2, 5, 4 };
if ( !turtle.dropItemStack(item, oppositeSide[turtle.getFacingDir()]) )
{
turtle.dropItemStack(item, turtle.getFacingDir());
}
}
}
world.playAuxSFX(2001, newX, newY, newZ, blockID + matadata * 4096);
world.setBlock(newX, newY, newZ, 0, 0, 3);
return true;
}
private boolean attack(ITurtleAccess turtle, int dir)
{
return turtle.attackWithItemStack(new ItemStack(Item.swordDiamond), dir, 2.0F);
}
@Override
public Icon getIcon(ITurtleAccess turtle, TurtleSide side) {
return upgradeItem.getIconIndex();
}
} }}
TurtleアップグレードIDはgetUpgradeIDの戻り値で指定する。このサンプルでは前述の@MODクラスBasicUpgradesのメンバー変数から取得して指定している。アップグレードのタイプはenum TurtleUpgradeTypeの列挙子でToolを指定。装着したTurtleに付く形容詞は"Tool"を指定(つまり"Tool Turtle"になる)。クラフトに必要なアイテムと装着したアップグレードの外観は金のツルハシ。Toolタイプなので無用なcreatePeripheralではnullを返す。
Toolタイプの本領はuseToolによって発揮される。このサンプルではverbの種類(DigかAttackか)で分岐させた後、それぞれ別のメンバー関数(digとattack)に処理させている。
-dig
Turtleに採掘させる場合、採掘に必要な処理そのものを書く必要がある。
まず、useToolから得たITurtleAccess turtleによりTurtleの座標を得て、その座標と採掘する方向dirから採掘すべきブロックの座標と種類、メタデータを取得する。次に、採掘すべきブロックが採掘できるか(高度、種類)を調べる。採掘可能だった場合は採掘して得られるアイテムを取得し、スロットに入りきらなかった場合はドロップする。最後に採掘の効果音を鳴らし、採掘したブロックを消す(空気ブロックにする)。
-attack
採掘処理が難しい一方で、攻撃は専用メソッドが用意されているため簡単である。このサンプルではダイヤソードの2倍の攻撃力14(ハート7個分)でdir方向を攻撃する。
ちなみに、それぞれのverdは単にTurtle側のturtle.dig()とturtle.attack()で呼び出されるというだけで、必ずしもTurtleが採掘や攻撃を行わなければならないという訳ではない。
**TurtleBasicPeripheral.java
ITurtleUpgradeの実装クラスでPeripheralタイプのTurtleアップグレードを実装している。
#highlight(java){{
package sample.upgrade;
import net.minecraft.block.Block;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Icon;
import dan200.computer.api.IHostedPeripheral;
import dan200.turtle.api.ITurtleAccess;
import dan200.turtle.api.ITurtleUpgrade;
import dan200.turtle.api.TurtleSide;
import dan200.turtle.api.TurtleUpgradeType;
import dan200.turtle.api.TurtleVerb;
public class TurtleBasicPeripheral implements ITurtleUpgrade
{
public ItemStack upgradeItem = new ItemStack(Block.stone, 1, 0);
@Override
public int getUpgradeID() {
return BasicUpgrades.basicPeripheralUpgradeID;
}
@Override
public String getAdjective() {
return "Peripheral";
}
@Override
public TurtleUpgradeType getType() {
return TurtleUpgradeType.Peripheral;
}
@Override
public ItemStack getCraftingItem() {
return upgradeItem;
}
@Override
public boolean isSecret() {
return false;
}
@Override
public IHostedPeripheral createPeripheral(ITurtleAccess turtle,
TurtleSide side) {
return new PeripheralTurtleBasicPeripheral(turtle, side);
}
@Override
public boolean useTool(ITurtleAccess turtle, TurtleSide side,
TurtleVerb verb, int direction) {
return false;
}
@Override
public Icon getIcon(ITurtleAccess turtle, TurtleSide side) {
return Block.stoneSingleSlab.getBlockTextureFromSide(0);
}
} }}
TurtleアップグレードIDはgetUpgradeIDの戻り値で指定する。このサンプルでは前述の@MODクラスBasicUpgradesのメンバー変数から取得して指定している。アップグレードのタイプはenum TurtleUpgradeTypeの列挙子でPeripheralを指定。装着したTurtleに付く形容詞は"Peripheral"を指定(つまり"Peripheral Turtle"になる)。クラフトに必要なアイテムは石ブロック。装着したアップグレードの外観は石ハーフブロックの下面。
Peripheralタイプなので、createPeripheralでは周辺機器の機能を実装したIHostedPeripheralの実装クラスのインスタンスを返す。このサンプルでは、後述のPeripheralTurtleBasicPeripheralのインスタンスを返している。ToolタイプではないのでuseToolは呼び出されない。
**PeripheralTurtleBasicPeripheral.java
IHostedPeripheralの実装クラスでPeripheralタイプのアップグレードの周辺機器としての動作を実装している。IHostedPeripheralはIPeripheralのサブインターフェイスである。[[周辺機器ブロック追加Mod>Modding/Peripheral]]も参照のこと。
#highlight(java){{
package sample.upgrade;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.Vec3;
import dan200.computer.api.IComputerAccess;
import dan200.computer.api.IHostedPeripheral;
import dan200.turtle.api.ITurtleAccess;
import dan200.turtle.api.TurtleSide;
public class PeripheralTurtleBasicPeripheral implements IHostedPeripheral
{
private ITurtleAccess m_turtle;
private IComputerAccess m_computer;
private TurtleSide m_side;
PeripheralTurtleBasicPeripheral(ITurtleAccess turtle, TurtleSide side)
{
m_turtle = turtle;
m_side = side;
}
@Override
public String getType()
{
return "turtlebasic";
}
@Override
public String[] getMethodNames()
{
return new String[] { "test", "getPosition" };
}
@Override
public Object[] callMethod( IComputerAccess computer, int method, Object[] arguments )
throws Exception
{
switch( method )
{
case 0:
// test
if( arguments.length < 1 ) {
throw new Exception("Expected argument");
}
return new Object[] { arguments[0] };
case 1:
//getPosition
Vec3 pos = m_turtle.getPosition();
if( arguments.length > 0
&& arguments[0] instanceof Boolean
&& true == (Boolean)arguments[0])
{
return new Object[] {
"Position: " + (int)pos.xCoord
+ ", " + (int)pos.yCoord
+ ", " + (int)pos.zCoord
};
}
return new Object[] {
Integer.valueOf((int)pos.xCoord),
Integer.valueOf((int)pos.yCoord),
Integer.valueOf((int)pos.zCoord)
};
}
return null;
}
@Override
public boolean canAttachToSide(int side)
{
return true;
}
@Override
public void attach( IComputerAccess computer)
{
m_computer = computer;
System.out.printf("[TurtleBasicPeripheral] Attached to Computer #%d (side: %s)\n",
m_computer.getID(), m_computer.getAttachmentName()
);
}
@Override
public void detach( IComputerAccess computer )
{
System.out.printf("[TurtleBasicPeripheral] Detached from Computer #%d\n",
computer.getID()
);
}
@Override
public void update()
{
}
@Override
public void readFromNBT(NBTTagCompound nbttagcompound) {
}
@Override
public void writeToNBT(NBTTagCompound nbttagcompound) {
}
} }}
[[周辺機器ブロック追加Mod>Modding/Peripheral]]と似たような構成になっているが、以下のような点が違う。
-attachはTurtle起動時、detachはattach後のTurtle破壊時に呼び出される(Turtleアップグレードの特徴)
-attach後に毎Tick呼び出されるupdateが追加されている(IHostedPeripheralの特徴)
-NBTへデータを読み書きするメソッドが追加されている(IHostedPeripheralの特徴)
このサンプルではタートルへのアクセスインターフェイスを取得するために、引数付きのコンストラクタを追加している。これは周辺機器側からタートルへアクセスするのに必要である。また、attach時にTurtle内のComputerのアクセスインターフェイスを取得している。周辺機器ブロックと違い、アップグレード周辺機器に接続するのは装着されたTurtleだけなので、それらは単なるメンバ変数に保存している。
周辺機器のメソッドとして、[[周辺機器ブロック追加Mod>Modding/Peripheral]]のサンプルと同様の"test"と、Turtleの座標を取得する"getPosition"を実装している。getPositionは引数にtrueを指定して呼ばれた時は座標を文字列にして返し、それ以外のときは座標を3つの数値で返す(サンプルではあるが、GPSから考えればチート性能なメソッドである)。
ComputerCraftにTurtleアップグレードを追加するModの製作について解説する。
&color(red){対象:Minecraft Forgeを利用して独自のレシピを追加できるようなModding初級者以上。}
参考資料:
-[[Minecraft Midding Wiki>http://minecraftjp.info/modding/index.php/Minecraft_Modding_Wiki]]
--[[チュートリアル一覧: MinecraftForgeUniversal>http://minecraftjp.info/modding/index.php/%E3%83%81%E3%83%A5%E3%83%BC%E3%83%88%E3%83%AA%E3%82%A2%E3%83%AB%E4%B8%80%E8%A6%A7#MinecraftForgeUniversal]]
-[[ComputerCraft Forums: Peripherals and Turtle Upgrades>http://www.computercraft.info/forums2/index.php?/forum/17-]]
--[[Creating Peripherals and Turtle Upgrades>http://www.computercraft.info/forums2/index.php?/topic/606-]]
-[[ComputerCraft Wiki: Turtle Upgrade IDs>http://www.computercraft.info/wiki/index.php?title=Turtle_Upgrade_IDs]]
-[[Minecraft Forge: Tutorials>http://www.minecraftforge.net/wiki/Category:Tutorials]]
執筆時のバージョン:
-ComputerCraft 1.53 for Minecraft 1.5.2
----
#contents
----
*Turtleアップグレード追加Modの概要
Turtleアップグレードとは、Digging TurtleやCrafty Turtleのように、Turtleにアイテムやブロックを装着(クラフト)することによって機能を追加することができるシステムである。
**アップグレードの実装
TurtleアップグレードはITurtleUpgradeインターフェイスの実装クラスとして機能を実装し、その実装クラスをComputerCraftに登録することによってTurtleに装着できるようになる。機能追加に関するAPIも用意されているため、簡単に作ることができる。
**アップグレードのタイプ
Turtleアップグレードには以下の2タイプがある。
-[[turtle.digやturtle.attack>API/Turtle]]で作動する&bold(){Tool}タイプ(例:ダイヤシャベルでDigging Turtle)
-[[Peripheral API>API/Peripheral]]で作動する&bold(){Peripheral}タイプ(例:作業台でCrafty Turtle)
Turtleアップグレードを製作するときは、どちらか一方のタイプを選択する必要がある。今のところ1つのTurtleには、1つのToolタイプと1つのPeripheralタイプ、または2つのPeripheralタイプを装着することができる(例:ダイヤクワ(Tool)とWireless Modem(Peripheral)でWireless Farming Turtle)。
**アップグレードID
Turtleアップグレードには他のTurtleアップグレードと重複しないID番号を割り当てる必要がある。Mod製作者が割り当て可能なIDの範囲は【-1.52】では64~255、【1.53-】では64~32767である。既に配布されているModが使用しているTurtleアップグレードIDは[[ComputerCraft Wiki>http://www.computercraft.info/wiki/index.php?title=Turtle_Upgrade_IDs]]で確認することができる。
*基本的なTurtleアップグレード追加Modの例
ToolタイプとPeripheralタイプのTurtleアップグレードを追加する。
このサンプルは以下の4クラスからなる。
-BasicUpgrades
-TurtleBasicTool
-TurtleBasicPeripheral
-PeripheralTurtleBasicPeripheral
簡略化のため[[Proxyシステム>http://minecraftjp.info/modding/index.php/%E3%83%97%E3%83%AD%E3%82%AD%E3%82%B7%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6]]は利用していない。
なお、このサンプルmodの前提modは【MinecraftForge】と【ComputerCraft】である。
**BasicUpgrades.java
Modのメインクラス。@ModアノテーションによりForgeModLoaderにロードされる。
#highlight(java){{
package sample.upgrade;
import net.minecraftforge.common.Configuration;
import net.minecraftforge.common.Property;
import cpw.mods.fml.common.Loader;
import cpw.mods.fml.common.Mod;
import cpw.mods.fml.common.event.FMLInitializationEvent;
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
import cpw.mods.fml.common.network.NetworkMod;
import dan200.turtle.api.TurtleAPI;
@Mod(modid="BasicUpgrades", name="BasicUpgrades", version="0.0.0", dependencies="after:CCTurtle")
@NetworkMod(clientSideRequired=true, serverSideRequired=false)
public class BasicUpgrades {
public static int basicToolUpgradeID;
public static int basicPeripheralUpgradeID;
@Mod.PreInit
public void preInit(FMLPreInitializationEvent event)
{
Property Prop;
Configuration cfg = new Configuration(event.getSuggestedConfigurationFile());
cfg.load();
Prop = cfg.get("upgrade", "basicToolUpgradeID", 110);
basicToolUpgradeID = Prop.getInt();
Prop = cfg.get("upgrade", "basicPeripheralUpgradeID", 111);
basicPeripheralUpgradeID = Prop.getInt();
cfg.save();
}
@Mod.Init
public void init(FMLInitializationEvent event)
{
TurtleAPI.registerUpgrade(new TurtleBasicTool());
TurtleAPI.registerUpgrade(new TurtleBasicPeripheral());
}
} }}
@Modアノテーションを付加したクラスがForge Mod Loaderにロードされる。ここでModの情報も登録している。特筆すべきは&bold(){dependencies="after:CCTurtle"}という値で、これはこのModをComputerCraftよりも後に読み込ませる効果がある。
@Mod.PreInitアノテーションを付加したメソッド&bold(){preInit}(@Mod.Initメソッドの前に呼び出される)でコンフィグファイルを読み込み、TurtleアップグレードIDのブロックIDを取得している。ToolアップグレードIDのデフォルト値は&bold(){110}、PeripheralアップグレードIDのデフォルト値は&bold(){111}。
@Mod.Initアノテーションを付加したメソッド&bold(){init}(初期化時に呼び出される)でComputerCraftにTurtleアップグレードを登録している。TurtleアップブレードのクラスをTurtleAPI.registerUpgrade()で登録することにより、そのTurtleアップグレードがゲーム中で使用可能になる。
**TurtleBasicTool.java
ITurtleUpgradeの実装クラスでToolタイプのTurtleアップグレードを実装している。このクラスで、アップグレードをTurtleに装着するためのアイテム(装着レシピはComputerCraftによる自動追加)や、装着後の外観、採掘・攻撃時の動作などを指定することができる。
このサンプルでは、簡単な採掘と攻撃ができるようになっている。
#highlight(java){{
package sample.upgrade;
import java.util.ArrayList;
import java.util.Iterator;
import net.minecraft.block.Block;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Facing;
import net.minecraft.util.Icon;
import net.minecraft.util.Vec3;
import net.minecraft.world.World;
import dan200.computer.api.IHostedPeripheral;
import dan200.turtle.api.ITurtleAccess;
import dan200.turtle.api.ITurtleUpgrade;
import dan200.turtle.api.TurtleSide;
import dan200.turtle.api.TurtleUpgradeType;
import dan200.turtle.api.TurtleVerb;
public class TurtleBasicTool implements ITurtleUpgrade
{
public ItemStack upgradeItem = new ItemStack(Item.pickaxeGold);
@Override
public int getUpgradeID()
{
return BasicUpgrades.basicToolUpgradeID;
}
@Override
public String getAdjective()
{
return "Tool";
}
@Override
public TurtleUpgradeType getType()
{
return TurtleUpgradeType.Tool;
}
@Override
public ItemStack getCraftingItem()
{
return upgradeItem;
}
@Override
public boolean isSecret()
{
return false;
}
@Override
public IHostedPeripheral createPeripheral(ITurtleAccess turtle,
TurtleSide side)
{
return null;
}
@Override
public boolean useTool(ITurtleAccess turtle, TurtleSide side,
TurtleVerb verb, int direction)
{
switch( verb )
{
case Dig:
return dig(turtle, direction);
case Attack:
return attack(turtle, direction);
}
return false;
}
private boolean dig(ITurtleAccess turtle, int dir)
{
World world = turtle.getWorld();
Vec3 position = turtle.getPosition();
if (position == null)
{
return false;
}
int newX = (int)position.xCoord + Facing.offsetsXForSide[dir];
int newY = (int)position.yCoord + Facing.offsetsYForSide[dir];
int newZ = (int)position.zCoord + Facing.offsetsZForSide[dir];
if ( (newY < 0) || (newY >= world.getHeight()) )
{
return false;
}
int blockID = world.getBlockId(newX, newY, newZ);
Block block = Block.blocksList[blockID];
if ( (blockID == 0)
|| (blockID == Block.bedrock.blockID)
|| (block.getBlockHardness(world, newX, newY, newZ) <= -1.0F)
)
{
return false;
}
int matadata = world.getBlockMetadata(newX, newY, newZ);
ArrayList items = block.getBlockDropped(world, newX, newY, newZ, matadata, 0);
Iterator it = items.iterator();
while (it.hasNext())
{
ItemStack item = (ItemStack)it.next();
if ( !turtle.storeItemStack(item) )
{
int[] oppositeSide = { 1, 0, 3, 2, 5, 4 };
if ( !turtle.dropItemStack(item, oppositeSide[turtle.getFacingDir()]) )
{
turtle.dropItemStack(item, turtle.getFacingDir());
}
}
}
world.playAuxSFX(2001, newX, newY, newZ, blockID + matadata * 4096);
world.setBlock(newX, newY, newZ, 0, 0, 3);
return true;
}
private boolean attack(ITurtleAccess turtle, int dir)
{
return turtle.attackWithItemStack(new ItemStack(Item.swordDiamond), dir, 2.0F);
}
@Override
public Icon getIcon(ITurtleAccess turtle, TurtleSide side) {
return upgradeItem.getIconIndex();
}
} }}
TurtleアップグレードIDはgetUpgradeIDの戻り値で指定する。このサンプルでは前述の@MODクラスBasicUpgradesのメンバー変数から取得して指定している。アップグレードのタイプはenum TurtleUpgradeTypeの列挙子でToolを指定。装着したTurtleに付く形容詞は"Tool"を指定(つまり"Tool Turtle"になる)。クラフトに必要なアイテムと装着したアップグレードの外観は金のツルハシ。Toolタイプなので無用なcreatePeripheralではnullを返す。
Toolタイプの本領はuseToolによって発揮される。このサンプルではverbの種類(DigかAttackか)で分岐させた後、それぞれ別のメンバー関数(digとattack)に処理させている。
-dig
Turtleに採掘させる場合、採掘に必要な処理そのものを書く必要がある。
まず、useToolから得たITurtleAccess turtleによりTurtleの座標を得て、その座標と採掘する方向dirから採掘すべきブロックの座標と種類、メタデータを取得する。次に、採掘すべきブロックが採掘できるか(高度、種類)を調べる。採掘可能だった場合は採掘して得られるアイテムを取得し、スロットに入りきらなかった場合はドロップする。最後に採掘の効果音を鳴らし、採掘したブロックを消す(空気ブロックにする)。
-attack
採掘処理が難しい一方で、攻撃は専用メソッドが用意されているため簡単である。このサンプルではダイヤソードの2倍の攻撃力14(ハート7個分)でdir方向を攻撃する。
ちなみに、それぞれのverdは単にTurtle側のturtle.dig()とturtle.attack()で呼び出されるというだけで、必ずしもTurtleが採掘や攻撃を行わなければならないという訳ではない。
**TurtleBasicPeripheral.java
ITurtleUpgradeの実装クラスでPeripheralタイプのTurtleアップグレードを実装している。
#highlight(java){{
package sample.upgrade;
import net.minecraft.block.Block;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Icon;
import dan200.computer.api.IHostedPeripheral;
import dan200.turtle.api.ITurtleAccess;
import dan200.turtle.api.ITurtleUpgrade;
import dan200.turtle.api.TurtleSide;
import dan200.turtle.api.TurtleUpgradeType;
import dan200.turtle.api.TurtleVerb;
public class TurtleBasicPeripheral implements ITurtleUpgrade
{
public ItemStack upgradeItem = new ItemStack(Block.stone, 1, 0);
@Override
public int getUpgradeID() {
return BasicUpgrades.basicPeripheralUpgradeID;
}
@Override
public String getAdjective() {
return "Peripheral";
}
@Override
public TurtleUpgradeType getType() {
return TurtleUpgradeType.Peripheral;
}
@Override
public ItemStack getCraftingItem() {
return upgradeItem;
}
@Override
public boolean isSecret() {
return false;
}
@Override
public IHostedPeripheral createPeripheral(ITurtleAccess turtle,
TurtleSide side) {
return new PeripheralTurtleBasicPeripheral(turtle, side);
}
@Override
public boolean useTool(ITurtleAccess turtle, TurtleSide side,
TurtleVerb verb, int direction) {
return false;
}
@Override
public Icon getIcon(ITurtleAccess turtle, TurtleSide side) {
return Block.stoneSingleSlab.getBlockTextureFromSide(0);
}
} }}
TurtleアップグレードIDはgetUpgradeIDの戻り値で指定する。このサンプルでは前述の@MODクラスBasicUpgradesのメンバー変数から取得して指定している。アップグレードのタイプはenum TurtleUpgradeTypeの列挙子でPeripheralを指定。装着したTurtleに付く形容詞は"Peripheral"を指定(つまり"Peripheral Turtle"になる)。クラフトに必要なアイテムは石ブロック。装着したアップグレードの外観は石ハーフブロックの下面。
Peripheralタイプなので、createPeripheralでは周辺機器の機能を実装したIHostedPeripheralの実装クラスのインスタンスを返す。このサンプルでは、後述のPeripheralTurtleBasicPeripheralのインスタンスを返している。ToolタイプではないのでuseToolは呼び出されない。
**PeripheralTurtleBasicPeripheral.java
IHostedPeripheralの実装クラスでPeripheralタイプのアップグレードの周辺機器としての動作を実装している。IHostedPeripheralはIPeripheralのサブインターフェイスである。[[周辺機器ブロック追加Mod>Modding/Peripheral]]も参照のこと。
#highlight(java){{
package sample.upgrade;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.Vec3;
import dan200.computer.api.IComputerAccess;
import dan200.computer.api.IHostedPeripheral;
import dan200.turtle.api.ITurtleAccess;
import dan200.turtle.api.TurtleSide;
public class PeripheralTurtleBasicPeripheral implements IHostedPeripheral
{
private ITurtleAccess m_turtle;
private IComputerAccess m_computer;
private TurtleSide m_side;
PeripheralTurtleBasicPeripheral(ITurtleAccess turtle, TurtleSide side)
{
m_turtle = turtle;
m_side = side;
}
@Override
public String getType()
{
return "turtlebasic";
}
@Override
public String[] getMethodNames()
{
return new String[] { "test", "getPosition" };
}
@Override
public Object[] callMethod( IComputerAccess computer, int method, Object[] arguments )
throws Exception
{
switch( method )
{
case 0:
// test
if( arguments.length < 1 ) {
throw new Exception("Expected argument");
}
return new Object[] { arguments[0] };
case 1:
//getPosition
Vec3 pos = m_turtle.getPosition();
if( arguments.length > 0
&& arguments[0] instanceof Boolean
&& true == (Boolean)arguments[0])
{
return new Object[] {
"Position: " + (int)pos.xCoord
+ ", " + (int)pos.yCoord
+ ", " + (int)pos.zCoord
};
}
return new Object[] {
Integer.valueOf((int)pos.xCoord),
Integer.valueOf((int)pos.yCoord),
Integer.valueOf((int)pos.zCoord)
};
}
return null;
}
@Override
public boolean canAttachToSide(int side)
{
return true;
}
@Override
public void attach( IComputerAccess computer)
{
m_computer = computer;
System.out.printf("[TurtleBasicPeripheral] Attached to Computer #%d (side: %s)\n",
m_computer.getID(), m_computer.getAttachmentName()
);
}
@Override
public void detach( IComputerAccess computer )
{
System.out.printf("[TurtleBasicPeripheral] Detached from Computer #%d\n",
computer.getID()
);
}
@Override
public void update()
{
}
@Override
public void readFromNBT(NBTTagCompound nbttagcompound) {
}
@Override
public void writeToNBT(NBTTagCompound nbttagcompound) {
}
} }}
[[周辺機器ブロック追加Mod>Modding/Peripheral]]と似たような構成になっているが、以下のような点が違う。
-attachはTurtle起動時、detachはattach後のTurtle破壊時に呼び出される(Turtleアップグレードの特徴)
-attach後に毎Tick呼び出されるupdateが追加されている(IHostedPeripheralの特徴)
-NBTへデータを読み書きするメソッドが追加されている(IHostedPeripheralの特徴)
このサンプルではタートルへのアクセスインターフェイスを取得するために、引数付きのコンストラクタを追加している。これは周辺機器側からタートルへアクセスするのに必要である。また、attach時にTurtle内のComputerのアクセスインターフェイスを取得している。周辺機器ブロックと違い、アップグレード周辺機器に接続するのは装着されたTurtleだけなので、それらは単なるメンバ変数に保存している。
周辺機器のメソッドとして、[[周辺機器ブロック追加Mod>Modding/Peripheral]]のサンプルと同様の"test"と、Turtleの座標を取得する"getPosition"を実装している。getPositionは引数にtrueを指定して呼ばれた時は座標を文字列にして返し、それ以外のときは座標を3つの数値で返す(サンプルではあるが、GPSから考えればチート性能なメソッドである)。