2017年12月23日土曜日

フェードアウトしたノードを再度表示する場合の注意事項

概要

SKAction.faceOut はノードをフェードアウトさせるためのアクションです
このアクションを使ってノードを非表示にした場合、そのノードを再度表示させる場合には必ず SKAction.fadeIn を使用しなければなりません
サンプルコードも交えて紹介します

環境

  • macOS X 10.13.2
  • Xcode 9.2 (9C40b)

コード

まず 1 度フェードアウトしたノードを再度表示しようとしても表示されない場合のコードです
なお、ノード (levelup) はデフォルトでは非表示の状態になっています

let show = SKAction.run({
    self.levelup.isHidden = false
})
let wait = SKAction.wait(forDuration: 1.0)
let fadeout = SKAction.fadeOut(withDuration: 0.5)
let hide = SKAction.run({
    self.levelup.isHidden = true
})
let actions = SKAction.sequence([show, wait, fadeout, hide])
levelup.run(actions)

これで表示してから再度非表示にするのに SKAction.faceOut を使っています
非表示は問題なくされるのですが、この流れが再度呼ばれたときに表示されません
なので以下のように変更する必要があります

let fadein = SKAction.fadeIn(withDuration: 0.1)
let show = SKAction.run({
    self.levelup.isHidden = false
})
let wait = SKAction.wait(forDuration: 1.0)
let fadeout = SKAction.fadeOut(withDuration: 0.5)
let hide = SKAction.run({
    self.levelup.isHidden = true
})
let actions = SKAction.sequence([fadein, show, wait, fadeout, hide])
levelup.run(actions)

すごい短い時間のフェードインを入れてあげます
こうすることで levelup ノードは再度表示されます
今回の場合非表示にするときにフェードアウトだけではなく isHidden = true でも非表示設定をしているため SKAction.faceIn の処理が実行されてても実はまで levelup ノードは非表示の状態なのでフェードインのアクションは目視で確認することができません
なので今回の SKAction.faceIn は levelup ノードを表示するためだけの処理になります

最後に

SKAction.faceOut でフェードアウトしたノードを再度表示する方法を紹介しました
フェードアウト後は単純に表示させるでだめの命令ではうまく表示されないようなので注意してください
また今回は同じノードを表示/非表示で使い続けることが前提になります
再表示するときには全く新しい SKSpriteNode などを作成するのであれば特にフェードインを気にする必要はありません

2017年12月21日木曜日

SpriteKit + Swift3 で touchesMoved を使ってタッチの軌跡を描く方法

概要

タッチした状態で画面上を指で動かしたときにその軌跡を描画する方法を紹介します

環境

  • macOS X 10.13.2
  • Xcode 9.2 (9C40b)

コード

var firstPoint: CGPoint?
var lineNode = SKShapeNode()
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    let touch = touches.first!
    firstPoint = touch.location(in: self)
}

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    let touch = touches.first!
    let position = touch.location(in: self)
    lineNode.removeFromParent()
    let path = CGMutablePath()
    path.move(to: firstPoint!)
    path.addLine(to: position)
    lineNode.path = path
    lineNode.lineWidth = 10.0
    lineNode.strokeColor = UIColor.blue
    lineNode.fillColor = UIColor.red
    self.addChild(lineNode)
    firstPoint = position
}

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    lineNode.removeFromParent()
}

touchesBegan で描画開始の位置を取得します
touchesMoved 中に開始位置の座標と移動先の座標を使って線を引いています
実体は SKShapeNode でその path プロパティを与えて上げることで 2 点間の間に線を引くことができます

touchesEnded でタッチが終了したときに描画した軌跡を削除します

動作確認

こんな感じで動作します
spritekit_draw_path1.gif

今回の場合一瞬しか軌跡が描かれません
操作を速くすると線が伸びます

addChild と removeFromParent をする位置を工夫すればペイントツールのように線を描くこともできると思います

2017年12月20日水曜日

Lenove Edge13 のメモリ増設する方法

概要

今更ではあるのですが、8 年前くらいに購入した Lenovo Edge13 のメモリを増設してみました
手順を備忘録がてら残しておきます

環境

  • Lenovo Edge13 0217-CTO
  • Windows7 64bit

交換するメモリ

今回は 2GB -> 4GB x 2 の 8GB に変更します
購入したメモリはこちらです

Team ノートPC用メモリ SO-DIMM-DDR3 永久保証 ECOパッケージ (1333Mhz PC3-10600 1.5V 4GBx2)

です
本当はサイバーマンデーで安くなるのを狙ったのですが全く対象にならずに定価で購入しました
で届いた現物がこちら
add_memory_edge13_1.jpg

これを交換していきます

PC を開ける

まず Edge13 の背面にあるパネルを開けましょう
ネジで止まっているだけなのでプラスドライバを使って開けます
全部で 5 箇所あります
add_memory_edge13_2.jpg

パネルが外れると基盤が出てきます
右下の部分にメモリがあります
2 スロット分ありデフォルトだと 1 スロットだけ使っています
add_memory_edge13_3.jpg

メモリを取り外す

今回は既存のを取り外して 4GB に交換します
メモリが刺さっている部分に銀の部品でメモリを押さえています
ちょっと堅いですが左右に引っ張るとメモリが出てくるようになるので左右同時に開いてみましょう
こんな感じで上にメモリが上がってくれば OK です
出てこない場合は金具を左右に開きながらメモリを持ち上げましょう
add_memory_edge13_4.jpg

あとは抜けば OK です

新しいメモリを取り付ける

取り外したら新しいメモリに交換しましょう
付けるときは先に斜めに差し込んであげます
ちゃんと奥まで差し込めていないと写真のように斜めに自立して上がりません
add_memory_edge13_5.jpg

差し込めたらあとは上から両指で下に押し込んであげれば OK です
金具の部分は少し力を入れてグッと押し込めば「パチン」といってしっかりハマってくれます
add_memory_edge13_6.jpg

2 枚あるので向きを間違えないようにしましょう
と言っても凹みがあるので大丈夫だと思います

あとはパネルを再度してネジで固定すれば OK です

動作確認

マシンを起動してちゃんと物理メモリが 8GB になっているか確認してみましょう
add_memory_edge13_0.png

問題なさそうです

最後に

今更ですが Lenovo Edge13 のメモリを 8GB に増設してみました
とりあえず複数ブラウザを上げるだけでもカクカクだったのでさすがにそれは解消しました

グラフィックボードや CPU がそもそもダメなのでゲーミング PC レベルにはなれませんがストレスなく作業できるようにはなったかなと思います

Lenovo Edge13 は 2010 年に出たマシンなのでそもそも低スペックです
がグレードアップできるパーツを交換することは今でもできるので可能な限りやってあげればまだまだ現役で動かすことはできるかなと思います

2017年12月19日火曜日

独自のクラフトレシピを作成する方法

概要

前回、独自鉱石を作成してみました
今回はその鉱石とインゴットをクラフトに使えるようにレシピを追加してみます

環境

  • macOS X 10.13.2
  • Minecraft 1.12.2
  • Forge 1.12.2 - 14.23.1.2555
  • Forge MDK 1.12.2 - 14.23.1.2555
  • Java 1.8.0_151
  • eclipse Oxygen.1a Release (4.7.1a)

