Skip to content

Instantly share code, notes, and snippets.

@keepoff07
Last active September 20, 2016 22:52
Show Gist options
  • Save keepoff07/ea0c87724c184d6a8a26 to your computer and use it in GitHub Desktop.
Save keepoff07/ea0c87724c184d6a8a26 to your computer and use it in GitHub Desktop.

自動装備の再現

やりたいこと

Minecraftのいつかのバージョンから、ゾンビや腐豚が落ちているアイテムを拾い、それを装備するようになりました。
これの装備をする機能をメソッドとして再現します。

バニラの自動装備

まず作る前にバニラの機能をおさらいします。 a
(GIFでかいですね)
まず、MOBは一番いいものを装備します。
a__| ̄ ̄|_______

a
また、エンチャントや名前などデータタグが付与されているものは、
同じ種類の防具でもよいものとして扱われます。
ただし、耐久が減っているとか、エンチャントの種類やレベルは関係ないようです。

作る

実際に作っていきます。

メソッドの概要を考える

まずはメソッドの概要を考えてみます。
(ItemStack) autoWear(LivingEntity ent, ItemStack item)
第一引数のLivingEntityに装備をさせたいMOB、第二引数に装備をさせるアイテムを入れ、
返り値には装備後のいらなくなったアイテムが返ってくるようにしましょう。

アイテムの種類を調べる

第二引数のアイテムが装備アイテムなのか、またどこの部位の装備なのかを調べます。
(ItemStack).getType()よりMaterialが返ってきます。
Materialは列挙型で、例えばヘルメットであれば~~_HELMETのように特定の文字が最後に付きます。それを利用しましょう。

int getArmorType(Material material) {
	String name = material.name();
	if(name.endsWith("_HELMET")) return 3;
	else if(name.endsWith("_CHESTPLATE")) return 2;
	else if(name.endsWith("_LEGGINGS")) return 1;
	else if(name.endsWith("_BOOTS")) return 0;
	else return -1;
}

こんな感じで、頭防具であれば3、胸防具であれば2、脚防具であれば1、足防具であれば0、それ以外で-1を返します。
返している数字は少し意味がありますがそれは後ほど。

アイテムにランクをつける

次に、上記の一番いいものを区別出来るようにしてみます。

装備の種類 ランク
ダイヤ装備(+データタグ) 9
ダイヤ装備 8
鉄装備(+データタグ) 7
鉄装備 6
チェーン装備(+データタグ) 5
チェーン装備 4
金装備(+データタグ) 5
金装備 4
皮装備(+データタグ) 3
皮装備 2
その他(+データタグ) 1
その他 0

このようにランク付けをしてみました。これをメソッドにしましょう。
方法は先程のようにMaterialから種類の区別をします。
(ItemStack).hasItemMeta()はそのアイテムがデータタグを持っているかをbooleanで返します。

int getRank(ItemStack item) {
	int rank = 0;
	String name = item.getType().name();
	if(name.startsWith("DIAMOND_")) rank = 8;
	else if(name.startsWith("IRON_")) rank = 6;
	else if(name.startsWith("GOLD_")) rank = 4;
	else if(name.startsWith("CHAINMAIL_")) rank = 4;
	else if(name.startsWith("LEATHER_")) rank = 2;
	if(item.hasItemMeta()) rank++;
	return rank;
}

仕上げ

まず、防具の種類を調べて-1以外であることを確認します。

ItemStack autoWear(LivingEntity ent, ItemStack item){
	int type = getArmorType(item.getType());
	if(type != -1) {
		//TODO
	}
	return item;
}

次に(LivingEntity).getEquipment()からEntityEquipment、エンティティの装備を取得し、
(EntityEquipment).getArmorContents()からItemStack[]、防具のアイテムを配列で取得します。
この配列は要素の数が4つで、足、脚、胸、頭装備の順に格納されています。
なのでここでアイテムの種類で取得した値が役に立ちます。

ItemStack autoWear(LivingEntity ent, ItemStack item){
	int type = getArmorType(item.getType());
	if(type != -1) {
		EntityEquipment equip = ent.getEquipment();
		ItemStack[] armor = equip.getArmorContents();
		ItemStack before = armor[type];
		//TODO
	}
	return item;
}

そして装備させようとしてるアイテム(item)と装備しているアイテム(before)のランクの比較をします。
装備させようとしてるアイテムの方がランクが高ければ装備が出来ます。
装備させるには(EntityEquipment).setArmorContents( ItemStack[] )で出来ます。
取得したItemStackの配列(armor)を少し変えれば出来ますね。
装備をさせた最後に元々装備していたアイテムを返して、終了っ!!

ItemStack autoWear(LivingEntity ent, ItemStack item){
	int type = getArmorType(item.getType());
	if(type != -1) {
		EntityEquipment equip = ent.getEquipment();
		ItemStack[] armor = equip.getArmorContents();
		ItemStack before = armor[type];
		if(getRank(item) > getRank(before)) {
			armor[type] = item;
			equip.setArmorContents(armor);
			return before;
		}
	}
	return item;
}

最後に

◆ギネスに ちょうせんしてるんだ。

ItemStack autoWear(LivingEntity ent, ItemStack item){
int type = getArmorType(item.getType());
if(type != -1) {
EntityEquipment equip = ent.getEquipment();
ItemStack[] armor = equip.getArmorContents();
ItemStack before = armor[type];
if(getRank(item) > getRank(before)) {
armor[type] = item;
equip.setArmorContents(armor);
return before;
}
}
return item;
}
int getRank(ItemStack item) {
int rank = 0;
String name = item.getType().name();
if(name.startsWith("DIAMOND_")) rank = 8;
else if(name.startsWith("IRON_")) rank = 6;
else if(name.startsWith("GOLD_")) rank = 4;
else if(name.startsWith("CHAINMAIL_")) rank = 4;
else if(name.startsWith("LEATHER_")) rank = 2;
if(item.hasItemMeta()) rank++;
return rank;
}
int getArmorType(Material material) {
String name = material.name();
if(name.endsWith("_HELMET")) return 3;
else if(name.endsWith("_CHESTPLATE")) return 2;
else if(name.endsWith("_LEGGINGS")) return 1;
else if(name.endsWith("_BOOTS")) return 0;
else return -1;
}
@844196
Copy link

844196 commented Mar 22, 2015

🍆

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment