Spica*

プログラミングの話。

IntelliJ IDEA + Forge 1.8 で modding 環境整えた

以前、 IntelliJ IDEA + Forge 1.7 で modding 環境整えた - Spica* という記事を書いたんですが、最近(?)ちょっとやり方が変わっていたようでした。 Basic Modding - Minecraft Forge の方ではなく、新設されていた公式ドキュメント Home - Forge Documentation を読みながら、再度環境を整えていきます。

環境

手順

この手順は、Forge DocumentationのGetting Startedのものです。

  • まず、Minecraft Forgeから、"Mdk"をダウンロード
    • 表示されるadfoc.usの広告は、絶対にクリックしないでね…
    • "forge-1.8-11.14.4.1563-mdk.zip"みたいなファイルがダウンロードできる
  • ダウンロードしたら、ダブルクリックで解凍
  • ターミナルを開き、下記を実行する。
# 解凍したディレクトリに移動
cd /path/to/forge-1.8-11.14.4.1563-mdk

# 環境を準備する(Minecraft, forgeのデコンパイルとビルド)
./gradlew setupDecompWorkspace

# intelliJ IDEA向けの環境ファイルを準備する
./gradlew genIntellijRuns

※もし、Mac OS X El Capitan以降をお使いで、 ./gradlew setupDecompWorkspace の実行に失敗する場合、 FIX MinecraftForge gradlesetupDecompWorkspace failed · Issue #2183 · MinecraftForge/MinecraftForge の問題が起きているかもしれません。こちらのコメントを参考に、 build.gradle のコメントを書き換えるとビルド通ると思います。

  • 続けてIntelliJ IDEAを開き、最初の画面で"import project"を選択して、先ほどのディレクトリの中にある"build.gradle"ファイルを選択する。その後JDKを選択したりする画面が表示されるが、そのまま次へいく。
  • しばらくすると、開発する画面が表示される。

f:id:esperia:20160107000027p:plain

こんな感じ。ここまでで開発の準備はOKです。

デバッグ実行を行う

  • IntelliJ IDEA上の、[Edit Configuration] を開く

f:id:esperia:20160107000855p:plain

  • 左上の+ボタンを押下し、Gradleを選択する

f:id:esperia:20160107003009p:plain

  • それぞれ値を入力して、OKを押す
    • Gradle projectの欄は、右側のディレクトリボタンを押すと自動的に入力可能
    • Tasksの欄は、 runClient にする

f:id:esperia:20160107003332p:plain

  • 緑色の右向き▲を押して、実行する

f:id:esperia:20160107003547p:plain

お疲れ様です!ここまでで実行OKです。

ここからどうやってMOD開発してくの?

僕もまだ模索中です。。

今のところ、Modding カテゴリーの記事一覧 - Minecraftとタートルと僕 がなかなか良さそうです。 1.7.10の記事で環境構築方法は違いますが、APIがそこまで大きく変わることはないと思うので。。

インターネットで検索して出る情報も、古い物が多いですがわりかし使えるのではないかと思ってます。

良さそうな記事あれば教えて下さい!!

Minecraftでカスタムアイテム作ってみる

ForgeのMod制作の続きをしてみる。以前のセットアップの記事はこっち

とりあえずアイテムを作る。

とりあえずアイテムを作るのは非常に簡単で、Mod初期化時に GameRegistry#registerItem() メソッドを使ってアイテムを登録すれば良いだけのようです。

ここでいうMod初期化時というのは、 preInit(FMLPreInitializationEvent event) が呼ばれるタイミングです。ハンドラの書き方とかはざっくりとセットアップの記事にも書いてます。

つまるところ、下記のように net.minecraft.item.Item を継承したクラスを新しく作っておき…

package com.example.examplemod;

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

public class GenericItem extends Item {

    public GenericItem() {
        // 色んな設定をする
        setMaxStackSize(64);
        setCreativeTab(CreativeTabs.tabMisc);
        setUnlocalizedName("genericItem");
    }

}

