提供: 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を作成します | |
− | + | *前提となる知識 | |
− | + | Basic blocks | |
− | |||
− | |||
− | |||
==NBTとは?== | ==NBTとは?== | ||
− | + | NBTとは、Minecraftのマップ保存の為にNotchが作成したフォーマットです。ノードをベースにしたファイル{node-based file}で、region files、player.dat files、level.dat filesに使われています。 | |
− | |||
− | |||
+ | 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 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? | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | 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: | |
+ | 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 | |
− | + | 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. | |
+ | First, we make the constructor. Please note that the class 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 | ||
} | } | ||
− | + | I won't go through this in detail, because you should allready know this stuff. | |
− | + | Next, the method used for detecting right clicks. | |
− | |||
− | |||
− | |||
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) | ||
{ | { | ||
118行目: | 63行目: | ||
return true; | return true; | ||
} | } | ||
− | + | Lets go through the content line for line... | |
− | |||
− | |||
− | |||
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. | |
− | |||
− | |||
− | |||
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. | |
− | |||
− | |||
− | |||
− | |||
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. | |
− | + | Now we need to add a method to the file that tells Minecraft that we are using a tile entity: | |
− | |||
− | |||
− | |||
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: | |
− | |||
− | |||
public TileEntity createNewTileEntity(World par1World) | public TileEntity createNewTileEntity(World par1World) | ||
{ | { | ||
157行目: | 87行目: | ||
} | } | ||
} | } | ||
− | + | We are now done with the block file. Lets move on to the tile entity file. | |
− | |||
− | + | Making the TileEntity | |
− | + | The TileEntity does not need a constructor. In fact, the first thing we do is to declare the variables containing the visitors: | |
− | |||
String visitor1="none"; | String visitor1="none"; | ||
String visitor2="none"; | String visitor2="none"; | ||
169行目: | 97行目: | ||
String visitor4="none"; | String visitor4="none"; | ||
String visitor5="none"; | String visitor5="none"; | ||
− | + | I'm not using an array. Sue me. | |
− | + | The next thing we are going to do is to write the method that loads the information from the NBT tag compound: | |
− | |||
− | |||
− | |||
@Override | @Override | ||
public void readFromNBT(NBTTagCompound nbt) | public void readFromNBT(NBTTagCompound nbt) | ||
184行目: | 109行目: | ||
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. | |
− | + | The next method saves to NBT: | |
− | |||
− | |||
− | |||
@Override | @Override | ||
public void writeToNBT(NBTTagCompound nbt) | public void writeToNBT(NBTTagCompound nbt) | ||
199行目: | 121行目: | ||
nbt.setString("visitor5", visitor5); | nbt.setString("visitor5", visitor5); | ||
} | } | ||
− | + | This code is also very self-explanatory. | |
− | + | The last method to add is the one called in the block. | |
− | |||
− | |||
− | |||
public void processActivate(EntityPlayer par5EntityPlayer, World world) { | public void processActivate(EntityPlayer par5EntityPlayer, World world) { | ||
if(!visitor1.equals(par5EntityPlayer.getEntityName())) | if(!visitor1.equals(par5EntityPlayer.getEntityName())) | ||
217行目: | 136行目: | ||
world.notifyBlockChange(xCoord, yCoord, zCoord, 2); | world.notifyBlockChange(xCoord, yCoord, zCoord, 2); | ||
} | } | ||
− | + | This might require some explanation: | |
− | |||
− | |||
− | |||
if(!visitor1.equals(par5EntityPlayer.getEntityName())) | if(!visitor1.equals(par5EntityPlayer.getEntityName())) | ||
− | + | This makes sure you cant register twice in a row in the guest list. | |
− | |||
− | |||
− | |||
visitor5=visitor4; | visitor5=visitor4; | ||
visitor4=visitor3; | visitor4=visitor3; | ||
231行目: | 144行目: | ||
visitor2=visitor1; | visitor2=visitor1; | ||
visitor1=par5EntityPlayer.getEntityName(); | visitor1=par5EntityPlayer.getEntityName(); | ||
− | + | This part shifts the guest list. | |
− | |||
− | |||
− | |||
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. | |
− | |||
− | + | All the code | |
− | VisitorBlock.java( | + | VisitorBlock.java(Main code file) |
− | |||
package com.generic.tutorial.nbt.block; | package com.generic.tutorial.nbt.block; | ||
258行目: | 166行目: | ||
@NetworkMod(clientSideRequired=true, serverSideRequired=false) | @NetworkMod(clientSideRequired=true, serverSideRequired=false) | ||
public class VisitorBlock { | 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 (Block class) | |
− | |||
− | |||
− | BlockVisitor.java ( | ||
− | |||
− | |||
package com.generic.tutorial.nbt.block; | package com.generic.tutorial.nbt.block; | ||
292行目: | 195行目: | ||
public class BlockVisitor extends BlockContainer { | 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; | return true; | ||
} | } | ||
− | + | @Override | |
− | + | public TileEntity createNewTileEntity(World par1World) | |
{ | { | ||
try | try | ||
323行目: | 226行目: | ||
} | } | ||
− | |||
− | |||
TileEntityVisitor.java | TileEntityVisitor.java | ||
− | |||
package com.generic.tutorial.nbt.block; | package com.generic.tutorial.nbt.block; | ||
333行目: | 233行目: | ||
public class TileEntityVisitor extends TileEntity{ | 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); | par5EntityPlayer.addChatMessage("Visitors: " + visitor1 + ", " + visitor2 + ", " + visitor3 + ", " + visitor4 + ", " + visitor5); | ||
− | + | world.notifyBlockChange(xCoord, yCoord, zCoord, 2); | |
− | + | } | |
− | + | ||
− | + | @Override | |
− | + | public void readFromNBT(NBTTagCompound nbt) | |
{ | { | ||
super.readFromNBT(nbt); | super.readFromNBT(nbt); | ||
366行目: | 266行目: | ||
public void writeToNBT(NBTTagCompound nbt) | public void writeToNBT(NBTTagCompound nbt) | ||
{ | { | ||
− | + | super.writeToNBT(nbt); | |
− | + | nbt.setString("visitor1", visitor1); | |
nbt.setString("visitor2", visitor2); | nbt.setString("visitor2", visitor2); | ||
nbt.setString("visitor3", visitor3); | nbt.setString("visitor3", visitor3); | ||
375行目: | 275行目: | ||
} | } | ||
− | |||
− | + | Please note | |
− | Forge | + | You have to register the tileEntity with Forge, using: |
− | |||
GameRegistry.registerTileEntity(TileEntityVisitor.class, "visitorBlock"); | GameRegistry.registerTileEntity(TileEntityVisitor.class, "visitorBlock"); | ||
− | + | Read more | |
− | |||
− | |||
− | + | NBT page at Minecraft Coalition | |
+ | Categories: TutorialsTutorials/Intermediate |