提供: Minecraft Modding Wiki
移動先: 案内検索
 
1行目: 1行目:
 
このページは[http://www.minecraftforge.net/wiki/ Minecraft Forge Wiki]の[http://www.minecraftforge.net/wiki/How_to_use_NBT_Tag_Compound How to use NBT Tag Compound]の訳です。
 
このページは[http://www.minecraftforge.net/wiki/ Minecraft Forge Wiki]の[http://www.minecraftforge.net/wiki/How_to_use_NBT_Tag_Compound How to use NBT Tag Compound]の訳です。
翻訳はプログラミングやModdingに疎い人間がしています。訳語に不自然な点があれば訂正してください。
 
  
 
=NBT Tag Compoundの使い方=
 
=NBT Tag Compoundの使い方=
  
 
==最終的な目標==
 
==最終的な目標==
最後にブロックに右クリックをしたプレイヤーを記録する "last 5 visitors" Blockを作成します
+
 
*前提となる知識
+
最後にブロックを右クリックした5人のプレイヤーを記録する "last 5 visitors"ブロックを作成します
Basic blocks
+
 
 +
==前提となる知識==
 +
 
 +
[[Basic blocks]]
  
 
==NBTとは?==
 
==NBTとは?==
  
NBTとは、Minecraftのマップ保存の為にNotchが作成したフォーマットです。ノードをベースにしたファイル{node-based file}で、region files、player.dat files、level.dat filesに使われています。
+
NBTとは、Minecraftのマップ保存の為にNotchが作成したフォーマットです。ノードを基にしたファイルで、regionファイル、player.datファイル、level.datファイルに使われています。
 +
 
 +
バイナリだということを除けば、NBTの構造はとてもXMLに似ていると考えることができます。
  
NBTの構造は、バイナリを除いて、XMLのようなビットと考えることができます。<br>
 
 
どのNBTファイルも必ず"Tag_Compound"という種類のルートタグから始まっていて、それがこのチュートリアルの名前になっています。1つのTag_Compoundは他のノードをその中に保持することができます。そのルートタグは通常名前を持ちません。
 
どのNBTファイルも必ず"Tag_Compound"という種類のルートタグから始まっていて、それがこのチュートリアルの名前になっています。1つのTag_Compoundは他のノードをその中に保持することができます。そのルートタグは通常名前を持ちません。
  
 
==NBTを使う理由==
 
==NBTを使う理由==
  
NBT is very good if you want to store data that cannot be stored in data/metadata of the block/item. For example, you cant save all the item information from a chest in a 4 bit metadata, so you use NBT, which is practically infinite big. Size of block on the hard drive does increase a lot, though, so dont use NBT in blocks appearing naturally in big quantities.
+
NBTはブロックやアイテムのデータ/メタデータに保存出来ないものを保存するのにとても優れています。例えば、チェストの全アイテムの情報は4ビットのメタデータには保存出来ません。でも、NBTなら実質無限なのです。ただ、HDDの容量が実に増えているとは言え、大量に自然に現れるブロックにNBTを使用してはいけません。
NBT may also be useful in items. For example, the book uses NBT to save the author and contents of itself.
+
 
What is NBT used for in Minecraft?
+
また、NBTはアイテムにも便利です。例えば、本は作者と内容を保存するためにNBTを使用しています。
 +
 
 +
===MinecraftのどこにNBTが使われているでしょう?===
 +
 
 +
*看板
 +
*本
 +
*インベントリを持つ全てのブロック(かまど、チェスト、などなど)
 +
 
 +
===タグの種類===
 +
 
 +
NBTには12種類ものタグがあり、様々なデータが格納可能です:
 +
{|
 +
|'''ID'''
 +
|'''名前'''
 +
|'''解説'''
 +
|-
 +
|0
 +
|TAG_End
 +
|Compound Tagの終わり。通常見ることはない。
 +
|-
 +
|1
 +
|TAG_Byte
 +
|1バイトのデータを含むタグ
 +
|-
 +
|2
 +
|TAG_Short
 +
|1つのshort(数値)を含むタグ
 +
|-
 +
|3
 +
|TAG_Int
 +
|1つのintegerを含むタグ
 +
|-
 +
|4
 +
|TAG_Long
 +
|1つのlongを含むタグ
 +
|-
 +
|5
 +
|TAG_Float
 +
|1つのfloatを含むタグ
 +
|-
 +
|6
 +
|TAG_Double
 +
|1つのdoubleを含むタグ
 +
|-
 +
|7
 +
|TAG_Byte_Array
 +
|byteの配列を含むタグ
 +
|-
 +
|8
 +
|TAG_String
 +
|文字列を含むタグ
 +
|-
 +
|9
 +
|TAG_List
 +
|同じ種類の無名タグのリスト
 +
|-
 +
|10
 +
|TAG_Compound
 +
|名前付きタグのリスト。それぞれのNBTファイルの起点。他のCompoundを含むことが出来る。
 +
|-
 +
|11
 +
|TAG_Int_Array
 +
|integerの配列
 +
|-
 +
|}
 +
 
 +
''MinecraftCoalitionのNBTに関する情報はこのページの「参照」以下より参照してください。''
  
Signs
+
===ブロックのクラスを書く===
Books
 
All blocks with an inventory(Furnace, Chest, etc...)
 
Types of tags
 
  
There are 12 different types of tags, capable of storing different data:
+
もし作っているのがアイテムなら、ItemStackからCompound Tagを取得出来ます。それについてのチュートリアルを作成する必要があるでしょう。でも今はブロックで忙しいのです。
ID Name Description
 
0 TAG_End End of a compound tag. Normally never seen.
 
1 TAG_Byte A tag containing 1 byte of data.
 
2 TAG_Short A tag containing 1 short(Number value)
 
3 TAG_Int A tag containing 1 integer
 
4 TAG_Long A tag containing 1 long
 
5 TAG_Float A tag containing 1 float
 
6 TAG_Double A tag containing 1 double
 
7 TAG_Byte_Array A tag containing an array of bytes
 
8 TAG_String A tag containing a string
 
9 TAG_List A list of nameless tags of the same type.
 
10 TAG_Compound A list of named tag. The start of each NBT file. Can contain other compounds.
 
11 TAG_Int_Array An array of integers
 
Information taken from the MinecraftCoalition page on NBT. Please see the bottom of the page under "read more".
 
  
Writing the block class
+
NBTの値を保存するためにはTileEntityというものが必要です。TileEntityは基本的にブロックと繋がったエンティティで、ブロックの情報を保存するために使われます。
  
If it was an item we was making, you can get the tag compound from the ItemStack the item resolves in. I might make another tutorial about that. But because we are working with a block, we need to use something called a TileEntity to save NBT values. A TileEntity is basically a entity connected to a block, used to store stuff for the block.
+
最初に、コンストラクタを作ります。このクラスはBlockContainerを継承することに注意してください。
First, we make the constructor. Please note that the class extends BlockContainer.
 
  
 +
<source lang="java">
 
public BlockVisitor(int id) {
 
public BlockVisitor(int id) {
 
         super(id, 35, Material.circuits);
 
         super(id, 35, Material.circuits);
 
         // TODO Auto-generated constructor stub
 
         // TODO Auto-generated constructor stub
 
}
 
}
I won't go through this in detail, because you should allready know this stuff.
+
</source>
Next, the method used for detecting right clicks.
+
これについては説明する必要は無いでしょう。
 +
 
 +
次は、右クリックを検知するメソッドです。
 +
<source lang="java">
 
public boolean onBlockActivated(World world, int par2, int par3, int par4, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9)
 
public boolean onBlockActivated(World world, int par2, int par3, int par4, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9)
 
{
 
{
63行目: 118行目:
 
         return true;
 
         return true;
 
}
 
}
Lets go through the content line for line...
+
</source>
 +
 
 +
行ごとに見て行きましょう。
 +
<source lang="java">
 
if(!world.isRemote)
 
if(!world.isRemote)
This line checks if it is the server or client calling this. isRemote is true if it is the client, because after Minecraft 1.2.5, single player is run on a local server. Therefore, this is a easy way of detecting server/client.
+
</source>
 +
この行は、メソッドを呼び出しているのがサーバーかクライアントかを確認します。isRemoteはクライアントではtrueを返します。これは、1.2.5以降ではシングルでもローカルサーバー上で実行されているためです。つまり、これはサーバー/クライアントを検知する簡単な方法なのです。
 +
 
 +
<source lang="java">
 
TileEntityVisitor t = (TileEntityVisitor) world.getBlockTileEntity(par2, par3, par4);
 
TileEntityVisitor t = (TileEntityVisitor) world.getBlockTileEntity(par2, par3, par4);
This line gives us the variable t, by getting a tile entity from the world with the getBlockTileEntity method. par2, 3, and 4 are x, y, and z coordinates. Notice how we cast to a TileEntityVisitor.
+
</source>
 +
この行では変数tにgetBlockTileEntityメソッドを用いてワールドからTileEntityを取得します。par2、3、4はx、y、z座標を表します。
 +
TileEntityVisitorにキャストしていることに注意してください。
 +
 
 +
<source lang="java">
 
t.processActivate(par5EntityPlayer, world);
 
t.processActivate(par5EntityPlayer, world);
There is a method i made in our tileEntity called processActivate, that we use to do all the stuff in registering, and printing. The arguments are the player, and the world.
+
</source>
Now we need to add a method to the file that tells Minecraft that we are using a tile entity:
+
これは、登録と表示のためにTileEntityに設けた、processActivateというメソッドを呼び出しています。引数はプレイヤーとワールドです。
 +
 
 +
また、MinecraftにTileEntityを使うことを知らせるためにメソッドを追加する必要があります:
 +
<source lang="java">
 
public boolean hasTileEntity(int metadata)
 
public boolean hasTileEntity(int metadata)
 
{
 
{
 
     return true;
 
     return true;
 
}
 
}
The last method in the block file is the createNewTileEntity() method. It is quite simple, it just returns a new instance of a TileEntityVisitor:
+
</source>
 +
ブロックのファイルの最後のメソッドはcreateNewTileEntity()です。これは非常に単純で、TileEntityVisitorの新しいインスタンスを返すのみとなっています:
 +
<source lang="java">
 
public TileEntity createNewTileEntity(World par1World)
 
public TileEntity createNewTileEntity(World par1World)
 
{
 
{
87行目: 157行目:
 
     }
 
     }
 
}
 
}
We are now done with the block file. Lets move on to the tile entity file.
+
</source>
 +
