提供: Minecraft Modding Wiki
2012年10月22日 (月) 20:15時点におけるReginn666 (トーク | 投稿記録)による版
移動先: 案内検索

この記事は"Minecraft Forge4.3x"を前提MODとしています。

SpriteID無限化(独自のterrain.png, gui/items.pngの利用)

 今までのサンプルではバニラのテクスチャを参照していた. ブロックはterrain.png, アイテムはgui/items.pngだった. ModLoaderにおけるaddOverrideというメソッドはこれらの空き領域に対し16*16のテクスチャを上書きし, そのテクスチャのインデックスを返すものだったため, 空き領域が埋まるとMinecraftがクラッシュしてしまう. この問題を解決するためにforgeではブロックやアイテムが参照するテクスチャを切り替える機構が用意された. なおこのサンプルからプロキシシステムを利用する.
また, 独自のterrain.png, items.pngにも名前の制限はない. しかしテクスチャのサイズは256ドット×256ドットである. これは16ドット×16ドットのテクスチャが16×16個まとまっているものである.
今回サンプルに作成したテクスチャは以下の2つ.

フォルダ構造

ソースコード

  • mcroot/src/common/mods/spritesample
    • SpriteSampleCore.java
    • BlockSpriteSample.java
    • ItemSpriteSample.java
    • CommonProxy.java
    • /client
      • ClientProxy

テクスチャ

  • mcroot/bin/minecraft/mods/sprites
    • SpriteSampleBlocks.png
    • SpriteSampleItems.png

ソースコード

  • SpriteSampleCore
package mods.spritesample;

import java.util.logging.Level;

import net.minecraft.src.*;

import net.minecraftforge.common.Configuration;
import net.minecraftforge.common.Property;

import cpw.mods.fml.common.SidedProxy;
import cpw.mods.fml.common.FMLLog;
import cpw.mods.fml.common.Mod;
import cpw.mods.fml.common.network.NetworkMod;

import cpw.mods.fml.common.event.FMLInitializationEvent;
import cpw.mods.fml.common.event.FMLPreInitializationEvent;

import cpw.mods.fml.common.registry.GameRegistry;
import cpw.mods.fml.common.registry.LanguageRegistry;

@Mod(
	modid = "SpriteSampleMod",
	name  = "Sprite Sample Mod",
	version = "1.0.0"
)
@NetworkMod(
	clientSideRequired = true,
	serverSideRequired = false
)
public class SpriteSampleCore
{
	@SidedProxy(clientSide = "mods.spritesample.client.ClientProxy", serverSide = "mods.spritesample.CommonProxy")
	public static CommonProxy proxy;
	
	public static Block blockSpriteSample;
	public static Item  itemSpriteSample;
	
	public int blockIdSpriteSample;
	public int itemIdSpriteSample;
	
	@Mod.PreInit
	public void preInit(FMLPreInitializationEvent event)
	{
		Configuration cfg = new Configuration(event.getSuggestedConfigurationFile());
		try
		{
			cfg.load();
			Property blockProp = cfg.getBlock("SpriteSampleBlock", 1302);
			Property itemProp  = cfg.getItem("SpriteSampleItem", 4002);
			blockProp.comment  = "This comment is Block Property";
			itemProp.comment   = "This comment is Item Property";
			blockIdSpriteSample = blockProp.getInt();
			itemIdSpriteSample  = itemProp.getInt();
		}
		catch (Exception e)
		{
			FMLLog.log(Level.SEVERE, e, "Error Message");
		}
		finally
		{
			cfg.save();
		}
	}
	
	@Mod.Init
	public void init(FMLInitializationEvent event)
	{
		blockSpriteSample = (new BlockSpriteSample(blockIdSpriteSample, 0)).setBlockName("spritesampleblock").setCreativeTab(CreativeTabs.tabBlock);
		itemSpriteSample  = (new ItemSpriteSample(itemIdSpriteSample)).setIconCoord(0, 0).setItemName("spritesampleitem").setCreativeTab(CreativeTabs.tabMaterials);
		
		GameRegistry.registerBlock(blockSpriteSample);
		
		LanguageRegistry.addName(blockSpriteSample, "Sprite Sample Block");
		LanguageRegistry.instance().addNameForObject(blockSpriteSample, "ja_JP", "スプライトサンプルブロック");
		
		LanguageRegistry.addName(itemSpriteSample, "Sprite Sample Item");
		LanguageRegistry.instance().addNameForObject(itemSpriteSample, "ja_JP", "スプライトサンプルアイテム");
		
		GameRegistry.addShapelessRecipe(
			new ItemStack(itemSpriteSample, 1),
				new Object[]
				{
					Block.stone
				});
				
		GameRegistry.addShapelessRecipe(
			new ItemStack(blockSpriteSample, 1),
				new Object[]
				{
					Block.stone, Block.stone
				});
		
		proxy.registerTextures();
	}
}
  • BlockSpriteSample