com.sample.mod.handlers の作成

  • RecipeHandler.java
package com.sample.mod.handlers;

import com.sample.mod.init.BlockInit;
import com.sample.mod.init.ItemInit;

import net.minecraft.init.Blocks;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fml.common.registry.GameRegistry;

public class RecipeHandler {

    public static void registerCrafting() {
        GameRegistry.addShapedRecipe(new ResourceLocation("sm:sample_ore"), new ResourceLocation("sm:sample_blocks"), new ItemStack(BlockInit.sample_ore), new Object[] {"SSS", "SIS", "SSS", 'S', Blocks.STONE, 'I', ItemInit.sample_ingot});
    }

    public static void registerSmelting() {
        GameRegistry.addSmelting(BlockInit.sample_ore, new ItemStack(ItemInit.sample_ingot), 10);
    }
}

ポイントは GameRegistry.addShapedRecipeGameRegistry.addSmelting を使ってクラフトと精錬の定義を追加するという点です

まずクラフトレシピの追加に使う addShapedRecipe は 4 つの引数を使います
1 つ目はどのアイテムのレシピとして登録するか指定します
2 つ目は登録するレシピをどのグループのレシピに登録するか指定します
今回であれば sample_ore のクラフトであり sample_blocks のグループにレシピを登録します
3 つ目は実際にできる成果物です
今回はインゴットと石を使って独自鉱石を作成します
そして 4 つ目が作業台を使ってクラフトする際のレシピになります
Object クラスの配列として作成します
配列の使用するアイテムの数で上限するので可変です

  • new Object[] {"SSS", "SIS", "SSS", 'S', Blocks.STONE, 'I', ItemInit.sample_ingot}

今回の場合であれば S -> STONE と I -> 独自インゴットをクラフトに使うように定義しています
そして 3x3 のクラフトマスにどうやってそれらを配置するか定義します
各行ごとに String で定義する必要があり例えば "SSS" であれば一番上は石を 3 つ配置するということになります
ちなみに今回は 3x3 全部にアイテムを置くようにレシピを作成していますがピッケルや斧のように全マスを使用しないレシピなどの場合は半角スペースを使うことで空を表現することができます

精錬はかまどを使って作成することができるレシピです
その場合は addSmelting を使います
第一引数に精錬にしようするアイテムを指定して第二引数に作成されるアイテムを指定します
そして第三引数の数字は精錬時に取得できる経験値を指定します

  • RegistyHandler.java
package com.sample.mod.handlers;

import com.sample.mod.init.BlockInit;
import com.sample.mod.init.ItemInit;

public class RegistyHandler {

    public static void Client() {
        RecipeHandler.registerCrafting();
        RecipeHandler.registerSmelting();
    }

    public static void Common() {
        ItemInit.init();
        ItemInit.register();
        BlockInit.init();
        BlockInit.register();
        BlockInit.registerRenders();
    }
}

Client 側にレシピを登録する処理を追記します

これまでのも含めてパッケージエクスプローラは以下のようになっています
origin_craft1.png

動作確認

では動作確認してみます
テストには作業台とレシピ、石、独自インゴット、燃料 (今回は石炭) が必要になるのでインベントリから取得しておきましょう
まずクラフト側ですが指定の通りに石と独自インゴットを配置すると独自鉱石が生成できるようになっています
origin_craft2.png

origin_craft3.png

こんな感じです
次に精錬ですができた鉱石をそのまま精錬してみましょう
すると独自インゴットが作成できます
origin_craft4.png

origin_craft5.png

最後に

独自のクラフトレシピと精錬レシピを作成してみました
アイテムを追加したりするよりかはずっと簡単に作成できると思います
が、基本はその前に鉱石なりインゴットなり各種アイテムを作成しておく必要があるかなと思います

今回は鉱石とインゴットのレシピだけでしたがインゴットを生成したら武器なり防具なりを生成したくなります
それも同じようにレシピを登録するだけでできます
ただ、その際は武器や防具なりのアイテムの登録が必要になるのでやってみたい方はまずそこからやってみてください

また作業台を使わないでもクラフトできる不定形レシピも登録することができその場合は addShapelessRecipe を使います
不定形レシピとは例えば原木から木材を作成するレシピのようなことを指します

参考サイト

2017年12月18日月曜日

独自の鉱石をワールド内に発生させる方法

概要

前回 独自の鉱石を作成しました
これまではインベントリから取得できましたが今回は自然の世界にランダムで発生させてみたいと思います

環境

  • macOS X 10.13.2
  • Minecraft 1.12.2
  • Forge 1.12.2 - 14.23.1.2555
  • Forge MDK 1.12.2 - 14.23.1.2555
  • Java 1.8.0_151
  • eclipse Oxygen.1a Release (4.7.1a)

各種 Java ファイルの作成

コードを書いていきます

com.sample.mod.gen パッケージの作成

  • SampleOreGen.java
package com.sample.mod.gen;

import java.util.Random;

import com.sample.mod.init.BlockInit;

import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraft.world.chunk.IChunkProvider;
import net.minecraft.world.gen.IChunkGenerator;
import net.minecraft.world.gen.feature.WorldGenMinable;
import net.minecraft.world.gen.feature.WorldGenerator;
import net.minecraftforge.fml.common.IWorldGenerator;

public class SampleOreGen implements IWorldGenerator {

    private WorldGenerator sample_ore;

    public SampleOreGen() {
        sample_ore = new WorldGenMinable(BlockInit.sample_ore.getDefaultState(), 9);
    }

    @Override
    public void generate(Random random, int chunkX, int chunkZ, World world, IChunkGenerator chunkGenerator,
            IChunkProvider chunkProvider) {
        switch(world.provider.getDimension()) {
        case 0:
            runGenerator(sample_ore, world, random, chunkX, chunkZ, 50, 0, 50);
            break;
        case 1:
            break;
        case -1:
            break;
        }
    }

    private void runGenerator(WorldGenerator gen, World world, Random rand, int chunkX, int chunkZ, int chance, int minHeight, int maxHeight) {
        if (minHeight > maxHeight || minHeight < 0 || maxHeight > 256) throw new IllegalArgumentException("Ore generated out of bounds");
        int heightDiff = maxHeight - minHeight + 1;
        for (int i = 0; i < chance; i++) {
            int x = chunkX * 16 + rand.nextInt(16);
            int y = minHeight + rand.nextInt(heightDiff);
            int z = chunkZ * 16 + rand.nextInt(16);
            gen.generate(world, rand, new BlockPos(x, y, z));
        }
    }
}

WorldGenMinable でワールドを作成します
第二引数の 9 は鉱石が見つかった際に塊としていくつ周りに生成させるか指定できます

Override している generate でどのワールドに生成するかハンドリングします
world.provider.getDimension() で現在どのワールドタイプにいるのか取得することができます
-1 がネザーで 0 が通常世界で 1 がエンドポータルになります
今回は通常世界での鉱石は発生させるようにします