これでブロックのファイルについては終わりました。TileEntityに移りましょう。
  
Making the TileEntity
+
===TileEntityを作る===
  
The TileEntity does not need a constructor. In fact, the first thing we do is to declare the variables containing the visitors:
+
TileEntityはコンストラクタを必要としません。実際、最初にするのは訪問者を保持する変数の定義です:
 +
<source lang="java">
 
String visitor1="none";
 
String visitor1="none";
 
String visitor2="none";
 
String visitor2="none";
97行目: 169行目:
 
String visitor4="none";
 
String visitor4="none";
 
String visitor5="none";
 
String visitor5="none";
I'm not using an array. Sue me.
+
</source>
The next thing we are going to do is to write the method that loads the information from the NBT tag compound:
+
配列は使いません。何か問題でも?
 +
 
 +
次はNBT Tag Compoundから情報を読み込むメソッドを書きます:
 +
<source lang="java">
 
@Override
 
@Override
 
public void readFromNBT(NBTTagCompound nbt)
 
public void readFromNBT(NBTTagCompound nbt)
109行目: 184行目:
 
     this.visitor5 = nbt.getString("visitor5");
 
     this.visitor5 = nbt.getString("visitor5");
 
}
 
}
As you can se, we get a NBTTagComponund to use for reading. The rest of the code is quite self-explaining. On a note, remember to run super.readFromNBT(TagCompound); Because a lot of information is actually saved and loaded my the tileentity itself.
+
</source>
The next method saves to NBT:
+
お分かりの通り、読み込みのためにNBTTagComponundを使います。コードについては自明です。注意として、super.readFromNBT(TagCompound);の実行を忘れないでください。幾つもの情報をTileEntity自身が保存し、読み込んでいるからです。
 +
 
 +