package mods.spritesample;

import net.minecraft.src.*;

public class BlockSpriteSample extends Block
{
	public BlockSpriteSample(int blockId, int terrainId)
	{
		super(blockId, terrainId, Material.wood);
	}
	
	@Override
	public String getTextureFile()
	{
		return "/mods/sprites/SpriteSampleBlocks.png";
	}

}
  • ItemSpriteSample
package mods.spritesample;

import net.minecraft.src.*;

public class ItemSpriteSample extends Item
{
	public ItemSpriteSample(int itemId)
	{
		super(itemId);
	}
	
	@Override
	public String getTextureFile()
	{
		return "/mods/sprites/SpriteSampleItems.png";
	}
}
  • CommonProxy
package mods.spritesample;

import net.minecraft.src.*;

public class CommonProxy
{
	public void registerTextures()
	{
		//何もしない
	}
}
  • ClientProxy
package mods.spritesample.client;

import net.minecraft.src.*;
import net.minecraftforge.client.MinecraftForgeClient;

import cpw.mods.fml.common.Side;
import cpw.mods.fml.common.asm.SideOnly;

import mods.spritesample.CommonProxy;

@SideOnly(Side.CLIENT)
public class ClientProxy extends CommonProxy
{
	@Override
	public void registerTextures()
	{
		MinecraftForgeClient.preloadTexture("/mods/sprites/SpriteSampleBlocks.png");
		MinecraftForgeClient.preloadTexture("/mods/sprites/SpriteSampleItems.png");
	}
}

解説

 Forge式コンフィグファイルの利用同様, 既に解説した箇所の解説は省略する.


SpriteSampleCore

import cpw.mods.fml.common.SidedProxy;
プロキシシステムを使うためのアノテーション.


@SidedProxy(clientSide = "mods.spritesample.client.ClientProxy", serverSide = "mods.spritesample.CommonProxy")
public static CommonProxy proxy;
@SidedProxyの引数でクライアント側とサーバー側のクラスを指定する. この指定はフルパスでなければならない.


proxy.registerTextures();
プロキシのインスタンスを通してテクスチャの登録を行う. この1行はクライアント側でもサーバー側でも実行されるが, それぞれの実装はClientProxy, CommonProxyで異なる.


BlockSpriteSample

public String getTextureFile()
{
	return "/mods/sprites/SpriteSampleBlocks.png";
}
参照したいテクスチャファイルのパスを返す. この時テクスチャ自体はmcroot/bin/minecraft/mods/spritesフォルダにあることになる.

ItemSpriteSample

public String getTextureFile()
{
	return "/mods/sprites/SpriteSampleItems.png";
}
ブロックの場合と同様. アイテムのテクスチャファイルのパスを返す.

CommonProxy

public void registerTextures()
{
	//何もしない
}
サーバー側, CommonProxyでは何もしないが, ClientProxyでオーバーライドして使うために空のメソッドを定義している.

ClientProxy

package mods.spritesample.client;
クライアント専用のクラスは全てmods/spritesample/clientフォルダに入れることで, どのクラスがクライアント専用なのかをはっきりさせる. 必要ないなら同じパッケージでよい.


import net.minecraftforge.client.MinecraftForgeClient;
MinecraftForgeAPIのうちクライアント側のみの機能を提供するクラス.


import cpw.mods.fml.common.Side;
import cpw.mods.fml.common.asm.SideOnly;
新しいコーディング記法とUniversal Moddingで触れたアノテーション. 共通でない(≒クライアント専用, サーバー専用)クラスやメソッドにつける.


import mods.spritesample.CommonProxy;
CommonProxyとはパッケージが異なるのでインポートしておく.


@SideOnly(Side.CLIENT)
public class ClientProxy extends CommonProxy
ClientProxyに@SideOnlyアノテーションを付与している. またClientProxyはCommonProxyを継承している.


@Override
public void registerTextures()
{
	MinecraftForgeClient.preloadTexture("/mods/sprites/SpriteSampleBlocks.png");
	MinecraftForgeClient.preloadTexture("/mods/sprites/SpriteSampleItems.png");
}
CommonProxyで定義したメソッドをオーバーライドする. preloadTextureは引数のパスで指定した画像ファイルをキャッシュに読み込むメソッド. ここで指定する引数は上記のBlockSpriteSampleクラスとItemSpriteSampleクラスで記述したファイルパスと同じにする.

実際の挙動

今回の挙動も今までのサンプルとは大差ない. しかし, blocks.pngやitems.pngの左上の16*16のテクスチャを変更したり, コード内のterrainIdやsetIconCoordを変更するとそれに応じてテクスチャも変更される.