runGenerator で鉱石を配置する座標をランダムに決定し独自の鉱石が発生するワールドを作成します
まず高さのチェックをします
0 から 256 の範囲外は指定できないのでそれ以外が指定された場合はエラーとします
チャンクごとに chance で指定された回数分ワールドを作成します
chance が小さいほど 1 チャンク内に出現する鉱石の数は少なくなります
x, y, z の座標を生成しワールドを作成します
鉱石を発生させる高さを minHeight と maxHeight で指定できます
今回は 0 - 50 の高さで発生するようにしました

com.sample.mod.handlers パッケージの作成

  • RegistryHandler.java
package com.sample.mod.handlers;

import com.sample.mod.gen.SampleOreGen;
import com.sample.mod.init.BlockInit;
import com.sample.mod.init.ItemInit;

import net.minecraftforge.fml.common.registry.GameRegistry;

public class RegistyHandler {

    public static void Client() {
        RecipeHandler.registerCrafting();
        RecipeHandler.registerSmelting();
    }

    public static void Common() {
        ItemInit.init();
        ItemInit.register();
        BlockInit.init();
        BlockInit.register();
        BlockInit.registerRenders();
        GameRegistry.registerWorldGenerator(new SampleOreGen(), 0);
    }
}

GameRegistry.registerWorldGenerator(new SampleOreGen(), 0); で鉱石を発生させるワールドを登録します
第二引数はワールドの重みを指定することができます
大きければ大きいほど生成が後ろ回しになるため鉱石をあまり発生させたくない場合は値を大きくします

動作確認

クリエイティブモードでワールドを作成しましょう
今回の設定値であればそのまま下に掘っていけば簡単に見つかると思います
指定した高さの座標内で見つかると思います
またその周辺にも鉱石が発生しているのが確認できると思いますgen_org_ore1.png

最後に

独自で作成した鉱石をゲームワールド内に発生させる方法を紹介しました
新規で作成した鉱石の重みが軽いとたくさん作成されてしまうので、既存の鉱石の発生確率が下がってしまう点は注意してください

鉱石側のチューニング (壊せる回数や壊せるピッケルレベルなど) は鉱石側の設定で行ってください

参考サイト

2017年12月17日日曜日

Forge MDK を使って独自の鉱石を作成する

概要

前回 独自インゴットを作成してみました
今回はブロックの鉱石を作成してみます
コードは前回のものをそのまま流用し追加していきます

環境

  • macOS X 10.13.2
  • Minecraft 1.12.2
  • Forge 1.12.2 - 14.23.1.2555
  • Forge MDK 1.12.2 - 14.23.1.2555
  • Java 1.8.0_151
  • eclipse Oxygen.1a Release (4.7.1a)

各種 Java ファイルの作成

コードを書いていきます

com.sample.mod パッケージの作成

  • Reference.java

変更なし

  • SampleMod.java

変更なし

com.sample.mod.handlers パッケージの作成

  • RegistyHandler.java
package com.sample.mod.handlers;

import com.sample.mod.init.BlockInit;
import com.sample.mod.init.ItemInit;

public class RegistyHandler {

    public static void Client() {
    }

    public static void Common() {
        ItemInit.init();
        ItemInit.register();
        BlockInit.init();
        BlockInit.register();
        BlockInit.registerRenders();
    }
}

BlockInit の処理をコールします
BlockInit は後で作成します

com.sample.mod.init パッケージの作成

  • BlockInit.java
package com.sample.mod.init;

import com.sample.mod.init.blocks.CustomOre;

import net.minecraft.block.Block;
import net.minecraft.client.renderer.block.model.ModelResourceLocation;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.item.Item;
import net.minecraft.item.ItemBlock;
import net.minecraftforge.client.model.ModelLoader;
import net.minecraftforge.fml.common.registry.ForgeRegistries;

public class BlockInit {
    public static Block sample_ore;

    public static void init() {
        sample_ore = new CustomOre("sample_ore", 2.0F, 4.0F, 2);
    }

    public static void register() {
        registerBlock(sample_ore);
    }

    public static void registerBlock(Block block) {
        ForgeRegistries.BLOCKS.register(block);
        block.setCreativeTab(CreativeTabs.BUILDING_BLOCKS);
        ItemBlock item = new ItemBlock(block);
        item.setRegistryName(block.getRegistryName());
        ForgeRegistries.ITEMS.register(item);
    }

    public static void registerRenders() {
        registerRender(sample_ore);
    }

    public static void registerRender(Block block) {
        ModelLoader.setCustomModelResourceLocation(Item.getItemFromBlock(block), 0, new ModelResourceLocation(block.getRegistryName(), "inventory"));
    }
}

作成する鉱石の登録と描画を行います
CustomOre クラスを定義してそちらで鉱石の定義を行います

com.sample.mod.init.blocks パッケージの作成

  • CustomBlock.java
package com.sample.mod.init.blocks;

import net.minecraft.block.Block;
import net.minecraft.block.material.Material;

public class CustomBlock extends Block {

    public CustomBlock(String name, float hardness, float resistance) {
        super(Material.ROCK);
        setUnlocalizedName(name);
        setRegistryName(name);
        setHardness(hardness);
        setResistance(resistance);
    }
    public CustomBlock(Material materialIn) {
        super(materialIn);
    }

}

まず CustomBlock でブロックの定義と設定を行います
hardness は鉱石の硬さで resistance はピッケルの耐久度に影響する値です

  • CustoreOre.java
package com.sample.mod.init.blocks;

import net.minecraft.block.material.Material;

public class CustomOre extends CustomBlock {

    public CustomOre(String name, float hardness, float resistance, int harvestLevel) {
        super(name, hardness, resistance);
        setHarvestLevel("pickaxe", harvestLevel);
    }

    public CustomOre(Material materialIn) {
        super(materialIn);
    }

}

先ほど作成した CustomBlock を継承して作成します
harvestLevel はピッケルのレベルを指定することができます
木以上で掘れる鉱石、石以上で掘れる鉱石、鉄以上で掘れる鉱石などを定義することができます

com.sample.mod.proxy パッケージの作成

  • ClientProxy.java

変更なし

  • CommonProxy.java

変更なし

各種リソースファイルの作成

次に各種リソースファイルを作成します
リソースファイルとは mod の画像や定義情報のことを指します

assets.sm.lang

  • en_us.lang
item.sample_ingot.name=Sample Ingot
tile.sample_ore.name=Sample Ore

鉱石用の名前の定義を追記します

assets.sm.models.block

  • sample_ore.json
{
    "parent": "block/cube_all",
    "textures": {
        "all": "sm:blocks/sample_ore"
    }
}

鉱石としての定義を追加します

assets.sm.models.item

  • sample_ore.json
{
    "parent": "sm:block/sample_ore"
}

アイテムとしての定義を追加します

assets.sm.blockstates

  • sample_ore.json
{
    "variants": {
        "normal": { "model": "sm:sample_ore" }
    }
}

ブロックの形状を定義するファイルです
とりあえず鉄鉱石のものをそのまま採用します

assets.sm.textures.blocks

  • sample_ore.png

sample_ore.png

これも既存の鉄鉱石の画像を適当に変更して使用します

その他

  • mcmod.info

変更なし

全体としてプロジェクトエクスプローラが以下のようになっていれば OK です
origin_ore3.png

動作確認