次のメソッドはNBTへの保存です:
 +
<source lang="java">
 
@Override
 
@Override
 
public void writeToNBT(NBTTagCompound nbt)
 
public void writeToNBT(NBTTagCompound nbt)
121行目: 199行目:
 
     nbt.setString("visitor5", visitor5);
 
     nbt.setString("visitor5", visitor5);
 
}
 
}
This code is also very self-explanatory.
+
</source>
The last method to add is the one called in the block.
+
このコードもまた自明です。
 +
 
 +
最後のコードはブロックの方で呼び出されていたメソッドです。
 +
<source lang="java">
 
public void processActivate(EntityPlayer par5EntityPlayer, World world) {
 
public void processActivate(EntityPlayer par5EntityPlayer, World world) {
 
         if(!visitor1.equals(par5EntityPlayer.getEntityName()))
 
         if(!visitor1.equals(par5EntityPlayer.getEntityName()))
136行目: 217行目:
 
         world.notifyBlockChange(xCoord, yCoord, zCoord, 2);
 
         world.notifyBlockChange(xCoord, yCoord, zCoord, 2);
 
}
 
}
This might require some explanation:
+
</source>
 +
 
 +
これには幾らかの説明が必要でしょう:
 +
<source lang="java">
 
if(!visitor1.equals(par5EntityPlayer.getEntityName()))
 
