提供: Minecraft Modding Wiki
移動先: 案内検索
(ModelBakeEventHandler.java: 解説修正)
(一時的にソースコード削除。【重要】チュートリアルコードにマルチ環境のserver側で実行できない致命的なバグ(モデル関連メソッドがserver側で呼び出される)があったので修正予定)
11行目: 11行目:
  
 
=== ソースコード ===
 
=== ソースコード ===
「[[ComputerCraft_API/1.76/ツールタイプTurtleの追加|MC1.8 ツールタイプTurtleの追加]]」や「[[ComputerCraft_API/1.76/周辺機器の追加|MC1.8 周辺機器の追加]]」の解説を元にして、変更部分のみを解説します。<br>
 
Packageは適宜設定してください。
 
 
==== SampleUpgradeCore.java ====
 
<source lang = "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");
 
}
 
 
}
 
</source>
 
 
==== TurtleSample.java ====
 
<source lang = "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) {
 
 
}
 
 
}
 
</source>
 
 
==== SamplePeripheral.java ====
 
<source lang = "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;
 
}
 
 
}
 
</source>
 
 
==== ModelBakeEventHandler.java ====
 
<source lang = "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();
 
}
 
}
 
 
}
 
</source>
 
 
==== turtle_sample_left.json (models/block) ====
 
assets\sampleupgrademod\models\block ディレクトリに設置します。
 
<source lang = "javascript">
 
{
 
"parent": "computercraft:block/turtle_upgrade_base_left",
 
"textures": {
 
"texture": "blocks/stone"
 
}
 
}
 
</source>
 
 
==== turtle_sample_right.json (models/block) ====
 
assets\sampleupgrademod\models\block ディレクトリに設置します。
 
<source lang = "javascript">
 
{
 
"parent": "computercraft:block/turtle_upgrade_base_right",
 
"textures": {
 
"texture": "blocks/stone"
 
}
 
}
 
</source>
 
 
 
=== 解説 ===
 
==== SampleUpgradeCore.java ====
 
Modのコアとなるクラス
 
 
*TurtleUpgradeの登録
 
<source lang = "java">
 
ComputerCraftAPI.registerTurtleUpgrade(new TurtleSample(event.getSide()));
 
</source>
 
ITurtleUpgrade実装クラスのコンストラクタでモデルを登録するために引数でSideを渡しています。
 
 
*ModelBakeEvent受信クラスの登録
 
<source lang = "java">
 
MinecraftForge.EVENT_BUS.register(new ModelBakeEventHandler());
 
</source>
 
 
*ModelBakeEventでbakeするモデルのリスト
 
<source lang = "java">
 
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");
 
}
 
</source>
 
今回の例ではTurtle Upgradeの各モデルをModelBakeEventでまとめてbakeするために、モデルのJSONファイルの位置を登録するためのリストとメソッドを用意しています。<br>
 
モデルの位置は各ITurtleUpgrade実装クラスのコンストラクタでloadModelLocationメソッドを呼び出して登録します。
 
 
==== TurtleSample.java ====
 
Turtle Upgradeの機能を定義するクラス
 
 
*TurtleUpgradeのモデル登録
 
<source lang = "java">
 
@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");
 
}
 
}
 
</source>
 
コアクラスで用意したloadModelLocationメソッドをコンストラクタで呼び出してTurtle UpgradeのモデルのJSONファイルの位置を登録します。<br>
 
戻り値はgetModel()で使うためメンバフィールドに保存します。
 
 
*getType()
 
<source lang = "java">
 
@Override
 
public TurtleUpgradeType getType() {
 
return TurtleUpgradeType.Peripheral;
 
}
 
</source>
 
Turtle Upgradeの種類をTurtleUpgradeTypeの値で指定します。
 
 
今回は周辺機器タイプなので TurtleUpgradeType.Peripheral を返しています。
 
 
*getCraftingItem()
 
<source lang = "java">
 
private ItemStack upgradeItem = new ItemStack(Blocks.stone);
 
 
@Override
 
public ItemStack getCraftingItem() {
 
return upgradeItem;
 
}
 
</source>
 
Turtle Upgradeを装着するためのアイテムをItemStackで指定します。
 
 
今回はバニラブロックの石(焼石)を指定していますが、modで追加した独自アイテムも同様に指定できます。
 
 
*createPeripheral()
 
<source lang = "java">
 
@Override
 
public IPeripheral createPeripheral(ITurtleAccess turtle, TurtleSide side) {
 
return new SamplePeripheral(turtle, side);
 
}
 