プロジェクトを選択して Client の実行の構成から起動しましょう
成功するとブロックの一覧に表示され更にブロックなので置くこともできます

ブロック一覧
origin_ore2.png

配置した様子
origin_ore1.png

最後に

Forge MDK で独自の鉱石を作成してみました
クラフトなどの定義を追加すれば素材としても使えます

クラフトの定義方法なども勉強してそのうち紹介できればなとは思っています

参考サイト

2017年12月16日土曜日

Forge MDK を使って簡単な独自 Mod を開発してみた

概要

前回 Forge MDK + eclipse をインストールして Mod を開発する環境を構築してみました
今回はそこから簡単な独自 Mod を作成するところまでやってみました
origin_ingot2.png

環境

  • macOS X 10.13.2
  • Minecraft 1.12.2
  • Forge 1.12.2 - 14.23.1.2555
  • Forge MDK 1.12.2 - 14.23.1.2555
  • Java 1.8.0_151
  • eclipse Oxygen.1a Release (4.7.1a)

各種 Java ファイルの作成

まずはコードを書いていきます

com.sample.mod パッケージの作成

  • Reference.java
package com.sample.mod;

public class Reference {
    public static final String MODID = "sm";
    public static final String NAME = "Sample Mod";
    public static final String VERSION = "0.1";
    public static final String CLIENTPROXY = "com.sample.mod.proxy.ClientProxy";
    public static final String COMMONPROXY = "com.sample.mod.proxy.CommonProxy";
}

各種 mod に必要な情報を定義するクラスです

  • SampleMod.java
package com.sample.mod;

import com.sample.mod.proxy.CommonProxy;

import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.Mod.EventHandler;
import net.minecraftforge.fml.common.SidedProxy;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;

@Mod(modid = Reference.MODID, name = Reference.NAME, version = Reference.VERSION)
public class SampleMod {

    @SidedProxy(clientSide = Reference.CLIENTPROXY, serverSide = Reference.COMMONPROXY)
    public static CommonProxy proxy;

    @EventHandler
    public static void preInit(FMLPreInitializationEvent event) {
        proxy.preInit(event);
    }

    @EventHandler
    public static void init(FMLInitializationEvent event) {
        proxy.init(event);
    }

    @EventHandler
    public static void postInit(FMLPostInitializationEvent event) {
        proxy.postInit(event);
    }
}

メインクラスです
ここでは各種ハンドラの処理やアイテムを生成する処理をコールしているだけです
実際の処理は別のパッケージで定義していきます

com.sample.mod.handlers パッケージの作成

  • RegistyHandler.java
package com.sample.mod.handlers;

import com.sample.mod.init.ItemInit;

public class RegistyHandler {

    public static void Client() {
    }

    public static void Common() {
        ItemInit.init();
        ItemInit.register();
    }
}

各種アイテムなどを登録する処理を定義するクラスです
init および register は Common 側でコールしましょう
v1.11 の場合は register は Client でコールしますが、v1.12 の場合は Common 側でどちらもコールします
ItemInit クラスはこの後作成します

com.sample.mod.init パッケージの作成

  • ItemInit.java
package com.sample.mod.init;

import com.sample.mod.init.items.CustomIngot;

import net.minecraft.client.renderer.block.model.ModelResourceLocation;
import net.minecraft.item.Item;
import net.minecraftforge.client.model.ModelLoader;
import net.minecraftforge.fml.common.registry.ForgeRegistries;

public class ItemInit {

    public static Item sample_ingot;

    public static void init() {
        sample_ingot = new CustomIngot("sample_ingot");     
    }

    public static void register() {
        registerItem(sample_ingot);
    }

    public static void registerItem(Item item) {
        ForgeRegistries.ITEMS.register(item);
//      Minecraft.getMinecraft().getRenderItem().getItemModelMesher().register(item, 0, new ModelResourceLocation(item.getRegistryName(), "inventory"));
        ModelLoader.setCustomModelResourceLocation(item, 0, new ModelResourceLocation(item.getRegistryName(), "inventory"));
    }
}

アイテムを生成しマインクラフトの世界に追加します
今回はインベントリに追加します
またここでポイントですがマインクラフトの世界にアイテムを追加する場合は ModelLoader.setCustomModelResourceLocation を使います
コメントアウトしている Minecraft.getMinecraft() は v1.11 だと動作するのですが、v1.12 だと動作しないので注意してください (NullPointerException が発生します)

com.sample.mod.init.items パッケージの作成

  • CustomIngot.java
package com.sample.mod.init.items;

import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.item.Item;

public class CustomIngot extends Item {

    public CustomIngot(String name) {
        setUnlocalizedName(name);
        setRegistryName(name);
        setCreativeTab(CreativeTabs.MATERIALS);
    }
}

今回はインゴットを追加してみます
なのでカスタムするインゴット用のクラスを作成します
名前の登録とクリエイティブの設定を行います
今回は MATERIALS のタブ内にアイテムを追加します

com.sample.mod.proxy パッケージの作成

  • ClientProxy.java
package com.sample.mod.proxy;

import com.sample.mod.handlers.RegistyHandler;

import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;

public class ClientProxy extends CommonProxy {
    public void preInit(FMLPreInitializationEvent event) {
        super.preInit(event);
    }

    public void init(FMLInitializationEvent event) {
        super.init(event);
        RegistyHandler.Client();
    }

    public void postInit(FMLPostInitializationEvent event) {
        super.postInit(event);
    }
}

クライアントで動作させる場合の初期化処理を定義します

  • CommonProxy.java
package com.sample.mod.proxy;

import com.sample.mod.handlers.RegistyHandler;

import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;

public class CommonProxy {
    public void preInit(FMLPreInitializationEvent event) {
        RegistyHandler.Common();
    }

    public void init(FMLInitializationEvent event) {
    }

    public void postInit(FMLPostInitializationEvent event) {
    }
}

サーバまたはクライアント上で動作する際の共通処理を定義します
RegistyHandler.Common() をコールすることでゲーム開始時に今回追加するアイテムの登録処理を行います

各種リソースファイルの作成

次に各種リソースファイルを作成します
リソースファイルとは mod の画像や定義情報のことを指します

assets.sm.lang

  • en_us.lang
item.sample_ingot.name=Sample Ingot

mod の名前を定義するファイルです
各言語ごとにファイルを用意すればローカライズされたときに適切な名前を返すことができます

assets.sm.models.item

  • sample_ingot.json
{
    "parent": "item/generated",
    "textures": {
        "layer0": "sm:items/sample_ingot"
    }
}

mod の定義ファイルです
今回や画像情報しか定義しませんがここにアイテムの効果や使われ方、クラフト方法を定義することもできます

assets.sm.textures.items

  • sample_ingot.png

sample_ingot.png

既存の鉄インゴットの画像を適当に編集して作成しました

その他

  • mcmod.info
[
{
  "modid": "sm",
  "name": "Sample Mod",
  "description": "This is my sample mod.",
  "version": "${version}",
  "mcversion": "${mcversion}",
  "url": "",
  "updateUrl": "",
  "authorList": ["hawksnowlog"],
  "credits": "hawksnowlog",
  "logoFile": "",
  "screenshots": [],
  "dependencies": []
}
]