if(!visitor1.equals(par5EntityPlayer.getEntityName()))
This makes sure you cant register twice in a row in the guest list.
+
</source>
 +
これは、同じ訪問者を2度登録させないためです。
 +
 
 +
<source lang="java">
 
visitor5=visitor4;
 
visitor5=visitor4;
 
visitor4=visitor3;
 
visitor4=visitor3;
144行目: 231行目:
 
visitor2=visitor1;
 
visitor2=visitor1;
 
visitor1=par5EntityPlayer.getEntityName();
 
visitor1=par5EntityPlayer.getEntityName();
This part shifts the guest list.
+
</source>
 +
これは訪問者一覧を入れ替えます。
 +
 
 +
<source lang="java">
 
world.notifyBlockChange(xCoord, yCoord, zCoord, 2);
 
world.notifyBlockChange(xCoord, yCoord, zCoord, 2);
To be safe. This method tells the world to update neighbour blocks. Please note that i also print the visitors to the chat.
+
</source>
 +
安全のためです。このメソッドはワールドに周囲のブロックを更新することを伝えます。チャットに訪問者を表示していることにも注意してください。
  
All the code
+
===全てのコード===
  
VisitorBlock.java(Main code file)
+
VisitorBlock.java(メインのコード)
 +
<source lang="java">
 
package com.generic.tutorial.nbt.block;
 
package com.generic.tutorial.nbt.block;
  
166行目: 258行目:
 
@NetworkMod(clientSideRequired=true, serverSideRequired=false)
 
@NetworkMod(clientSideRequired=true, serverSideRequired=false)
 
public class VisitorBlock {
 
public class VisitorBlock {
        @Instance("VisitorBlock")
+
@Instance("VisitorBlock")
        VisitorBlock instance;
+
VisitorBlock instance;
        BlockVisitor visitor;
+
BlockVisitor visitor;
        int blockID=200;
+
int blockID=200;
        @PreInit
+
@PreInit
        public void preInit(FMLPreInitializationEvent event)
+
public void preInit(FMLPreInitializationEvent event)
        {
+
{
               
+
        }
+
}
        @Init
+
@Init
        public void load(FMLInitializationEvent event) {
+
public void load(FMLInitializationEvent event) {
                visitor = new BlockVisitor(blockID);
+
visitor = new BlockVisitor(blockID);
                GameRegistry.registerBlock(visitor);
+
GameRegistry.registerBlock(visitor);
                GameRegistry.registerTileEntity(TileEntityVisitor.class, "visitorBlock");
+
GameRegistry.registerTileEntity(TileEntityVisitor.class, "visitorBlock");
                GameRegistry.addRecipe(new ItemStack(visitor, 1), "###", "#%#", "###", '#', Item.redstone, '%', Item.paper);
+
GameRegistry.addRecipe(new ItemStack(visitor, 1), "###", "#%#", "###", '#', Item.redstone, '%', Item.paper);
        }
+
}
 
}
 
}
BlockVisitor.java (Block class)
+
 
 +
</source>
 +
 
 +
BlockVisitor.java (ブロックのクラス)
 +
 
 +
<source lang="java">
 
package com.generic.tutorial.nbt.block;
 
package com.generic.tutorial.nbt.block;
  
195行目: 292行目:
 
public class BlockVisitor extends BlockContainer {
 
public class BlockVisitor extends BlockContainer {
  