下記のように、Mod初期化時のハンドラで登録してあげると、もうそれだけでアイテムが一応出来上がる。

package com.example.examplemod;

import cpw.mods.fml.common.Mod;
import cpw.mods.fml.common.Mod.EventHandler;
import cpw.mods.fml.common.SidedProxy;
import cpw.mods.fml.common.event.FMLInitializationEvent;
import cpw.mods.fml.common.event.FMLPostInitializationEvent;
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
import cpw.mods.fml.common.registry.GameRegistry;
import net.minecraft.init.Blocks;

@Mod(modid = ExampleMod.MODID, name = ExampleMod.MODNAME, version = ExampleMod.VERSION)
public class ExampleMod {

    /** MODのID。小文字であること */
    public static final String MODID = "examplemod";
    /** MODの名前 */
    public static final String MODNAME = "Example Mod";
    /** MODのバージョン */
    public static final String VERSION = "1.0";

    @Mod.Instance(value = ExampleMod.MODID) //Tell Forge what instance to use.
    public static ExampleMod instance;
    private static GenericItem myItem;

    @EventHandler
    public void preInit(FMLPreInitializationEvent event) {
        myItem = new GenericItem();

        GameRegistry.registerItem(myItem, "myItem");
    }

}

確認してみる

  • シングルプレイでワールドを生成する
    • チートモードをONにしておく
  • そのワールドでプレイ開始
  • /give @p <MODID>:<ITEMID> というコマンドを発行する
    • <MODID> は、コード内の MODID 変数に格納した名前。
    • <ITEMID> は、 #registerItem() の第二引数に指定した名前。
    • 例: /give @p examplemod:myItem

上記でアイテムが入手できる。下記のような感じ

f:id:esperia:20151230215952p:plain

ローカライズ(日本語化)する

アイテムの名前がなんか変な名前(item.genericItem.name)になっているのが分かります。 これを日本語名にするには、アイテム名を記述したファイルを作成します。

ファイルは、プロジェクト内のsrc/main/resources/assets/genericmod/langディレクトリの下に、 ja_JP.lang という名前で作ります。僕の環境では、 src/main/resources まではディレクトリが存在したので、そこから先のフォルダとファイルは自分で作りました。

他の言語にも対応させるには、同様のディレクトリに別の言語向けファイルを作ります。例えば、英語だと en_US.lang です。

IntelliJ IDEAでは下記のような表示になります。

f:id:esperia:20151231010136p:plain

で、そのファイルには下記のような記述をします。

英語(en_US.lang):

item.genericItem.name=Delicious Cookie

日本語(ja_JP.lang):

item.genericItem.name=おいしいクッキー

その状態で実行すると、下記のような表示になります。

英語:

f:id:esperia:20151231011259p:plain

日本語:

f:id:esperia:20151231011247p:plain

おおおお。ほとんどコード書いてないですが、実際の画面にアイテムとして出てくれるとかなり嬉しいですね!

参考

PythonでCバインディング試してみた

以前MIDIハッカソンで、「PythonC/C++とお話できます!」的な話を聞いていて、ずっと気になっていたのでちょっと試すだけ試してみた。PythonからCプログラムを呼び出す | 象歩を参考に、そのまま動かすところまでやってみた。CもPythonも未経験だけど、可能性広げる意味で。。

コンパイルのところでちょっと詰まったのでメモっておく。

環境

  • Mac OS X El Capitan
  • HomebrewでインストールしたPython(v2.7.10)

ソースを用意する

先ほどの記事を参考に、 hello.chelloWrapper.c を用意する。「1.ソースコード」の節と「2.wraper コード」の節のソースコードをそれぞれそのままコピペでOK。

コンパイル

コンパイルに使用するコマンドは、参考記事では下記のようになってる。

gcc -fpic -o hello.o -c hello.c
gcc -fpic -I/usr/include/python -o helloWrapper.o -c helloWrapper.c
gcc -shared hello.o helloWrapper.o -o hellomodule.so

しかし、homebrewでインストールしたpythonでは /usr/include/python にヘッダファイルがあるわけではないので、そのままでは動かない。