mod 全体の情報を定義します
Forge の Mods 一覧に表示される際の情報になります

全体としてプロジェクトエクスプローラが以下のようになっていれば OK です
origin_ingot0.png

動作確認

プロジェクトを右クリックして Client で動作させてみましょう
起動後インベントリを開いて Materials のシークバーを一番下に持っていって最後に追加した mod があれば成功です
origin_ingot1.png

最後に

独自の mod を作成してみました
今回は本当にただ追加しただけなので何も効果のないアイテムになっています
ここからクラフト情報などを追加していく必要はあります

参考サイトにありますが動画のチュートリアルが非常に参考になります
ただ、Minecraft のバージョンによって動作する API がだいぶ変わっているので注意が必要です

Java で書くのが少し辛いですが API や開発方法には一定のパターンがあるのでイベントハンドリングやリソースファイルの配置などを覚えれば結構簡単に作れるようになると思います
あとは Web 上に先人の方が作られた mod のサンプルがたくさんあるのでそられを参考に頑張れば何とかなると思います

参考サイト

2017年12月15日金曜日

Forge MDK をインストールして独自 mod の開発環境を構築してみる

概要

これまで Forge と Raspberry Jam Mod を使って Ruby から Minecraft 自体を操作することをやってきました
PC 版の Minecraft は独自で Mod を作成することも可能です
JVM で動作しているので基本は Java を使って開発します
開発用のキットが配布されているので今回はそれをインストールして開発環境を構築してみました

環境

  • macOS X 10.13.2
  • Minecraft 1.12.2
  • Forge 1.12.2 - 14.23.1.2555
  • Forge MDK 1.12.2 - 14.23.1.2555
  • Java 1.8.0_151
  • eclipse Oxygen.1a Release (4.7.1a)

Forge MDK のダウンロード

公式からダウンロードできます
前回はここから Forge 本体をダウンロードしましたが今回は Forge MDK をダウンロードします
バージョンが合うようにダウンロードしましょう
install_forge_mdk1.png

forge-1.12.2-14.23.1.2555-mdk.zip というファイルがダウンロードできました

展開とインストール

ダウンロードできたら展開します
展開したら作業ディレクトリに移動しましょう

  • cd Downloads/
  • mkdir /path/to/mc-work
  • mv forge-1.12.2-14.23.1.2555-mdk.zip /path/to/mc-work
  • cd /path/to/mc-work
  • unzip forge-1.12.2-14.23.1.2555-mdk.zip

でいろいろとファイルが展開されます
その中の gradlew を実行します

  • ./gradlew setupDecompWorkspace

上記のコマンドは同梱の README.txt にも記載があります
gradle がインストールされていない場合は勝手にダウンロードしてインストールしてくれます
必要なライブラリをダウンロードしてビルドしてくれるので完了するまで待ちます

recompileMc で失敗する場合は

ここに記載のある通り最新の JDK にアップデートしましょう
他に vecmath.jar がシステムライブラリのパスにあるからエラーになるという情報もありますが自分はそれではなく JDK のバージョンが原因でした

eclipse 用のプロジェクトファイルを作成する

今回は IDE に eclipse を使うので以下のコマンドを実行してプロジェクト用のファイルなどを作成しましょう

  • ./gradlew eclipse

すると配下に .project ファイルが作成されると思います

eclipse でプロジェクトを開く

あとは eclipse を開いて先ほどビルドしたパスを指定してプロジェクトを開けば OK です

  • File -> Open Projects from File Systems
  • Import source から先ほどのディレクトリ (/path/to/mc-work) を指定
  • Finish で完了

パッケージエクスプローラで確認して以下のようになっていれば OK です
install_forge_mdk2.png

サンプルを実行してみる

src/main/java 配下に com.example.examplemod.ExampleMod.java があるのでこれを実行してみましょう
プロジェクトを右クリックして Run Configurations を選択します
すると Client と Server の実行設定がすでに存在していると思うので Client 側を実行してみます
install_forge_mdk3.png

すると勝手に Minecraft の Forge プロファイル版で起動してきます
install_forge_mdk4.png

起動したら Mods を見てみましょう
サンプル用の Mod の情報が一覧にあるのが確認できると思います
install_forge_mdk5.png

今回のサンプル Mod はコンソールにメッセージを表示するだけです
以下のようにメッセージが表示されているのを確認できると思います
install_forge_mdk6.png

最後に

Forge MDK をインストールして mod を開発する環境構築を行ってみました
バージョン周りで躓くところはありましたが比較的スムーズに構築できました
eclipse + Java が少し障壁が高いですが頑張ってインストールしてみてください
次回は実際に簡単な mod を開発するところまでやってみたいと思います

参考サイト

2017年12月14日木曜日

Minecraft でお家を自動構築してみた

概要

前回までに紹介している minecraft-pi-ruby を使ってそれっぽい家をコマンド一発で作成してみました
所謂チートになるのでメインのワールドではなく遊びで作ったワールドで試すことをおすすめします
なお使うには Forge + Raspberry Jam Mod が必要になるのでまだの方は以下を参考にインストールしてください

環境

  • macOS X 10.13.2
  • Minecraft 1.12.2
  • Forge 1.12.2 - 14.23.1.2555
  • Raspberry Jam 0.93
  • Ruby 2.4.1p111
  • minecraft-pi-ruby 0.0.1

スクリプト

幅 10 高さ 6 奥行き 10 の家を立てます
内装もそれっぽくしています
基本は座標情報を作成して set_block で適切なブロックを配置していきます
初めに土地を整地してから建築しています
今回は 1F 分しか作っていませんが同じように 2F を作ったり地下を作成したりもできると思います
あと庭とか牧場とかも自動で構築できると思います

# coding: utf-8
require 'minecraft-pi-ruby'