</source>
 
周辺機器タイプのTurtle Upgradeの場合、周辺機器の動作を定義したIPeripheral実装クラスのインスタンスを返します。
 
 
IPeripheral実装クラスにはコンストラクタの引数でTurtle Upgradeの情報を渡しています。
 
 
*useTool()
 
<source lang = "java">
 
@Override
 
public TurtleCommandResult useTool(ITurtleAccess turtle, TurtleSide side,
 
TurtleVerb verb, EnumFacing direction) {
 
return null;
 
}
 
</source>
 
周辺機器タイプのTurtle Upgradeでは呼び出されることは無いため、単にnullを返しています。
 
 
*getModel()
 
<source lang = "java">
 
@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);
 
}
 
}
 
</source>
 
Turtleに装着されたTurtle Upgradeの外観を指定します。<br>
 
戻り値はPair<IBakedModel, Matrix4f>で、IBakedModelがモデル、Matrix4fがモデルを変形する座標変換行列です。
 
 
今回はCC1.76の実装を参考にしています。<br>
 
コンストラクタで登録してModelBakeEventでbakeされたモデルをModelManager.getModel()で取得して返しています。<br>
 
Turtle Upgradeを装着した位置がTurtleの左側ならば左用のモデルを、右側ならば右用のモデルを描画するようにしています。
 
 
*update()
 
<source lang = "java">
 
@Override
 
public void update(ITurtleAccess turtle, TurtleSide side) {
 
 
}
 
</source>
 
Turtle UpgradeがTurtleに装着されている間、毎tick呼び出されます。<br>
 
ロードされているワールド上で装着されている数だけ呼び出されますが、各パラメータでどれに対する呼び出しなのかが判別が可能です。<br>
 
また、サーバ側とクライアント側でそれぞれ別に呼び出されますが、どちら側の呼び出しなのかはturtle.getWorld().isRemoteの値で判別可能です。<br>
 
ITurtleAccess.getPeripheral()で装着されている周辺機器Upgradeの周辺機器クラスのインスタンスを取得できます。<br>
 
turtle.getUpgradeNBTData()で読み書き可能なNBTTagCompoundを取得できます。このNBTTagCompoundはTurtleに記録され、ゲームを終了しても消去されません(Turtle Upgradeを取り外したりTurtleが破壊されると消えます)。
 
 
今回は何もしていません。
 
 
==== SamplePeripheral.java ====
 
周辺機器を定義するクラス
 
 
*装着されたTurtleの情報取得・保存
 
<source lang = "java">
 
private final ITurtleAccess turtleAccess;
 
private final TurtleSide turtleSide;
 
 
public SamplePeripheral(ITurtleAccess turtle, TurtleSide side) {
 
turtleAccess = turtle;
 
turtleSide = side;
 
}
 
</source>
 
周辺機器でTurtle Upgradeの情報を利用したい場合、コンストラクタで受け取って周辺機器側で保存しておきます。<br>
 
 
==== ModelBakeEventHandler.java ====
 
*ModelBakeEvent
 
<source lang = "java">
 
@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();
 
}
 
}
 
</source>
 
コアクラスのSet modelLocationsへ登録されたモデルをすべてbakeします。<br>
 
BakeしたモデルをmodelRegistryへ登録することによってITurtleUpgrade実装クラスのgetModel()で指定したモデルが描画されるようになります。
 
 
==== turtle_sample_left.json (models/block) ====
 
Turtleの左側に装着された時のTurtle Upgradeのモデルを指定するJSONファイルです。<br>
 
 
今回の例では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>
 
モデル自体はComputerCraft本体で定義されている物を流用しており、テクスチャのみ独自に設定(今回はバニラの石ブロック)しています。
 
 
==== turtle_sample_right.json (models/block) ====
 
Turtleの右側に装着された時のTurtle Upgradeのモデルを指定するJSONファイルです。<br>
 
解説はturtle_sample_left.jsonの項目を参照してください。
 

2016年1月10日 (日) 14:28時点における版

ComputerCraft API >

この記事は"Minecraft Forge Universal 10.14.4.x~"及び"ComputerCraft 1.76~"を前提MODとしています。

周辺機器タイプTurtleの追加

周辺機器タイプのTurtle Upgradeを追加します。

  • ITurtleUpgrade(周辺機器タイプ)の実装
  • TurtleUpgradeの登録
  • IPeripheralの実装
  • Turtle Upgradeの外観の実装

ソースコード