石橋を叩いて壊すページ

インベントリ関連メソッドの動きをちょっと確認してみた2

以前の記事の続きでインベントリ周りをいろいろ調べてみる。
というか、明日マインクラフト1.7公開予定らしいと昨日知った。
我ながら悪いタイミングで動作確認を始めてしまったものだと後悔を禁じえない。

PlayerInventoryのgetContents()はどういう値を返すのか

前回はプレイヤーの防具を取得できるgetArmorContents()について調べた。
今回はgetContents()、要するにインベントリの内容を返すメソッドを調べる。

懸案事項としてあるのが防具だ。直感的には、現在装備している防具も所持品の一種に違いない。
ということはgetContents()で返される内容には防具も含まれると予想するがどうなのか。

コードはこう。前回とほぼ同じ。

@EventHandler
public void onPlayerInteractEvent(PlayerInteractEvent e) {

	ItemStack[] is=e.getPlayer().getInventory().getContents();

	getServer().broadcastMessage("長さ"+is.length);
			
	for(int n=0;n!=is.length;n++)
	{
		getServer().broadcastMessage(n+":"+is[n]);
	}
}

みてのとおり、ゲーム中にクリックすればインベントリの内容が表示される仕組み。
じゃあやっていこう。


鉄の防具をまとい、インベントリをこんな感じにしてからクリックした。
長さ36
0:ItemStack{GRASS x 1}
1:ItemStack{GRASS x 2}
2:ItemStack{GRASS x 3}
3:ItemStack{GRASS x 4}
4:ItemStack{GRASS x 5}
5:ItemStack{GRASS x 6}
6:ItemStack{GRASS x 7}
7:ItemStack{GRASS x 8}
8:ItemStack{GRASS x 9}
9:ItemStack{GRASS x 10}
10:ItemStack{GRASS x 11}
11:ItemStack{GRASS x 12}
12:ItemStack{GRASS x 13}
13:ItemStack{GRASS x 14}
14:ItemStack{GRASS x 15}
15:ItemStack{GRASS x 16}
16:ItemStack{GRASS x 17}
17:ItemStack{GRASS x 18}
18:null
19:null
20:null
21:null
22:null
23:null
24:null
25:null
26:ItemStack{GRASS x 27}
27:null
28:null
29:null
30:null
31:null
32:null
33:null
34:null
35:ItemStack{GRASS x 36}


なにも持っていない場合。
長さ36
0:null
1:null
2:null
3:null
4:null
5:null
6:null
7:null
8:null
9:null
10:null
11:null
12:null
13:null
14:null
15:null
16:null
17:null
18:null
19:null
20:null
21:null
22:null
23:null
24:null
25:null
26:null
27:null
28:null
29:null
30:null
31:null
32:null
33:null
34:null
35:null