        public BlockVisitor(int id) {
+
public BlockVisitor(int id) {
                super(id, 35, Material.circuits);
+
super(id, 35, Material.circuits);
                // TODO Auto-generated constructor stub
+
// TODO Auto-generated constructor stub
        }
+
}
        public boolean onBlockActivated(World world, int par2, int par3, int par4, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9)
+
public boolean onBlockActivated(World world, int par2, int par3, int par4, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9)
 
     {
 
     {
                if(!world.isRemote)
+
if(!world.isRemote)
                {
+
{
                        TileEntityVisitor t = (TileEntityVisitor) world.getBlockTileEntity(par2, par3, par4);
+
TileEntityVisitor t = (TileEntityVisitor) world.getBlockTileEntity(par2, par3, par4);
                        t.processActivate(par5EntityPlayer, world);
+
t.processActivate(par5EntityPlayer, world);
                }
+
}
                return true;
+
return true;
 
     }
 
     }
        public boolean hasTileEntity(int metadata)
+
public boolean hasTileEntity(int metadata)
 
     {
 
     {
 
         return true;
 
         return true;
 
     }
 
     }
        @Override
+
@Override
        public TileEntity createNewTileEntity(World par1World)
+
public TileEntity createNewTileEntity(World par1World)
 
     {
 
     {
 
         try
 
         try
226行目: 323行目:
  
 
}
 
}
 +
</source>
 +
 
TileEntityVisitor.java
 
TileEntityVisitor.java
 +
<source lang="java">
 
package com.generic.tutorial.nbt.block;
 
package com.generic.tutorial.nbt.block;
  
233行目: 333行目:
 
public class TileEntityVisitor extends TileEntity{
 
public class TileEntityVisitor extends TileEntity{
  
        String visitor1="none";
+
String visitor1="none";
        String visitor2="none";
+
String visitor2="none";
        String visitor3="none";
+
String visitor3="none";
        String visitor4="none";
+
String visitor4="none";
        String visitor5="none";
+
String visitor5="none";
        public void processActivate(EntityPlayer par5EntityPlayer, World world) {
+
public void processActivate(EntityPlayer par5EntityPlayer, World world) {
                if(!visitor1.equals(par5EntityPlayer.getEntityName()))
+
if(!visitor1.equals(par5EntityPlayer.getEntityName()))
                {
+
{
                        visitor5=visitor4;
+
visitor5=visitor4;
                        visitor4=visitor3;
+
visitor4=visitor3;
                        visitor3=visitor2;
+
visitor3=visitor2;
                        visitor2=visitor1;
+
visitor2=visitor1;
                        visitor1=par5EntityPlayer.getEntityName();
+
visitor1=par5EntityPlayer.getEntityName();
                }
+
}
                //System.out.println("Visitors: " + visitor1 + ", " + visitor2 + ", " + visitor3 + ", " + visitor4 + ", " + visitor5);
+
//System.out.println("Visitors: " + visitor1 + ", " + visitor2 + ", " + visitor3 + ", " + visitor4 + ", " + visitor5);
 
                 par5EntityPlayer.addChatMessage("Visitors: " + visitor1 + ", " + visitor2 + ", " + visitor3 + ", " + visitor4 + ", " + visitor5);
 
                 par5EntityPlayer.addChatMessage("Visitors: " + visitor1 + ", " + visitor2 + ", " + visitor3 + ", " + visitor4 + ", " + visitor5);
                world.notifyBlockChange(xCoord, yCoord, zCoord, 2);
+
world.notifyBlockChange(xCoord, yCoord, zCoord, 2);
        }
+
}
       
+
        @Override
+
@Override
        public void readFromNBT(NBTTagCompound nbt)
+
public void readFromNBT(NBTTagCompound nbt)
 