$ gcc -fpic -I/usr/include/python -o helloWrapper.o -c helloWrapper.c
helloWrapper.c:2:10: fatal error: 'Python.h' file not found
#include "Python.h"
         ^
1 error generated.

$ ls /usr/include/python
ls: /usr/include/python: No such file or directory

この辺を解決しなきゃ。。

hello.cコンパイル

とりあえず一行目は動くので、動かして hello.o を作る。warning出るけど…

$ gcc -fpic -o hello.o -c hello.c
hello.c:9:2: warning: implicitly declaring library function 'printf' with type 'int (const char *, ...)'
        printf("こんにちは、私は %s  %s です。\n", adrs, name);
        ^
hello.c:9:2: note: include the header <stdio.h> or explicitly provide a declaration for 'printf'
1 warning generated.

$ ls
hello.c         hello.o         helloWrapper.c

helloWrapper.cコンパイル

続けて、 helloWrapper.cコンパイルPython.hをインクルードしているので、これがあるパスを見つけて、 -I の後に記述しなくちゃいけない。

で、ググってたら、python-config --prefixというコマンドがある のを見つけたので実行してみると、ビンゴっぽかった。

$ python-config --prefix
/usr/local/Cellar/python/2.7.10_2/Frameworks/Python.framework/Versions/2.7

$ ls `python-config --prefix`
Headers@   Python*    Resources/ bin/       include/   lib/

Headers内に Python.h があったので helloWrapper.cコンパイルは下記のコマンドでいけた。

$ gcc -fpic -I`python-config --prefix`/Headers -o helloWrapper.o -c helloWrapper.c
helloWrapper.c:31:10: warning: incompatible pointer types initializing 'PyCFunction' (aka 'PyObject *(*)(PyObject *, PyObject *)') with an expression of type
      'PyObject *(PyObject *, PyObject *, PyObject *)' [-Wincompatible-pointer-types]
        {"out", hello_out, METH_VARARGS | METH_KEYWORDS},
                ^~~~~~~~~
1 warning generated.

$ ls
hello.c         hello.o         helloWrapper.c  helloWrapper.o

hellomodule.soの作成

最後、 hellomodule.so 共有モジュールの作成。これもさっきのパスにヒントがあって、 -L オプションには、libディレクトリを指定すれば良いようだった。

-l のオプションですごく迷ったのだけど、 compilation - C can't compile - symbol(s) not found for architecture x86_64 - Stack Overflow とか見ると、静的ライブラリlibimplementations.aの場合は-limplementationsという指定にしていた。

libディレクトリには、libpython2.7.dylibというファイル名があったので、-lpython2.7かなと思って下記のコマンドを発行。

$ gcc -L`python-config --prefix`/lib -lpython2.7 -shared hello.o helloWrapper.o -o hellomodule.so
$ ls
hello.c         hello.o         helloWrapper.c  helloWrapper.o  hellomodule.so*

いけた。ここまでで材料が揃った。

実行する