class House
  def initialize
    @mc = Minecraft.new
    @base = @mc.get_player_position
  end

  def f1
    front
    right_side
    left_side
    back
    proof
    stairs
    furniture
  end

  def clear
    xrange = -13..13
    yrange = 0..10
    zrange = -13..13
    xrange.each { |x|
      yrange.each { |y|
        zrange.each { |z|
          @mc.set_block(@base.x + x, @base.y + y, @base.z + z, Block::AIR)
        }
      }
    }
  end

  private
  def front
    # レンガx5, レンガx5
    pos1 = @base.clone
    pos2 = @base.clone
    @mc.set_blocks(pos1, pos2.move(x: 4), Block::BRICK_BLOCK)
    @mc.set_blocks(pos2.move(x: 2), pos1.move(x: 10), Block::BRICK_BLOCK)
    # 扉
    pos3 = @base.clone.move(x: 5)
    @mc.set_block(pos3.x, pos3.y, pos3.z, Block::DOOR_WOOD, 0)
    @mc.set_block(pos3.x, pos3.y + 1, pos3.z, Block::DOOR_WOOD, 8)
    # レンガx5, レンガx5
    pos1 = @base.clone.move(y: 1)
    pos2 = @base.clone.move(y: 1)
    @mc.set_blocks(pos1, pos2.move(x: 4), Block::BRICK_BLOCK)
    @mc.set_blocks(pos2.move(x: 2), pos1.move(x: 10), Block::BRICK_BLOCK)
    # レンガ11 x 縦4
    4.times { |i|
      pos1 = @base.clone.move(y: i + 2)
      pos2 = @base.clone.move(x: 10, y: i + 2)
      @mc.set_blocks(pos1, pos2, Block::BRICK_BLOCK)
    }
    # 松明
    5.times { |x|
      pos4 = @base.clone.move(x: (x * 2) + 1, y: 3)
      @mc.set_block(pos4.x, pos4.y, pos4.z, Block::TORCH, 5)
    }
  end

  private
  def right_side
    # レンガ11 x 縦6
    6.times { |i|
      pos1 = @base.clone.move(y: i)
      pos2 = @base.clone.move(y: i, z: 10)
      @mc.set_blocks(pos1, pos2, Block::BRICK_BLOCK)
    }
    # 窓
    pos1 = @base.clone.move(y: 1, z: 2)
    pos2 = @base.clone.move(y: 2, z: 3)
    @mc.set_blocks(pos1, pos2, Block::GLASS)
    @mc.set_blocks(pos1.move(z: 5), pos2.move(z: 5), Block::GLASS)
    # 松明
    5.times { |z|
      pos4 = @base.clone.move(x: -1, y: 3, z: (z * 2) + 1)
      @mc.set_block(pos4.x, pos4.y, pos4.z, Block::TORCH, 2)
    }
  end

  def left_side
    # レンガ11 x 縦6
    6.times { |i|
      pos1 = @base.clone.move(x: 10, y: i)
      pos2 = @base.clone.move(x: 10, y: i, z: 10)
      @mc.set_blocks(pos1, pos2, Block::BRICK_BLOCK)
    }
    # 窓
    pos1 = @base.clone.move(x: 10, y: 1, z: 2)
    pos2 = @base.clone.move(x: 10, y: 2, z: 3)
    @mc.set_blocks(pos1, pos2, Block::GLASS)
    @mc.set_blocks(pos1.move(z: 5), pos2.move(z: 5), Block::GLASS)
    # 松明
    5.times { |z|
      pos4 = @base.clone.move(x: 11, y: 3, z: (z * 2) + 1)
      @mc.set_block(pos4.x, pos4.y, pos4.z, Block::TORCH, 1)
    }
  end

  def back
    # レンガ11 x 縦6
    6.times { |i|
      pos1 = @base.clone.move(y: i, z: 10)
      pos2 = @base.clone.move(x: 10, y: i, z: 10)
      @mc.set_blocks(pos1, pos2, Block::BRICK_BLOCK)
    }
    # 松明
    5.times { |x|
      pos4 = @base.clone.move(x: (x * 2) + 1, y: 3, z: 11)
      @mc.set_block(pos4.x, pos4.y, pos4.z, Block::TORCH, 3)
    }
  end

  def proof
    # ガラス
    9.times { |x|
      9.times { |z|
        pos1 = @base.clone.move(x: 1 + x, y: 5, z: 1 + z)
        if z % 2 == 0
          @mc.set_block(pos1.x, pos1.y, pos1.z, Block::GLASS)
        else
          @mc.set_block(pos1.x, pos1.y, pos1.z, Block::BRICK_BLOCK)
        end
      }
    }
  end

  def stairs
    # 階段
    7.times { |z|
      6.times { |y|
        pos1 = @base.clone.move(x: 1, y: y, z: 3 + z)
        pos2 = @base.clone.move(x: 2, y: y, z: 3 + z)
        if y == z
          @mc.set_block(pos1.x, pos1.y, pos1.z, 108, 2)
          @mc.set_block(pos2.x, pos2.y, pos2.z, 108, 2)
          break
        else
          @mc.set_block(pos1.x, pos1.y, pos1.z, Block::BRICK_BLOCK)
          @mc.set_block(pos2.x, pos2.y, pos2.z, Block::BRICK_BLOCK)
        end
      }
    }
    # 外に出れるように穴を開ける
    3.times { |z|
      pos1 = @base.clone.move(x: 1, y: 5, z: 5 + z)
      pos2 = @base.clone.move(x: 2, y: 5, z: 5 + z)
      @mc.set_block(pos1.x, pos1.y, pos1.z, Block::AIR)
      @mc.set_block(pos2.x, pos2.y, pos2.z, Block::AIR)
    }
  end

  def furniture
    # ラージチェスト
    3.times { |y|
      3.step(6, 3).to_a.each { |x|
        pos1 = @base.clone.move(x: x, y: y, z: 9)
        @mc.set_block(pos1.x, pos1.y, pos1.z, Block::CHEST)
        @mc.set_block(pos1.x + 1, pos1.y, pos1.z, Block::CHEST)
      }
    }
    # かまど
    pos1 = @base.clone.move(x: 5, z: 9)
    @mc.set_block(pos1.x, pos1.y, pos1.z, Block::FURNACE_ACTIVE)
    # 作業台
    pos1.move(x: 3)
    @mc.set_block(pos1.x, pos1.y, pos1.z, Block::CRAFTING_TABLE)
    # 本棚
    3.times { |z|
      2.times { |y|
        pos1 = @base.clone.move(x: 9, y: y, z: 4 + z)
        @mc.set_block(pos1.x, pos1.y, pos1.z, Block::BOOKSHELF)
      }
    }
  end
end

h = House.new
h.clear
h.f1

家の前面、背面、左右、天井を別々の関数で定義しています
あとは家具系のアイテムを配置する関数も用意しています

松明を配置するときだけ少し座標の把握が必要かもしれません
汎用的に作成しているわけではないので、家を広げたり家具を移動する場合は頑張ってポジション情報を変更してください

あとは実行するだけです
実行する際はマイクラを起動しておくのを忘れずに

  • bundle exec ruby house.rb

動作確認

こんな感じの家が一瞬で建ちます
内装
auto_building_my_house1.png

外観
auto_building_my_house2.png

最後に

minecraft-pi-ruby を使って家を自動で構築してみました
とりあえず簡単な家を作成しただけですが、あとはこれを応用するだけで何でもできると思います
一点注意が必要なのは実行したら元の状態には戻せません
自分で家を破壊することは可能ですが元の地形に完全に戻すことはできません

チートなのでサバイバルモードに飽きたらやるようにしましょう
プログラムの勉強にも良いかなとは思うんですが単純なコードになるのでガッツリ勉強するのには向かないかもです

2017年12月13日水曜日

minecraft-pi-ruby でトビラを設置する方法

概要

少しクセのある感じだったので備忘録がてら別記事で残しておこうと思います

環境

  • macOS X 10.13.2
  • Minecraft 1.12.2
  • Forge 1.12.2 - 14.23.1.2555
  • Raspberry Jam 0.93
  • Ruby 2.4.1p111
  • minecraft-pi-ruby 0.0.1

コード

require 'minecraft-pi-ruby'

mc = Minecraft.new
base = mc.get_player_position

mc.set_block(base.x, base.y, base.z, Block::DOOR_WOOD, 0)
mc.set_block(base.x, base.y + 1, base.z, Block::DOOR_WOOD, 9)