前回getArmorContents()について調べたときは、空のスロットにはMaterial.AIRが入っていたが
今回getContents()ではNullが入るわけだ。ややこしい(;´Д`)

あと、着ている防具の内容はgetContents()には含まれていないので、
アイテムを退避させるようなコードを書く場合は防具を別途処理しないといけないことがわかる。

PlayerInventoryのsetContents(ItemStack[])はどういう値を期待しているのか

前回setArmorContentsの動きを確認したので、もう大体答えは見えているのだが
一応setContentsも動きを確認しておく事にする。

コードはこう。

@SuppressWarnings("deprecation")
@EventHandler
public void onPlayerInteractEvent(PlayerInteractEvent e) {

	ItemStack[] is=new ItemStack[36];
	for(int n=0;n!=is.length;n++)
	{
		is[n]=new ItemStack(Material.GRASS,n+1);
		//is[n]=n%2==0?null:new ItemStack(Material.AIR);
	}

	e.getPlayer().getInventory().setContents(is);
	
	e.getPlayer().updateInventory();
	
	getServer().broadcastMessage("格納完了");
}

クリックするとItemStackの配列を作り、プレイヤーのインベントリに押し付けるコード。
では検証していこう。


上記したコードをそのまま実行。予想どおりの結果になった。
インベントリのスロット番号はホットバーが0~8だが、
9以降はいったん一番上の段へ上がり、その後下の段へ下がっていく事がわかる。
ちなみに、あらかじめ持っていたアイテムはすべて上書きされ消滅した。


何も持っていない状態で、上記したコードの配列の長さを5にした場合。
エラーは出ない。


何も持っていない状態で、上記したコードの配列の長さを37にした場合。
インベントリは変更されず、以下のエラーが出た。
Caused by: java.lang.IllegalArgumentException: Invalid inventory size; expected 36 or less


すべてのスロットを土にした状態で、上記したコードの
コメントアウトしてある一行をコメントアウト解除した場合。
AIRとNullを織り交ぜた配列をインベントリに適用する結果になるが、
エラーは起こらず、インベントリの内容はすべて抹消された。


インベントリを全部砂で埋めた状態で、上記したコードの配列の長さを5にした場合。
5番目以降のスロットのアイテムは保持されるかとも思ったが、砂はすべて消去され、土だけが残った。

最後の実験以外は、予想通りになった。

インベントリホルダーを順に土で埋めてみる

上記でインベントリのスロット番号を調べたついでに、
ほかのインベントリホルダーのスロット番号もついでに調べておこう。

コードは上記の流用。
木の棒を持ってインベントリホルダーを右クリックするとインベントリが土で埋まるようにした。

@EventHandler
public void onPlayerInteractEvent(PlayerInteractEvent e) {

	if(e.getAction().equals(Action.RIGHT_CLICK_BLOCK) &&
		e.getPlayer().getItemInHand().getType().equals(Material.STICK) &&
		e.getClickedBlock().getState() instanceof InventoryHolder)
	{
		e.setCancelled(true);
		
		inventoryFillGrass(((InventoryHolder)e.getClickedBlock().getState()).getInventory());
	}
}

@EventHandler
public void onPlayerInteractEntityEvent(PlayerInteractEntityEvent e) {

	if(e.getPlayer().getItemInHand().getType().equals(Material.STICK) && e.getRightClicked() instanceof InventoryHolder)
	{
		e.setCancelled(true);
		
		inventoryFillGrass(((InventoryHolder)e.getRightClicked()).getInventory());
	}
}

public void inventoryFillGrass(Inventory inv)
{
	ItemStack[] is=new ItemStack[inv.getSize()];
	for(int n=0;n!=is.length;n++)
	{
		is[n]=new ItemStack(Material.GRASS,n+1);
	}

	inv.setContents(is);
	
	getServer().broadcastMessage("格納完了");
}

ではいろいろなものを木の棒で右クリックしていこう。


チェスト。チェストつきトロッコ、トラップチェストも同様。


ラージチェスト。トラップラージチェストも同様。


ディスペンサー。ドロッパーも同様。


かまど。ちなみにかまどつきトロッコはインベントリホルダーではない。


ホッパー。ホッパーつきトロッコも同様。


醸造台。


ウマもインベントリホルダー。使えるスロットは2つのみ。
なお、1スロット目はサドル専用、2スロット目はウマ防具専用スロットなので、
それ以外のアイテムをセットしている場合、Bukkit再起動のタイミングでアイテムは消去されてしまう。

2014/07/20追記:(バージョン:git-Bukkit-1.7.9-R0.2-1-ga6e0bfd-b3095jnks (MC: 1.7.9))


ロバとラマ。上はチェストを背負った状態、下は背負っていない状態。
チェストを背負っていない場合はインベントリは1スロットのみだが、チェストを背負っている場合は15スロット追加される。
上記画像ではコードから直接インベントリを弄ったせいで、本来使用できない2スロット目も使用できている。
しかし、チェストを背負っていない状態のロバ・ラマの3スロット目以降(チェストによる増加分スロット)はコードからでも使用できない。
ウマ同様に、1スロット目にサドル以外、2スロット目にウマ防具以外が設定されていると、
Bukkit再起動のタイミングでアイテムは消去されてしまう。
もっとも、ロバやラマには本来ウマ防具を設定できないが、コードから直接設定すると、サーバを再起動しても消去はされない。


醸造台に土を設定してもビンが表示される。


ウマに土を装備させても表示はされない。

ビーコンもインベントリホルダーだが、土を設定できなかった。
以上で大まかな動作は確認できたかな?

マインクラフトのバージョンがあがると、MODやプラグインの作者は対応や検証の作業に追われるわけだけど
今年7月にプラグイン作りを始めた自分としては、今回が始めてのバージョンアップなので
どの程度プラグインが動かなくなるものなのか楽しみではある。

この記事を評価

この記事にコメント

  1. ...

【この記事にコメント】
お名前:
コメント:

Menu