     {
 
     {
 
         super.readFromNBT(nbt);
 
         super.readFromNBT(nbt);
266行目: 366行目:
 
     public void writeToNBT(NBTTagCompound nbt)
 
     public void writeToNBT(NBTTagCompound nbt)
 
     {
 
     {
        super.writeToNBT(nbt);
+
    super.writeToNBT(nbt);
        nbt.setString("visitor1", visitor1);
+
    nbt.setString("visitor1", visitor1);
 
         nbt.setString("visitor2", visitor2);
 
         nbt.setString("visitor2", visitor2);
 
         nbt.setString("visitor3", visitor3);
 
         nbt.setString("visitor3", visitor3);
275行目: 375行目:
  
 
}
 
}
 +
</source>
  
Please note
+
===注意事項===
  
You have to register the tileEntity with Forge, using:
+
Forge(訳注:これ自体はFML)を使ってTileEntityを登録する必要があります:
 +
<source lang="java">
 
GameRegistry.registerTileEntity(TileEntityVisitor.class, "visitorBlock");
 
GameRegistry.registerTileEntity(TileEntityVisitor.class, "visitorBlock");
Read more
+
</source>
 +
 
 +
===参考==
  
NBT page at Minecraft Coalition
+
[http://wiki.vg/NBT Minecraft CoalitionのNBTのページ]
Categories: TutorialsTutorials/Intermediate
 

2012年12月13日 (木) 23:04時点における最新版

このページはMinecraft Forge WikiHow to use NBT Tag Compoundの訳です。

NBT Tag Compoundの使い方[編集]

最終的な目標[編集]

最後にブロックを右クリックした5人のプレイヤーを記録する "last 5 visitors"ブロックを作成します

前提となる知識[編集]

Basic blocks

NBTとは?[編集]

NBTとは、Minecraftのマップ保存の為にNotchが作成したフォーマットです。ノードを基にしたファイルで、regionファイル、player.datファイル、level.datファイルに使われています。

バイナリだということを除けば、NBTの構造はとてもXMLに似ていると考えることができます。

どのNBTファイルも必ず"Tag_Compound"という種類のルートタグから始まっていて、それがこのチュートリアルの名前になっています。1つのTag_Compoundは他のノードをその中に保持することができます。そのルートタグは通常名前を持ちません。

NBTを使う理由[編集]

NBTはブロックやアイテムのデータ/メタデータに保存出来ないものを保存するのにとても優れています。例えば、チェストの全アイテムの情報は4ビットのメタデータには保存出来ません。でも、NBTなら実質無限なのです。ただ、HDDの容量が実に増えているとは言え、大量に自然に現れるブロックにNBTを使用してはいけません。

また、NBTはアイテムにも便利です。例えば、本は作者と内容を保存するためにNBTを使用しています。

MinecraftのどこにNBTが使われているでしょう?[編集]

  • 看板
  • インベントリを持つ全てのブロック(かまど、チェスト、などなど)

タグの種類[編集]

NBTには12種類ものタグがあり、様々なデータが格納可能です:

ID 名前 解説
0 TAG_End Compound Tagの終わり。通常見ることはない。
1 TAG_Byte 1バイトのデータを含むタグ
2 TAG_Short 1つのshort(数値)を含むタグ
3 TAG_Int 1つのintegerを含むタグ
4 TAG_Long 1つのlongを含むタグ
5 TAG_Float 1つのfloatを含むタグ
6 TAG_Double 1つのdoubleを含むタグ
7 TAG_Byte_Array byteの配列を含むタグ
8 TAG_String 文字列を含むタグ
9 TAG_List 同じ種類の無名タグのリスト
10 TAG_Compound 名前付きタグのリスト。それぞれのNBTファイルの起点。他のCompoundを含むことが出来る。
11 TAG_Int_Array integerの配列

MinecraftCoalitionのNBTに関する情報はこのページの「参照」以下より参照してください。

ブロックのクラスを書く[編集]

もし作っているのがアイテムなら、ItemStackからCompound Tagを取得出来ます。それについてのチュートリアルを作成する必要があるでしょう。でも今はブロックで忙しいのです。

NBTの値を保存するためにはTileEntityというものが必要です。TileEntityは基本的にブロックと繋がったエンティティで、ブロックの情報を保存するために使われます。

最初に、コンストラクタを作ります。このクラスはBlockContainerを継承することに注意してください。

public BlockVisitor(int id) {
        super(id, 35, Material.circuits);
        // TODO Auto-generated constructor stub
}

これについては説明する必要は無いでしょう。

次は、右クリックを検知するメソッドです。

public boolean onBlockActivated(World world, int par2, int par3, int par4, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9)
{
        if(!world.isRemote)
        {
                TileEntityVisitor t = (TileEntityVisitor) world.getBlockTileEntity(par2, par3, par4);
                t.processActivate(par5EntityPlayer, world);
        }
        return true;
}

行ごとに見て行きましょう。

if(!world.isRemote)

この行は、メソッドを呼び出しているのがサーバーかクライアントかを確認します。isRemoteはクライアントではtrueを返します。これは、1.2.5以降ではシングルでもローカルサーバー上で実行されているためです。つまり、これはサーバー/クライアントを検知する簡単な方法なのです。

TileEntityVisitor t = (TileEntityVisitor) world.getBlockTileEntity(par2, par3, par4);

この行では変数tにgetBlockTileEntityメソッドを用いてワールドからTileEntityを取得します。par2、3、4はx、y、z座標を表します。 TileEntityVisitorにキャストしていることに注意してください。

t.processActivate(par5EntityPlayer, world);

これは、登録と表示のためにTileEntityに設けた、processActivateというメソッドを呼び出しています。引数はプレイヤーとワールドです。

また、MinecraftにTileEntityを使うことを知らせるためにメソッドを追加する必要があります:

public boolean hasTileEntity(int metadata)
{
    return true;
}

ブロックのファイルの最後のメソッドはcreateNewTileEntity()です。これは非常に単純で、TileEntityVisitorの新しいインスタンスを返すのみとなっています:

public TileEntity createNewTileEntity(World par1World)
{
    try
    {
        return new TileEntityVisitor();
    }
    catch (Exception var3)
    {
        throw new RuntimeException(var3);
    }
}

これでブロックのファイルについては終わりました。TileEntityに移りましょう。

TileEntityを作る[編集]

TileEntityはコンストラクタを必要としません。実際、最初にするのは訪問者を保持する変数の定義です:

String visitor1="none";
String visitor2="none";
String visitor3="none";
String visitor4="none";
String visitor5="none";

配列は使いません。何か問題でも?

次はNBT Tag Compoundから情報を読み込むメソッドを書きます:

@Override
public void readFromNBT(NBTTagCompound nbt)
{
    super.readFromNBT(nbt);
    this.visitor1 = nbt.getString("visitor1");
    this.visitor2 = nbt.getString("visitor2");
    this.visitor3 = nbt.getString("visitor3");
    this.visitor4 = nbt.getString("visitor4");
    this.visitor5 = nbt.getString("visitor5");
}

お分かりの通り、読み込みのためにNBTTagComponundを使います。コードについては自明です。注意として、super.readFromNBT(TagCompound);の実行を忘れないでください。幾つもの情報をTileEntity自身が保存し、読み込んでいるからです。

次のメソッドはNBTへの保存です:

@Override
public void writeToNBT(NBTTagCompound nbt)
{
    super.writeToNBT(nbt);
    nbt.setString("visitor1", visitor1);
    nbt.setString("visitor2", visitor2);
    nbt.setString("visitor3", visitor3);
    nbt.setString("visitor4", visitor4);
    nbt.setString("visitor5", visitor5);
}

このコードもまた自明です。

最後のコードはブロックの方で呼び出されていたメソッドです。

public void processActivate(EntityPlayer par5EntityPlayer, World world) {
        if(!visitor1.equals(par5EntityPlayer.getEntityName()))
        {
                visitor5=visitor4;
                visitor4=visitor3;
                visitor3=visitor2;
                visitor2=visitor1;
                visitor1=par5EntityPlayer.getEntityName();
        }
        //System.out.println("Visitors: " + visitor1 + ", " + visitor2 + ", " + visitor3 + ", " + visitor4 + ", " + visitor5);
        par5EntityPlayer.addChatMessage("Visitors: " + visitor1 + ", " + visitor2 + ", " + visitor3 + ", " + visitor4 + ", " + visitor5);
        world.notifyBlockChange(xCoord, yCoord, zCoord, 2);
}

これには幾らかの説明が必要でしょう:

if(!visitor1.equals(par5EntityPlayer.getEntityName()))

これは、同じ訪問者を2度登録させないためです。

visitor5=visitor4;
visitor4=visitor3;
visitor3=visitor2;
visitor2=visitor1;
visitor1=par5EntityPlayer.getEntityName();

これは訪問者一覧を入れ替えます。

world.notifyBlockChange(xCoord, yCoord, zCoord, 2);

安全のためです。このメソッドはワールドに周囲のブロックを更新することを伝えます。チャットに訪問者を表示していることにも注意してください。

全てのコード[編集]

VisitorBlock.java(メインのコード)

package com.generic.tutorial.nbt.block;

import net.minecraft.src.*;
import cpw.mods.fml.common.Mod;
import cpw.mods.fml.common.Mod.Init;
import cpw.mods.fml.common.Mod.Instance;
import cpw.mods.fml.common.Mod.PreInit;
import cpw.mods.fml.common.event.FMLInitializationEvent;
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
import cpw.mods.fml.common.network.NetworkMod;
import cpw.mods.fml.common.registry.GameRegistry;

@Mod(modid="VisitorBlock", name="VisitorBlock", version="0.0.1")
@NetworkMod(clientSideRequired=true, serverSideRequired=false)
public class VisitorBlock {
	@Instance("VisitorBlock")
	VisitorBlock instance;
	BlockVisitor visitor;
	int blockID=200;
	@PreInit
	public void preInit(FMLPreInitializationEvent event)
	{
		
	}
	@Init
	public void load(FMLInitializationEvent event) {
		visitor = new BlockVisitor(blockID);
		GameRegistry.registerBlock(visitor);
		GameRegistry.registerTileEntity(TileEntityVisitor.class, "visitorBlock");
		GameRegistry.addRecipe(new ItemStack(visitor, 1), "###", "#%#", "###", '#', Item.redstone, '%', Item.paper);
	}
}

BlockVisitor.java (ブロックのクラス)

package com.generic.tutorial.nbt.block;

import net.minecraft.src.Block;
import net.minecraft.src.BlockContainer;
import net.minecraft.src.EntityPlayer;
import net.minecraft.src.Material;
import net.minecraft.src.TileEntity;
import net.minecraft.src.World;

public class BlockVisitor extends BlockContainer {

	public BlockVisitor(int id) {
		super(id, 35, Material.circuits);
		// TODO Auto-generated constructor stub
	}
	public boolean onBlockActivated(World world, int par2, int par3, int par4, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9)
    {
		if(!world.isRemote)
		{
			TileEntityVisitor t = (TileEntityVisitor) world.getBlockTileEntity(par2, par3, par4);
			t.processActivate(par5EntityPlayer, world);
		}
		return true;
    }
	public boolean hasTileEntity(int metadata)
    {
        return true;
    }
	@Override
	public TileEntity createNewTileEntity(World par1World)
    {
        try
        {
            return new TileEntityVisitor();
        }
        catch (Exception var3)
        {
            throw new RuntimeException(var3);
        }
    }   

}

TileEntityVisitor.java

package com.generic.tutorial.nbt.block;

import net.minecraft.src.*;

public class TileEntityVisitor extends TileEntity{

	String visitor1="none";
	String visitor2="none";
	String visitor3="none";
	String visitor4="none";
	String visitor5="none";
	public void processActivate(EntityPlayer par5EntityPlayer, World world) {
		if(!visitor1.equals(par5EntityPlayer.getEntityName()))
		{
			visitor5=visitor4;
			visitor4=visitor3;
			visitor3=visitor2;
			visitor2=visitor1;
			visitor1=par5EntityPlayer.getEntityName();
		}
		//System.out.println("Visitors: " + visitor1 + ", " + visitor2 + ", " + visitor3 + ", " + visitor4 + ", " + visitor5);
                par5EntityPlayer.addChatMessage("Visitors: " + visitor1 + ", " + visitor2 + ", " + visitor3 + ", " + visitor4 + ", " + visitor5);
		world.notifyBlockChange(xCoord, yCoord, zCoord, 2);
	}
	
	@Override
	public void readFromNBT(NBTTagCompound nbt)
    {
        super.readFromNBT(nbt);
        this.visitor1 = nbt.getString("visitor1");
        this.visitor2 = nbt.getString("visitor2");
        this.visitor3 = nbt.getString("visitor3");
        this.visitor4 = nbt.getString("visitor4");
        this.visitor5 = nbt.getString("visitor5");
    }

    @Override
    public void writeToNBT(NBTTagCompound nbt)
    {
    	super.writeToNBT(nbt);
    	nbt.setString("visitor1", visitor1);
        nbt.setString("visitor2", visitor2);
        nbt.setString("visitor3", visitor3);
        nbt.setString("visitor4", visitor4);
        nbt.setString("visitor5", visitor5);
    }

}

注意事項[編集]

Forge(訳注:これ自体はFML)を使ってTileEntityを登録する必要があります:

GameRegistry.registerTileEntity(TileEntityVisitor.class, "visitorBlock");

=参考[編集]

Minecraft CoalitionのNBTのページ