上記だと現在位置に木の扉を作成します
ポイントは扉の上下を別々で作成する必要があるという点です
set_block は 1 つ分のブロックしか作成することができないので扉を作成するには 2 度コールする必要があります

また最後の引数の 0, 8 で 0 が下側の扉を作成するフラグで 8 が上の扉を作成するフラグになります
上の扉は 9 も指定することができて、手前に作成するか後ろに作成するかの違いがあります

また、作成する座標が中に浮いている座標だと扉は設置されずドロップされた状態で生成されます

最後に

minecraft-pi-ruby で扉を設置する方法を紹介しました
他のブロックもこんな感じで 2 回コールしないと設置できないものがあります
また、第 5 引数によって配置する際の挙動が変わるので注意しましょう
ちなみに松明はかなりクセがあるので注意しましょう

mc.set_block(pos.x, pos.y, pos.z - 1 , Block::TORCH, 4)

これでブロックの手前に松明が設置できます
ブロックがある pos から 1 つ手前に松明を設置するようにして第 5 引数で松明を North の方角に設置するように命令しています

参考サイト

2017年12月12日火曜日

minecraft-pi-ruby サンプル集

概要

ちょろっと触ったので残しておきます
基本的な操作を押さえています
minecraft-pi-ruby の環境構築こちら

環境

  • macOS X 10.13.2
  • Minecraft 1.12.2
  • Forge 1.12.2 - 14.23.1.2555
  • Raspberry Jam 0.93
  • Ruby 2.4.1p111
  • minecraft-pi-ruby 0.0.1

サンプルスクリプト

# coding: utf-8
require 'minecraft-pi-ruby'

mc = Minecraft.new

# プレイヤーの座標を取得
ppos = mc.get_player_position
mc.say ppos

# プレイヤーの隣に丸石を作成
x = ppos.x + 1
mc.set_block(x, ppos.y, ppos.z, Block::STONE)

# プレイヤーの前にダイヤブロックを作成
z = ppos.z + 1
mc.set_block(ppos.x, ppos.y, z, Block::DIAMOND_BLOCK)

# プレイヤーの上に金ブロックを作成
y = ppos.y + 2
mc.set_block(ppos.x, y, ppos.z, Block::GOLD_BLOCK)

# 現在位置から 10 高い頭上に 10 x 10 の金ブロックを作成
bpos1 = ppos.clone
bpos1.y += 10
bpos2 = bpos1.clone
bpos2.x += 9
bpos2.y += 9
bpos2.z += 9
mc.say bpos1
mc.say bpos2
mc.set_blocks(bpos1, bpos2, Block::GOLD_BLOCK)

# x 方向に 10 個TNT を作成
bpos3 = ppos.clone
bpos3.x += 2
bpos4 = bpos3.clone
bpos4.x += 9
mc.say bpos3
mc.say bpos4
mc.set_blocks(bpos3, bpos4, Block::TNT)

# カメラモード切替 (なぜか動作しない)
mc.set_camera_mode(:fixed)

# 真下のブロックの ID を取得 (なぜか常に Fail になる)
mc.say mc.get_block(ppos.x, ppos.y - 1, ppos.z)

# 現在の位置から高さ 30 のところにプレイヤーを移動 (落ちないようにブロックを作成)
mc.set_block(ppos.x, ppos.y + 29, ppos.z, Block::STONE)
mc.set_player_position(ppos.x, ppos.y + 30, ppos.z)

記載のバージョン PC 版ではうまく動作しないメソッドもありました
ブロックの設置とプレイヤーの移動ができれば何とかなると思います
使えるブロックの一覧はこちらでコードと石の対応はこちらこちらが参考になると思います

これを使って家でも自動で構築できるスクリプトでも書いてみようと思います

2017年12月11日月曜日

Minecraft PC 版のキャラスキンを変更してみた

概要

Minecraft の PC 版はキャラのスキンを自分で作成することができます
今回は NovaSkin というサービスを使って作成したスキンを設定するところまでやってみました

環境

  • macOS X 10.13.2
  • Minecraft 1.12.2

NovaSkin で独自のスキンを作成する

NovaSkin というサイトで一から独自のスキンを作成することができます
操作方法は参考サイトに記載のページがわかりやすいです

今回は Gallery からすでに作成済みのスキンを取得して設定してみます
適当に検索して好きなスキンを見つけて選択しましょう
novaskin1.png
とりあえず今回はピカチュウのスキンを選択しました

好きなスキン選択もしくは作成できたら右上の「Apply」を選択しましょう
すると以下のような画面になるので「Click here to open minecraft.net ant apply your skin」を選択しましょう
novaskin2.png

スキンを設定する

すると Minecraft の公式ページに飛ぶので自分の Minecraft アカウントでログインしましょう
するとスキンを変更する画面に飛んでくれるのでここで「Change」を選択します
novaskin3.png

すると以下のような感じでスキンの変更が完了します
novaskin4.png

ちなみに png データを直接ダウンロードして Minecraft launcher から png ファイルを設定することも可能です
novaskin6.png

動作確認

実際に Minecraft を起動してスキンが変更されているか確認してみましょう
マシンがネットに接続されている状態であれば問題なくスキンがカスタマイズできていると思います
novaskin5.png

最後に

Minecraft PC 版のスキンを変更する方法を紹介しました
今回は NovaSkin というサービスを使ってスキンを変更しました
元のデータは png 情報なので頑張って自分で png 情報を作成しても OK です
が、いろいろ面倒なのでそういったジェネレート系のサービスを活用することをおすすめします

参考サイト

2017年12月10日日曜日

Minecraft に Raspberry Jam Mod をインストールしてプログラミングしてみる

概要

前回 Minecraft 上に Forge という mod を管理するための mod をインストールしました
今回は更に Raspberry Jam Mod をインストールしてプログラムで Minecraft を操作してみたいと思います

環境

  • macOS X 10.13.2
  • Minecraft 1.12.2
  • Forge 1.12.2 - 14.23.1.2555
  • Raspberry Jam 0.93
  • Ruby 2.4.1p111
  • minecraft-pi-ruby 0.0.1

Raspberry Jam Mod のインストール

まずは Github 上にある zip ファイルをダウンロードしましょう
install_raspberry_jam1.png

mods.zip をダウンロードすれば OK です
ダウンロードできたら解凍しましょう
すると Minecraft のバージョンごとに Jar ファイルが展開できます
これを Forge の mods ディレクトリ配下にコピーします( zip ファイルを直接置いてもいいよみたいな紹介記事がありますが Jar に展開しないとダメでした)

  • cp ~/Downloads/1.12.2/RaspberryJamMod.jar ~/Library/Application\ Support/minecraft/mods/

これで OK です
Forge プロファイルで Minecraft を起動しましょう
Mods の一覧を確認すると Raspberry Jam Mod がちゃんとインストールされているのを確認できると思います
install_raspberry_jam2.png

新規でワールドを作成する

テスト用のワールドを作成しましょう
ワールドはクリエイティブモードで作成することをオススメします
が、サバイバルでもハードコアでも OK です

Ruby スクリプトを作成する

ではプログラミングしていきましょう

  • bundle init
  • vim Gemfile
gem "minecraft-pi-ruby"
  • bundle install --path vendor
  • vim test.rb
