#fav2toshi_a Advent Calendar 最終日

さ、最終日なので何日目とかは関係ないのですよ?

ふぁぼとmikutter・としぁさんとの戦いについてはとしぁさんの記事を見ていただければいいかと思いますが、最近はとしぁさんのmikutterもいろんな意味で落ち着いてきましたよね。

もちろん安定している、という意味でもあるのですが、昔はよくとしぁさんから何回ふぁぼったとかのDM爆撃をされたものです。

その前はリプライだったりして

こんなふうにリプ爆撃をされたころもありました。

こんな感じだったらしいですね。でも

のようにたかだか10分だったわけでセミナーの間中、複数人からふぁぼられているいまとなっては・・・といった感じですね。

しかし、しかし、しかし このころはふぁぼる側とふぁぼられる側との温かな交流があったとも言えるのではないだろうか

なんというか、ふぁぼるリスク・ふぁぼるための試行錯誤・反撃…息をのむような瞬間・・・10分間でありました。

そのふぁぼの緊張感をとりもどしたくはないですか?

というわけで、こちらをごらんください。

はい Minecarftです。ちょっとmodをいれていますが

この人っぽい緑のなにか、拡大してみましょう。

はい、と○ぁですね(

このmobはそれぞれとしぁ氏のついーよと関連づけられていす。そのついーよの中身を定期的に「つぶやき」ます。

また、ライフ・スピード・防御、全てがふぁぼられ数(favstarから取得)に比例しています。 もしふぁぼられが0だったらって? いやいや、そんなオカルトありえません

そして、このと○ぁをたおすと・・・もうお分かりですね?

そう、ふぁぼられます。

と○ぁは金塊をドロップします。これから金のインゴットを作ってクラフトすると・・・・

こんなパーツができるので、6種類のパーツをあつめると、冒頭の「としぁスポーンブロック」ができます。このスポーンブロックは黒曜石と同じぐらい硬いのでこれで部屋を作ってスポーンさせてTNTを落としたりすると一気にふぁぼれていいんじゃないかなあと思います。

まあ、基本的にと○ぁはかなりスポーンするように作ってあるのでてきとーにしてるだけでも結構ふぁぼられるんですけどね。 よくふぁぼられてるやつはめっちゃ強いので気をつけてくださいね。しかもまとまってわくし。ふぁぼられてないとしぁはざこなんですけどねえ。



これから

  • スキンの改善
  • パーツ画像の改善
  • ふぁぼりをasyncにする
  • 50個ごとに「と○ぁを50体ふぁぼりたおしました」とかつぶやくようにしたい
  • と○ぁスポーンを使ったトラップタワーによるふぁぼ爆撃の実験

技術的なはなし

MIKUって知ってますか? よく知らないでけどLispっぽいなにものかですよね。

今回はそれを尊重して、 Clojureでmodを書きました・・・・・・と言いたかったんですが、いろいろあってmob動作部分は全てJavaになりました…orz

どういう原理かというと Fav2toshi_a.java

@Mod(modid="f2t", name="fav2toshi_a", version="0.0.0")
@NetworkMod(clientSideRequired=true, serverSideRequired=false)
public class Fav2toshi_a {
    @Init
    public void load(FMLInitializationEvent event) {
        String name = "f2t";
        this.ns = name + ".core";
        System.out.println("Enabling " + name + " clojure Plugin");
        invokeClojureFunc("load", this, ExtendableItem.class, ItemStack.class, ExtendableBlock.class,
                          Constants.items, Constants.blocks, Constants.materials);
    }

    private void invokeClojureFunc(String enableFunction, Object... args) {
        try {
            ClassLoader previous = Thread.currentThread().getContextClassLoader();
            Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader()); 

            clojure.lang.RT.loadResourceScript(ns.replaceAll("[.]", "/")+".clj");
            clojure.lang.RT.var(ns, enableFunction).invoke(args);

            Thread.currentThread().setContextClassLoader(previous);
        } catch (Exception e) {
            System.out.println("Something broke setting up Clojure");
            e.printStackTrace();
        }
    }
}

と、こういった感じで "clojure.lang.RT"を使って「実行時に」Clojureのファイルを読ませます。引数にしているのは、Clojure側で必要になるクラスとかです。

(defn load [args]
  (do
    (def Mod (nth args 0))
    (def Item (nth args 1))
    (def ItemStack (nth args 2))
    (def Block (nth args 3))
    (def items (assoc (mapit (nth args 4))
                 "toshiaHead" (new-item 900 0 "toshiaHead" "封印されしとしぁの頭")
                 "toshiaRightHand" (new-item 901 1 "toshiaRightHand" "封印されしとしぁの右手")
                 "toshiaBody" (new-item 902 2 "toshiaBody" "封印されしとしぁ")
                 "toshiaLeftHand" (new-item 903 3 "toshiaLeftHand" "封印されしとしぁの左手")
                 "toshiaRightLeg" (new-item 904 4 "toshiaRightLeg" "封印されしとしぁの右足")
                 "toshiaLeftLeg" (new-item 905 5 "toshiaLeftLeg" "封印されしとしぁの左足")))
    (def materials (mapit (nth args 6)))
    (def blocks (assoc (mapit (nth args 5))
                  "toshia" (toshia-spawn)))

    (create-recipes)
    (create-mob)
    (println "#fav2toshi_a loaded")))

Clojure側ではこうやって引数をうけとっています。 たとえば新しいアイテムを生成するnew-itemとかをのぞいてみると

(defn inst [clas & args]
  (Reflector/invokeConstructor clas (to-array args)))

(defn new-item [i icon name name2]
  (let [item (inst Item (intg i))]
    (doto item
      (.icon (intg icon))
      (.name name))
    (LanguageRegistry/addName item name2)
    item))

このように "Item"クラスのコンストラクタを Reflectorを使って呼び出して、各種設定をしてアイテム登録をしています。

"Item"クラスは生のマインクラフトのItemクラス、ではなく

public class ExtendableItem extends Item {

    public ExtendableItem(Integer par1) {
        super(par1);
    }

    public void icon(int i) {
        this.setIconIndex(i);
    }
    
    public void name(String n) {
        this.setItemName(n);
    }

    @Override
    public String getTextureFile() {
        return CommonProxy.ITEMS_PNG;
    }
}

このような薄いラッパクラスをかませています。

さて、なんで Reflectorを使ったり、ラッパクラスを使っているかというと、マイクラの元からあるクラスだと難読化によってクラス名が変わってしまうからなんですね。あーめんど。

このへんをおさえてしまえば、Clojureでマイクラmodを書くことはそんなにはむずかしくもなくなると思います。(Bukkit使う時とはくらべものにならないけど)


さてはて、そんなこんなでマイクラしながらとしぁさんのおもしろいついーよを読んで、ふぁぼれるようになりましたね。
それでは2013年も #fav2toshi_a をよろしくお願いいたします。