$ python
Python 2.7.10 (default, Jul 13 2015, 12:05:58)
[GCC 4.2.1 Compatible Apple LLVM 6.1.0 (clang-602.0.53)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import hello
>>> hello.add(2, 3)
5
>>> hello.out("大原", "麗子")
こんにちは、私は 大原 の 麗子 です。
>>> quit()

おおー!

今度はnode.jsのネイティブバインディングやってみたいですね!

ComputerCraftEduで遊んだ

近年Minecraftは好奇心をくすぐる意味で教育に良いと言われており、Microsoft「Minecraft in education」を出すなど、そっちの方面で結構盛り上がっています。

ComputerCraftEduは、ComputerCraftの教育向けにカスタマイズされたMODで、ブロックを使ったプログラミングが可能です。Minecraft in educationの一部として同梱されており、半ば公式認定されてる感あります。

f:id:esperia:20151128224813p:plain

導入

Minecraftと、Forgeのインストール

  • Minecraft公式クライアントをインストール
  • ランチャー起動→ゲーム開始→終了
  • Forge 1.7.10をインストール
  • ランチャーを起動
  • [Edit Profile]を押下し、下記のような感じでプロファイルを設定

f:id:esperia:20151128225133p:plain

  • ランチャー起動→ゲーム開始→終了
    • ゲーム開始すると、先ほどのプロファイル内の[Game Directory]に指定したパス内に、[mods]ディレクトリができます。

http://services.minecraftedu.com/wiki/ComputerCraftEdu#Using_ComputerCraftEdu

ComputerCraftEduのインストール

  • 公式サイトのGetting Startedの[I'M A PLAYER]の中に、[Download Mod for 1.7.10]があるので、それを押下する
    • ComputerCraftPlusComputerCraftEdu1.74.jar がダウンロードできる。
  • ダウンロードした、上記jarファイルを、[mods]ディレクトリに入れる。

公式チュートリアルマップを導入する

  • 公式サイトのGetting Startedの[I'M A PLAYER]の中に、[Tutorial Map for Regular Minecraft]があるので、それを押下する
    • Turtle Canyon for ComputerCraftEdu and Forge 1.7.10.2.zip がダウンロードできる。
  • zipを解凍しておく。中から Turtle Canyon for ComputerCraftEdu and Forge 1.7.10.2 というディレクトリが出てくる
  • [Game Directory]のパス内([mods]ディレクトリと同じ階層)に、[saves]ディレクトリがあるので、この中に入れる

使ってみる

導入できたら、早速ランチャーより、ゲームを起動しましょう。[シングルプレイ]メニューの中に、[Turtle Canyon 1.7.10.2]があるのでそれをクリックします。

f:id:esperia:20151129022955p:plain

こんなマップです。

f:id:esperia:20151129023837p:plain

このマップは、ちょっとした物語の設定があり、主人公は「伝説のTurtle Canyon」を探し求めて幾多の時間を旅してきたことになっています。砂漠、かつ渓谷なのはこの辺の設定を反映したものっぽい。

さらに、この渓谷は不思議な力で護られており、物語的にブロックが自由に壊せない設定となっています(=アドベンチャーモード)。

ここまでで、いろいろ遊べる感じですね!

自分で作るには

ComputerCraftEduでは、 Beginner's TurtleTurtle Remote Control が必要です。チュートリアルマップでは既に用意されていましたが、自分で作るには、材料を揃えて作業台で作らなければなりません。

メモ的に、作り方を書いておきます。

Beginner's Turtle

f:id:esperia:20151128231730p:plain

Remote control

f:id:esperia:20151128231737p:plain

Beginner's Mining Turtle

さらに、ブロックを破壊できるTurtleを作るには、 Beginner's Turtle にダイアモンドのツルハシを組み合わせる必要があります。

  • Beginner's Turtle 1つ
  • ダイアモンドのツルハシ(diamond_pickaxe) 1つ

f:id:esperia:20151129024358p:plain

参考リンク

IntelliJ IDEA + Forge 1.7 で modding 環境整えた

追記:こちらは1.7.10以前向けの記事です。1.8以降はIntelliJ IDEA + Forge 1.8 で modding 環境整えた - Spica*をご参考ください。

とりあえずMod作り始めるところまで書いとく。

環境

手順

# 移動
cd /path/to/forge-1.7.10-10.13.4.1558-1.7.10-src

# 下記の2つのコマンドを順番に実行
./gradlew setupDecompWorkspace
./gradlew setupDevWorkspace ideaModule
  • IntelliJ IDEAを開き、最初の画面で"import project"を選択して、先ほどのディレクトリの中にある"build.gradle"ファイルを選択する。その後JDKを選択したりする画面が表示されるが、そのまま次へいく。
  • しばらくすると、開発する画面が表示される。

MODの実行

MODの知識ない状態で、どうやって手を付ければいいのかが難しいですね…。みんなどこ見てるの。 このへんが公式だと思うだけど、Outdatedって。。

とりあえず、最初からあるクラスのコードに+αして、動いてることを確認してみる。

package com.example.examplemod;

import cpw.mods.fml.common.Mod;
import cpw.mods.fml.common.Mod.EventHandler;
import cpw.mods.fml.common.event.FMLInitializationEvent;
import net.minecraft.init.Blocks;

@Mod(modid = ExampleMod.MODID, name = ExampleMod.MODNAME, version = ExampleMod.VERSION)
public class ExampleMod {
    /** MODのID。小文字であること */
    public static final String MODID = "examplemod";
    /** MODの名前 */
    public static final String MODNAME = "Example Mod";
    /** MODのバージョン */
    public static final String VERSION = "1.0";

    @Mod.Instance(value = ExampleMod.MODID) //Tell Forge what instance to use.
    public static ExampleMod instance;

    @EventHandler
    public void init(FMLInitializationEvent event) {
        // some example code
        System.out.println("Hello!! DIRT BLOCK >> " + Blocks.dirt.getUnlocalizedName());
    }
}

そして、ターミナルから下記を実行。

cd /path/to/forge-1.7.10-10.13.4.1558-1.7.10-src

# 実行
./gradlew runClient

Minecraftが起動する。と同時に、ターミナルに沢山のログが流れる。 その中に、先ほどのメッセージが表示されていることを確認する。

f:id:esperia:20151126010331p:plain

…ちゃんと出てる!ということはとりあえず実行完了ということですね。 早くブロック置きたい。

※つづき書きました:Minecraftでカスタムアイテム作ってみる - Spica*

mecabをnodeで使う (Mac OS X)

# MeCabインストール
$ brew search mecab
homebrew/php/php53-mecab      homebrew/php/php56-mecab      mecab-jumandic                mecab-unidic
homebrew/php/php54-mecab      mecab                         mecab-ko
homebrew/php/php55-mecab      mecab-ipadic                  mecab-ko-dic

$ brew install mecab mecab-ipadic

# モジュール作って、インストール
$ mkdir my-mecab-test
$ cd my-mecab-test
$ npm init
$ npm install mecab-async --save

# テストファイル作る
$ vim test.js

今回使用したモジュールは、 node-mecab-async です。このドキュメントに沿って、下記のように "test.js" を記述しました。

var MeCab = new require('mecab-async')
  , mecab = new MeCab();

mecab.parse('すもももももももものうち', function(err, result) {
  if (err) throw err;
  console.log(result);
});

そして実行。

$ node test.js
[ [ 'すもも', '名詞', '一般', '*', '*', '*', '*', 'すもも', 'スモモ', 'スモモ' ],
  [ 'も', '助詞', '係助詞', '*', '*', '*', '*', 'も', 'モ', 'モ' ],
  [ 'もも', '名詞', '一般', '*', '*', '*', '*', 'もも', 'モモ', 'モモ' ],
  [ 'も', '助詞', '係助詞', '*', '*', '*', '*', 'も', 'モ', 'モ' ],
  [ 'もも', '名詞', '一般', '*', '*', '*', '*', 'もも', 'モモ', 'モモ' ],
  [ 'の', '助詞', '連体化', '*', '*', '*', '*', 'の', 'ノ', 'ノ' ],
  [ 'うち', '名詞', '非自立', '副詞可能', '*', '*', '*', 'うち', 'ウチ', 'ウチ' ] ]

mecabほんとすごい…

phpMyAdminを最速で動かす(PHP5.4以降限定)

# ダウンロード(お好きなバージョン)
curl -O -L https://files.phpmyadmin.net/phpMyAdmin/4.4.14.1/phpMyAdmin-4.4.14.1-all-languages.zip

# 解凍
unzip phpMyAdmin-4.4.14.1-all-languages.zip
cd phpMyAdmin-4.4.14.1-all-languages

# phpMyAdmin起動
php -S localhost:8888

# http://localhost:8888/ にアクセス

いちいちApacheの設定するのとか権限周りめんどいなぁとか思ってたけどPHP: ビルトインウェブサーバー - Manual忘れてたわ…音速で起動した。