require 'minecraft-pi-ruby'

mc = Minecraft.new
mc.say 'Ruby Test!'
  • bundle exec ruby test.rb

ワールドは開いた状態にしておきましょう
F3 + P で非アクティブになったときにポーズしないようにするとデバッグしやすいと思います
実行して成功すると以下のようにゲーム側にメッセージが表示されます
install_raspberry_jam4.gif

ちなみに get_player_position というメソッドが使いたい場合は Gemfile に

gem "minecraft-pi-ruby", github: "eaglestone/minecraft-pi-ruby"

と書いてから bundle install してください

最後に

Raspberry Jam Mod を使ってマイクラの世界を Ruby から操作できるようにしてみました
mod とは違いカスタマイズできるものではありませんが人の行動やブロックの生成など自動化したりすることができます

詳しい API ドキュメントはここなど Web を探せばいろいろサンプルも出てきます

既存のワードでも動かすことができるので自分の自慢のワールドをこれでガンガン自動化していきましょう

2017年12月9日土曜日

Minecraft 1.12 で Forge をインストールする方法

概要

Minecraft で mod を使うための下準備編となります
Minecraft 自体の購入方法はインストールについては前回の記事を参考にしてください

環境

  • macOS X 10.13.2
  • Minecraft 1.12.2
  • Forge 1.12.2 - 14.23.1.2555
    • Optifine 1.12.2_HD_U_C7

インストーラをダウンロードする

公式からダウンロードしましょう
今回は Recommended からダウンロードします
Windows の場合はインストーラが用意されていますが Mac の場合は Minecraft 本体と同じで Jar ファイルをダウンロードします
「Installer」のボタンからダウンロードしましょう
install_mc_forge1.png

今回は forge-1.12.2-14.23.1.2555-installer.jar という名前の Jar ファイルがダウンロードできました

Forge のインストール

ダウンロードした Jar ファイルをダブルクリックすれば OK です
セキュリティの警告が出てダブルクリックで開けない場合は右クリックから開くで開きましょう

開くと以下のような画面になるので OK を選択します
今回はデフォルトの設定のまま進みます
install_mc_forge2.png

ダウンロードがいろいろと始まります
install_mc_forge3.png

Complete 画面になればインストール完了です
指定したパスに Forge がインストールされています

local:~ hawksnowlog$ ls -ltr ~/Library/Application\ Support/minecraft/
total 1592
-rw-r--r--   1 hawksnowlog  staff   71984 11 25 17:40 nativeUpdaterLog.txt
drwxr-xr-x   5 hawksnowlog  staff     160 11 25 17:48 assets
drwxr-xr-x   2 hawksnowlog  staff      64 11 25 17:53 resourcepacks
-rw-r--r--   1 hawksnowlog  staff     118 11 25 17:53 realms_persistence.json
drwxr-xr-x   3 hawksnowlog  staff      96 11 25 20:56 saves
-rw-r--r--   1 hawksnowlog  staff     111 12  7 22:50 usercache.json
-rw-r--r--   1 hawksnowlog  staff     714 12  8 09:53 nativelog.txt
drwxr-xr-x  37 hawksnowlog  staff    1184 12  8 09:54 logs
-rw-r--r--   1 hawksnowlog  staff    2044 12  8 09:55 options.txt
-rw-r--r--   1 hawksnowlog  staff  595886 12  8 09:55 launcher_log.txt
drwxr-xr-x   4 hawksnowlog  staff     128 12  8 10:03 versions
drwxr-xr-x  13 hawksnowlog  staff     416 12  8 10:03 libraries
-rw-r--r--   1 hawksnowlog  staff    1111 12  8 10:04 launcher_profiles.json
local:~ hawksnowlog$ ls -ltr ~/Library/Application\ Support/minecraft/versions/
total 0
drwxr-xr-x  4 hawksnowlog  staff  128 12  8 09:54 1.12.2
drwxr-xr-x  3 hawksnowlog  staff   96 12  8 10:04 1.12.2-forge1.12.2-14.23.1.2555

Forge のインストールを確認する

インストール後 Minecraft Launcher を起動しましょう
するとプレイの選択一覧に Forge が選択できるようになっています
変更して起動してみましょう
install_mc_forge4.png

Forge で起動すると以下のような画面になります
install_mc_forge5.png
「Mod」のボタンが増えているのがわかると思います

試しに mod を追加してみる

何がいいかなーと思ったのですが「Optifine」という mod をインストールすることにしました
あまりゲームには影響しない支援系の mod でマイクラ自体を軽量化するための mod です

まず Optifine の公式サイトにアクセスしましょう
そして自分のマイクラのバージョンにあった mod をダウンロードします
今回は「OptiFine 1.12.2 HD U C7」から「OptiFine_1.12.2_HD_U_C7.jar」をダウンロードしました
install_mc_forge6.png

Jar がダウンロードできたら Forge が mod を管理するの指定のディレクトリに Jar を配置しましょう

  • cp ~/Downloads/OptiFine_1.12.2_HD_U_C7.jar ~/Library/Application\ Support/minecraft/mods/

これだけで Forge 上に Optifine mod がインストールされます
再度 Minecraft を Forge プロファイルで開きましょう
そして、ビデオ設定に進むと以下のように Optifine が有効になった状態だと言うことがわかります
install_mc_forge9.png

が何故かここで疑問だったのですが、Forge プロファイルで起動した際のトップ画面にある Mod の一覧には Optifine が含まれていません
どういう条件でこの一覧に含まれるかは不明ですが Optifine は出てきませんでした
それでもビデオ設定行くと Optifine が適用された状態になっていました

おまけ Optifine 個別でインストールする方法

実は Forge がなくても Optifine をインストールすることができます
Forge をインストールしたときに新規でプロファイルが作成されましたがそれと同様に Optifine 用のプロファイルを作成することで Optifine mod のみが動作する環境も作れます

Jar をダブルクリックして開きましょう
すると Optifine のインストール画面が起動するのでそのままインストールを進めましょう
このとき先ほど Forge インストール時に指定した Minecraft のパスと合っているか確認してください
問題なければ「Install」を選択しましょう
install_mc_forge7.png

これで再度 Minecraft を起動してみましょう
このとき Forge のプロファイルではなく Optifine のプロファイルが追加されているのでそちらを選択します
install_mc_forge8.png

そして設定からビデオ設定を選択すると Optifine で拡張された設定項目が追加されていることが確認できると思います
install_mc_forge9.png

これで Optifine を個別プロファイルでインストールすることができました
Forge は不要で Optifine mod だけでプレイしたい場合にはこちらの方法を使ってみてください

最後に

Minecraft に Forge という mod をインストールしてみました
Forge 自体は mod をインストールしやすくする mod みたいなものなので、そこまでゲームに直接影響する mod ではないです
今後 mod を使ってプログラムするための下準備でもあるのでその方法を紹介しました

おまけで Optifine mod のインストール方法も紹介しました
指定のディレクトリに Jar を追加するだけで Forge 上に mod を追加できるので非常に簡単に mod を追加できます

次回は Raspberry Jam mod を Forge 上にインストールして Minecraft でプログラムできる環境を構築したいと思います

参考サイト