(ModelBakeEventHandler#loadModeのFunction()のジェネリクスを修正) |
(解説追加) |
||
306行目: | 306行目: | ||
ComputerCraftAPI.registerTurtleUpgrade(new TurtleSample(event.getSide())); | ComputerCraftAPI.registerTurtleUpgrade(new TurtleSample(event.getSide())); | ||
</source> | </source> | ||
− | + | ITurtleUpgrade実装クラスのコンストラクタでモデルを登録するために引数でSideを渡しています。 | |
− | |||
*ModelBakeEvent受信クラスの登録 | *ModelBakeEvent受信クラスの登録 | ||
314行目: | 313行目: | ||
</source> | </source> | ||
− | * | + | *ModelBakeEventでbakeするモデルのリスト |
<source lang = "java"> | <source lang = "java"> | ||
public static Set<ResourceLocation> modelLocations = new HashSet<ResourceLocation>(); | public static Set<ResourceLocation> modelLocations = new HashSet<ResourceLocation>(); | ||
325行目: | 324行目: | ||
} | } | ||
</source> | </source> | ||
− | + | 今回の例ではTurtle Upgradeの各モデルをModelBakeEventでまとめてbakeするために、モデルのJSONファイルの位置を登録するためのリストとメソッドを用意しています。<br> | |
− | + | モデルの位置は各ITurtleUpgrade実装クラスのコンストラクタでloadModelLocationメソッドを呼び出して登録します。 | |
==== TurtleSample.java ==== | ==== TurtleSample.java ==== | ||
346行目: | 345行目: | ||
} | } | ||
</source> | </source> | ||
− | + | コアクラスで用意したloadModelLocationメソッドをコンストラクタで呼び出してTurtle UpgradeのモデルのJSONファイルの位置を登録します。<br> | |
戻り値はgetModel()で使うためメンバフィールドに保存します。 | 戻り値はgetModel()で使うためメンバフィールドに保存します。 | ||
*getType() | *getType() | ||
+ | <source lang = "java"> | ||
+ | @Override | ||
+ | public TurtleUpgradeType getType() { | ||
+ | return TurtleUpgradeType.Peripheral; | ||
+ | } | ||
+ | </source> | ||
Turtle Upgradeの種類をTurtleUpgradeTypeの値で指定します。 | Turtle Upgradeの種類をTurtleUpgradeTypeの値で指定します。 | ||
368行目: | 373行目: | ||
*createPeripheral() | *createPeripheral() | ||
− | 周辺機器タイプのTurtle | + | <source lang = "java"> |
+ | @Override | ||
+ | public IPeripheral createPeripheral(ITurtleAccess turtle, TurtleSide side) { | ||
+ | return new SamplePeripheral(turtle, side); | ||
+ | } | ||
+ | </source> | ||
+ | 周辺機器タイプのTurtle Upgradeの場合、周辺機器の動作を定義したIPeripheral実装クラスのインスタンスを返します。 | ||
− | + | IPeripheral実装クラスにはコンストラクタの引数でTurtle Upgradeの情報を渡しています。 | |
*useTool() | *useTool() | ||
+ | <source lang = "java"> | ||
+ | @Override | ||
+ | public TurtleCommandResult useTool(ITurtleAccess turtle, TurtleSide side, | ||
+ | TurtleVerb verb, EnumFacing direction) { | ||
+ | return null; | ||
+ | } | ||
+ | </source> | ||
周辺機器タイプのTurtle Upgradeでは呼び出されることは無いため、単にnullを返しています。 | 周辺機器タイプのTurtle Upgradeでは呼び出されることは無いため、単にnullを返しています。 | ||
394行目: | 412行目: | ||
今回はCC1.76の実装を参考にしています。<br> | 今回はCC1.76の実装を参考にしています。<br> | ||
+ | コンストラクタで登録してModelBakeEventでbakeされたモデルをModelManager.getModel()で取得して返しています。<br> | ||
Turtle Upgradeを装着した位置がTurtleの左側ならば左用のモデルを、右側ならば右用のモデルを描画するようにしています。 | Turtle Upgradeを装着した位置がTurtleの左側ならば左用のモデルを、右側ならば右用のモデルを描画するようにしています。 | ||
*update() | *update() | ||
− | Turtle | + | <source lang = "java"> |
+ | @Override | ||
+ | public void update(ITurtleAccess turtle, TurtleSide side) { | ||
+ | |||
+ | } | ||
+ | </source> | ||
+ | Turtle UpgradeがTurtleに装着されている間、毎tick呼び出されます。<br> | ||
ロードされているワールド上で装着されている数だけ呼び出されますが、各パラメータでどれに対する呼び出しなのかが判別が可能です。<br> | ロードされているワールド上で装着されている数だけ呼び出されますが、各パラメータでどれに対する呼び出しなのかが判別が可能です。<br> | ||
また、サーバ側とクライアント側でそれぞれ別に呼び出されますが、どちら側の呼び出しなのかはturtle.getWorld().isRemoteの値で判別可能です。<br> | また、サーバ側とクライアント側でそれぞれ別に呼び出されますが、どちら側の呼び出しなのかはturtle.getWorld().isRemoteの値で判別可能です。<br> | ||
− | + | ITurtleAccess.getPeripheral()で装着されている周辺機器Upgradeの周辺機器クラスのインスタンスを取得できます。<br> | |
turtle.getUpgradeNBTData()で読み書き可能なNBTTagCompoundを取得できます。このNBTTagCompoundはTurtleに記録され、ゲームを終了しても消去されません(Turtle Upgradeを取り外したりTurtleが破壊されると消えます)。 | turtle.getUpgradeNBTData()で読み書き可能なNBTTagCompoundを取得できます。このNBTTagCompoundはTurtleに記録され、ゲームを終了しても消去されません(Turtle Upgradeを取り外したりTurtleが破壊されると消えます)。 | ||
406行目: | 431行目: | ||
==== SamplePeripheral.java ==== | ==== SamplePeripheral.java ==== | ||
− | * | + | 周辺機器を定義するクラス |
+ | |||
+ | *装着されたTurtleの情報取得・保存 | ||
<source lang = "java"> | <source lang = "java"> | ||
private final ITurtleAccess turtleAccess; | private final ITurtleAccess turtleAccess; | ||
416行目: | 443行目: | ||
} | } | ||
</source> | </source> | ||
− | + | 周辺機器でTurtle Upgradeの情報を利用したい場合、コンストラクタで受け取って周辺機器側で保存しておきます。<br> | |
==== ModelBakeEventHandler.java ==== | ==== ModelBakeEventHandler.java ==== | ||
449行目: | 476行目: | ||
} | } | ||
</source> | </source> | ||
− | + | コアクラスのSet modelLocationsへ登録されたモデルをすべてbakeします。<br> | |
− | + | モデルをbakeすることによってITurtleUpgrade実装クラスのgetModel()で指定したモデルが描画されるようになります。 | |
==== turtle_sample_left.json (models/block) ==== | ==== turtle_sample_left.json (models/block) ==== | ||
Turtleの左側に装着された時のTurtle Upgradeのモデルを指定するJSONファイルです。<br> | Turtleの左側に装着された時のTurtle Upgradeのモデルを指定するJSONファイルです。<br> | ||
− | + | ||
− | <source lang = " | + | 今回の例ではJSONファイルの位置を "block/turtle_sample_left" と指定したため(TurtleSampleのコンストラクタ)、assets\<MOD_ID>\models\block ディレクトリに設置します。 |
− | + | ||
+ | <source lang = "javascript"> | ||
+ | "parent": "computercraft:block/turtle_upgrade_base_left", | ||
+ | "textures": { | ||
+ | "texture": "blocks/stone" | ||
+ | } | ||
</source> | </source> | ||
モデル自体はComputerCraft本体で定義されている物を流用しており、テクスチャのみ独自に設定(今回はバニラの石ブロック)しています。 | モデル自体はComputerCraft本体で定義されている物を流用しており、テクスチャのみ独自に設定(今回はバニラの石ブロック)しています。 | ||
462行目: | 494行目: | ||
==== turtle_sample_right.json (models/block) ==== | ==== turtle_sample_right.json (models/block) ==== | ||
Turtleの右側に装着された時のTurtle Upgradeのモデルを指定するJSONファイルです。<br> | Turtleの右側に装着された時のTurtle Upgradeのモデルを指定するJSONファイルです。<br> | ||
− | 解説はturtle_sample_left. | + | 解説はturtle_sample_left.jsonの項目を参照してください。 |
2016年1月4日 (月) 13:45時点における版
この記事は"Minecraft Forge Universal 10.14.4.x~"及び"ComputerCraft 1.76~"を前提MODとしています。 |
周辺機器タイプTurtleの追加
周辺機器タイプのTurtle Upgradeを追加します。
- ITurtleUpgrade(周辺機器タイプ)の実装
- TurtleUpgradeの登録
- IPeripheralの実装
- Turtle Upgradeの外観の実装
ソースコード
「MC1.8 ツールタイプTurtleの追加」や「MC1.8 周辺機器の追加」の解説を元にして、変更部分のみを解説します。
Packageは適宜設定してください。
SampleUpgradeCore.java
// package mods.sample.upgrade; import java.util.HashSet; import java.util.Set; import net.minecraft.client.resources.model.ModelResourceLocation; import net.minecraft.util.ResourceLocation; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod.EventHandler; import net.minecraftforge.fml.common.event.FMLInitializationEvent; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import dan200.computercraft.api.ComputerCraftAPI; @Mod(modid=SampleUpgradeCore.MOD_ID, name=SampleUpgradeCore.MOD_NAME, version=SampleUpgradeCore.MOD_VERSION, dependencies = SampleUpgradeCore.MOD_DEPENDENCIES) public class SampleUpgradeCore { public static final String MOD_ID = "sampleupgrademod"; public static final String MOD_NAME = "Sample Upgrade Mod"; public static final String MOD_VERSION = "1.0"; public static final String MOD_DEPENDENCIES = "after:ComputerCraft"; public static Set<ResourceLocation> modelLocations = new HashSet<ResourceLocation>(); @EventHandler public void init(FMLInitializationEvent event) { ComputerCraftAPI.registerTurtleUpgrade(new TurtleSample(event.getSide())); MinecraftForge.EVENT_BUS.register(new ModelBakeEventHandler()); } @SideOnly(Side.CLIENT) public static ModelResourceLocation loadModelLocation(String domain, String path) { ResourceLocation location = new ResourceLocation(domain, path); modelLocations.add(location); return new ModelResourceLocation(location, "inventory"); } }
TurtleSample.java
// package mods.sample.upgrade; import javax.vecmath.Matrix4f; import net.minecraft.client.Minecraft; import net.minecraft.client.resources.model.IBakedModel; import net.minecraft.client.resources.model.ModelManager; import net.minecraft.client.resources.model.ModelResourceLocation; import net.minecraft.init.Blocks; import net.minecraft.item.ItemStack; import net.minecraft.util.EnumFacing; import net.minecraft.util.ResourceLocation; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import org.apache.commons.lang3.tuple.Pair; import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.api.turtle.ITurtleAccess; import dan200.computercraft.api.turtle.ITurtleUpgrade; import dan200.computercraft.api.turtle.TurtleCommandResult; import dan200.computercraft.api.turtle.TurtleSide; import dan200.computercraft.api.turtle.TurtleUpgradeType; import dan200.computercraft.api.turtle.TurtleVerb; public class TurtleSample implements ITurtleUpgrade { private ResourceLocation upgradeID = new ResourceLocation(SampleUpgradeCore.MOD_ID, "sample"); private ItemStack upgradeItem = new ItemStack(Blocks.stone); @SideOnly(Side.CLIENT) private ModelResourceLocation modelLeft; @SideOnly(Side.CLIENT) private ModelResourceLocation modelRight; public TurtleSample(Side side) { if (side.isClient()) { String modid = SampleUpgradeCore.MOD_ID; modelLeft = SampleUpgradeCore.loadModelLocation(modid, "block/turtle_sample_left"); modelRight = SampleUpgradeCore.loadModelLocation(modid, "block/turtle_sample_right"); } } @Override public ResourceLocation getUpgradeID() { return upgradeID; } @Override public int getLegacyUpgradeID() { return -1; } @Override public String getUnlocalisedAdjective() { return "Sample"; } @Override public TurtleUpgradeType getType() { return TurtleUpgradeType.Peripheral; } @Override public ItemStack getCraftingItem() { return upgradeItem; } @Override public IPeripheral createPeripheral(ITurtleAccess turtle, TurtleSide side) { return new SamplePeripheral(turtle, side); } @Override public TurtleCommandResult useTool(ITurtleAccess turtle, TurtleSide side, TurtleVerb verb, EnumFacing direction) { return null; } @Override @SideOnly(Side.CLIENT) public Pair<IBakedModel, Matrix4f> getModel(ITurtleAccess turtle, TurtleSide side) { Minecraft mc = Minecraft.getMinecraft(); ModelManager modelManager = mc.getRenderItem().getItemModelMesher().getModelManager(); if (side == TurtleSide.Left) { return Pair.of(modelManager.getModel(modelLeft), null); } else { return Pair.of(modelManager.getModel(modelRight), null); } } @Override public void update(ITurtleAccess turtle, TurtleSide side) { } }
SamplePeripheral.java
// package mods.sample.upgrade; import dan200.computercraft.api.lua.ILuaContext; import dan200.computercraft.api.lua.LuaException; import dan200.computercraft.api.peripheral.IComputerAccess; import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.api.turtle.ITurtleAccess; import dan200.computercraft.api.turtle.TurtleSide; public class SamplePeripheral implements IPeripheral { private final ITurtleAccess turtleAccess; private final TurtleSide turtleSide; public SamplePeripheral(ITurtleAccess turtle, TurtleSide side) { turtleAccess = turtle; turtleSide = side; } @Override public String getType() { return "sample"; } @Override public String[] getMethodNames() { return new String[] {}; } @Override public Object[] callMethod(IComputerAccess computer, ILuaContext context, int method, Object[] arguments) throws LuaException, InterruptedException { switch(method) { } return null; } @Override public void attach(IComputerAccess computer) { } @Override public void detach(IComputerAccess computer) { } @Override public boolean equals(IPeripheral other) { if ((other != null) && (other instanceof SamplePeripheral)) { return other == this; } return false; } }
ModelBakeEventHandler.java
// package mods.sample.upgrade; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.client.resources.model.IBakedModel; import net.minecraft.client.resources.model.ModelResourceLocation; import net.minecraft.util.ResourceLocation; import net.minecraftforge.client.event.ModelBakeEvent; import net.minecraftforge.client.model.IModel; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import com.google.common.base.Function; public class ModelBakeEventHandler { @SubscribeEvent public void onModelBakeEvent(ModelBakeEvent event) { for (ResourceLocation location : SampleUpgradeCore.modelLocations) { loadModel(event, location); } } private void loadModel(ModelBakeEvent event, ResourceLocation location) { try { IModel model = event.modelLoader.getModel(location); IBakedModel bakedModel = model.bake(model.getDefaultState(), DefaultVertexFormats.ITEM, new Function<ResourceLocation, TextureAtlasSprite>() { @Override public TextureAtlasSprite apply(ResourceLocation location) { Minecraft mc = Minecraft.getMinecraft(); return mc.getTextureMapBlocks().getAtlasSprite(location.toString()); } }); ModelResourceLocation modelLocation = new ModelResourceLocation(location, "inventory"); event.modelRegistry.putObject(modelLocation, bakedModel); } catch (Exception e) { e.printStackTrace(); } } }
turtle_sample_left.json (models/block)
assets\sampleupgrademod\models\block ディレクトリに設置します。
{ "parent": "computercraft:block/turtle_upgrade_base_left", "textures": { "texture": "blocks/stone" } }
turtle_sample_right.json (models/block)
assets\sampleupgrademod\models\block ディレクトリに設置します。
{ "parent": "computercraft:block/turtle_upgrade_base_right", "textures": { "texture": "blocks/stone" } }
解説
SampleUpgradeCore.java
Modのコアとなるクラス
- TurtleUpgradeの登録
ComputerCraftAPI.registerTurtleUpgrade(new TurtleSample(event.getSide()));
ITurtleUpgrade実装クラスのコンストラクタでモデルを登録するために引数でSideを渡しています。
- ModelBakeEvent受信クラスの登録
MinecraftForge.EVENT_BUS.register(new ModelBakeEventHandler());
- ModelBakeEventでbakeするモデルのリスト
public static Set<ResourceLocation> modelLocations = new HashSet<ResourceLocation>(); @SideOnly(Side.CLIENT) public static ModelResourceLocation loadModelLocation(String domain, String path) { ResourceLocation location = new ResourceLocation(domain, path); modelLocations.add(location); return new ModelResourceLocation(location, "inventory"); }
今回の例ではTurtle Upgradeの各モデルをModelBakeEventでまとめてbakeするために、モデルのJSONファイルの位置を登録するためのリストとメソッドを用意しています。
モデルの位置は各ITurtleUpgrade実装クラスのコンストラクタでloadModelLocationメソッドを呼び出して登録します。
TurtleSample.java
Turtle Upgradeの機能を定義するクラス
- TurtleUpgradeのモデル登録
@SideOnly(Side.CLIENT) private ModelResourceLocation modelLeft; @SideOnly(Side.CLIENT) private ModelResourceLocation modelRight; public TurtleSample(Side side) { if (side.isClient()) { String modid = SampleUpgradeCore.MOD_ID; modelLeft = SampleUpgradeCore.loadModelLocation(modid, "block/turtle_sample_left"); modelRight = SampleUpgradeCore.loadModelLocation(modid, "block/turtle_sample_right"); } }
コアクラスで用意したloadModelLocationメソッドをコンストラクタで呼び出してTurtle UpgradeのモデルのJSONファイルの位置を登録します。
戻り値はgetModel()で使うためメンバフィールドに保存します。
- getType()
@Override public TurtleUpgradeType getType() { return TurtleUpgradeType.Peripheral; }
Turtle Upgradeの種類をTurtleUpgradeTypeの値で指定します。
今回は周辺機器タイプなので TurtleUpgradeType.Peripheral を返しています。
- getCraftingItem()
private ItemStack upgradeItem = new ItemStack(Blocks.stone); @Override public ItemStack getCraftingItem() { return upgradeItem; }
Turtle Upgradeを装着するためのアイテムをItemStackで指定します。
今回はバニラブロックの石(焼石)を指定していますが、modで追加した独自アイテムも同様に指定できます。
- createPeripheral()
@Override public IPeripheral createPeripheral(ITurtleAccess turtle, TurtleSide side) { return new SamplePeripheral(turtle, side); }
周辺機器タイプのTurtle Upgradeの場合、周辺機器の動作を定義したIPeripheral実装クラスのインスタンスを返します。
IPeripheral実装クラスにはコンストラクタの引数でTurtle Upgradeの情報を渡しています。
- useTool()
@Override public TurtleCommandResult useTool(ITurtleAccess turtle, TurtleSide side, TurtleVerb verb, EnumFacing direction) { return null; }
周辺機器タイプのTurtle Upgradeでは呼び出されることは無いため、単にnullを返しています。
- getModel()
@Override @SideOnly(Side.CLIENT) public Pair<IBakedModel, Matrix4f> getModel(ITurtleAccess turtle, TurtleSide side) { Minecraft mc = Minecraft.getMinecraft(); ModelManager modelManager = mc.getRenderItem().getItemModelMesher().getModelManager(); if (side == TurtleSide.Left) { return Pair.of(modelManager.getModel(modelLeft), null); } else { return Pair.of(modelManager.getModel(modelRight), null); } }
Turtleに装着されたTurtle Upgradeの外観を指定します。
戻り値はPair<IBakedModel, Matrix4f>で、IBakedModelがモデル、Matrix4fがモデルを変形する座標変換行列です。
今回はCC1.76の実装を参考にしています。
コンストラクタで登録してModelBakeEventでbakeされたモデルをModelManager.getModel()で取得して返しています。
Turtle Upgradeを装着した位置がTurtleの左側ならば左用のモデルを、右側ならば右用のモデルを描画するようにしています。
- update()
@Override public void update(ITurtleAccess turtle, TurtleSide side) { }
Turtle UpgradeがTurtleに装着されている間、毎tick呼び出されます。
ロードされているワールド上で装着されている数だけ呼び出されますが、各パラメータでどれに対する呼び出しなのかが判別が可能です。
また、サーバ側とクライアント側でそれぞれ別に呼び出されますが、どちら側の呼び出しなのかはturtle.getWorld().isRemoteの値で判別可能です。
ITurtleAccess.getPeripheral()で装着されている周辺機器Upgradeの周辺機器クラスのインスタンスを取得できます。
turtle.getUpgradeNBTData()で読み書き可能なNBTTagCompoundを取得できます。このNBTTagCompoundはTurtleに記録され、ゲームを終了しても消去されません(Turtle Upgradeを取り外したりTurtleが破壊されると消えます)。
今回は何もしていません。
SamplePeripheral.java
周辺機器を定義するクラス
- 装着されたTurtleの情報取得・保存
private final ITurtleAccess turtleAccess; private final TurtleSide turtleSide; public SamplePeripheral(ITurtleAccess turtle, TurtleSide side) { turtleAccess = turtle; turtleSide = side; }
周辺機器でTurtle Upgradeの情報を利用したい場合、コンストラクタで受け取って周辺機器側で保存しておきます。
ModelBakeEventHandler.java
- ModelBakeEvent
@SubscribeEvent public void onModelBakeEvent(ModelBakeEvent event) { for (ResourceLocation location : SampleUpgradeCore.modelLocations) { loadModel(event, location); } } private void loadModel(ModelBakeEvent event, ResourceLocation location) { try { IModel model = event.modelLoader.getModel(location); IBakedModel bakedModel = model.bake(model.getDefaultState(), DefaultVertexFormats.ITEM, new Function<ResourceLocation, TextureAtlasSprite>() { @Override public TextureAtlasSprite apply(ResourceLocation location) { Minecraft mc = Minecraft.getMinecraft(); return mc.getTextureMapBlocks().getAtlasSprite(location.toString()); } }); ModelResourceLocation modelLocation = new ModelResourceLocation(location, "inventory"); event.modelRegistry.putObject(modelLocation, bakedModel); } catch (Exception e) { e.printStackTrace(); } }
コアクラスのSet modelLocationsへ登録されたモデルをすべてbakeします。
モデルをbakeすることによってITurtleUpgrade実装クラスのgetModel()で指定したモデルが描画されるようになります。
turtle_sample_left.json (models/block)
Turtleの左側に装着された時のTurtle Upgradeのモデルを指定するJSONファイルです。
今回の例ではJSONファイルの位置を "block/turtle_sample_left" と指定したため(TurtleSampleのコンストラクタ)、assets\<MOD_ID>\models\block ディレクトリに設置します。
"parent": "computercraft:block/turtle_upgrade_base_left", "textures": { "texture": "blocks/stone" }
モデル自体はComputerCraft本体で定義されている物を流用しており、テクスチャのみ独自に設定(今回はバニラの石ブロック)しています。
turtle_sample_right.json (models/block)
Turtleの右側に装着された時のTurtle Upgradeのモデルを指定するJSONファイルです。
解説はturtle_sample_left.jsonの項目を参照してください。