2014/06/26

MineFactoryReloaded on 1.7.2

English version here (2014/07/19).

とりあえず動いたのでやりかたをメモ。

D:\dev> set PATH=%PATH%;D:\tools\apache-ant-1.9.4\bin ←antのパス。ビルドに必要。
D:\dev> set PATH=%PATH%;D:\tools\gradle-1.12\bin ←gradleのパス。付属の gradlew.bat を使うならいらない。
D:\dev> set PATH=%PATH%;D:\tools\PortableGit-1.9.4-preview20140611\cmd ←gitのパス。ソース取得用。
D:\dev> set JAVA_HOME=C:\Program Files\Java\jdk1.7.0_60
D:\dev> git clone https://github.com/CoFH/CoFHLib.git
D:\dev> git clone https://github.com/CoFH/CoFHCore.git
D:\dev> git clone https://github.com/skyboy/MineFactoryReloaded.git
D:\dev> cd CoFHLib
D:\dev\CoFHLib> gradle build
D:\dev\CoFHLib> cd ..\CoFHCore
D:\dev\CoFHCore> ant ←gradleのダウンロードにすごく時間がかかることがあるので、build.xmlの237行目にある"./gradlew"を"gradle"に変更してから実行
D:\dev\CoFHCore> cd ..\MineFactoryReloaded
D:\dev\MineFactoryReloaded> ant

あとは、CoFHLib\build\libs\CoFHLib-1.7.2R1.0-CUSTOM_BUILD.jar、CoFHCore\build\dist\CoFHCore-[1.7.2]3.0.0B1-CUSTOM_BUILD.jar と MineFactoryReloaded\build\dist\MineFactoryReloaded-[1.7.2]2.8.0B2-CUSTOM_BUILD.jar を mods フォルダに突っ込めば導入完了。

ss

↑ゴムの木

CoFHLib/Core が 1.7.2 対応してきたってことは、ThermalExpansion もそろそろ対応してくるのだろうか。楽しみでござります。

※当然だけど、これらは開発中のものであり、mod 開発者やいち早く触ってみたい物好きな人用のものなので、安定性を重視する人にはオススメできません。普通の人は開発者からの配布を待った方がよさそうです。

2014/06/07

BinaryWriter.Write(string) と StreamWriter.Write(string)

いろいろ違うらしい。以下のようなテストコード作成していろいろ確認してみた。

using System;
using System.Linq;
using System.Text;

namespace ConsoleApplication3
{
    class Program
    {
        static void Main(string[] args)
        {
            var str = "Hello World!";

            Console.WriteLine("Input = {0}", str);

            Console.WriteLine("");
            Console.WriteLine("GetBytes (UTF8 with BOM)");
            DisplayBytes(GetBytes(str, true));

            Console.WriteLine("");
            Console.WriteLine("GetBytes (UTF8 without BOM)");
            DisplayBytes(GetBytes(str, false));

            Console.WriteLine("");
            Console.WriteLine("BinaryWriter (UTF8 with BOM)");
            DisplayBytes(BinaryWriter(str, true));

            Console.WriteLine("");
            Console.WriteLine("BinaryWriter(UTF8 without BOM)");
            DisplayBytes(BinaryWriter(str, false));

            Console.WriteLine("");
            Console.WriteLine("StreamWriter (UTF8 with BOM)");
            DisplayBytes(StreamWriter(str, true));

            Console.WriteLine("");
            Console.WriteLine("StreamWriter (UTF8 without BOM)");
            DisplayBytes(StreamWriter(str, false));

            Console.WriteLine("");
            Console.WriteLine("StreamWriter2 (UTF8 with BOM)");
            DisplayBytes(StreamWriter2(str, true));

            var longString = new String('A', 0x100);

            Console.WriteLine("");
            Console.WriteLine("BinaryWriter (long string, length: 0x{0:X})", longString.Length);
            var bwlong = BinaryWriter(longString, true);
            DisplayBytes(bwlong);
            int size;
            Console.WriteLine(
                "DecodeLEB128: Value = 0x{0:X}, Size = {1}",
                DecodeLEB128(bwlong, out size),
                size);

            Console.ReadKey();
        }

        static byte[] GetBytes(string str, bool withBOM)
        {
            return new UTF8Encoding(withBOM).GetBytes(str);
        }

        static byte[] BinaryWriter(string str, bool withBOM)
        {
            using (var ms = new System.IO.MemoryStream())
            {
                var writer = new System.IO.BinaryWriter(ms, new UTF8Encoding(withBOM));
                writer.Write(str);
                writer.Flush();

                return ms.ToArray();
            }
        }

        static byte[] StreamWriter(string str, bool withBOM)
        {
            using (var ms = new System.IO.MemoryStream())
            {
                var writer = new System.IO.StreamWriter(ms, new UTF8Encoding(withBOM));
                writer.Write(str);
                writer.Flush();

                return ms.ToArray();
            }
        }

        static byte[] StreamWriter2(string str, bool withBOM)
        {
            using (var ms = new System.IO.MemoryStream())
            {
                ms.Seek(1, System.IO.SeekOrigin.Begin);

                var writer = new System.IO.StreamWriter(ms, new UTF8Encoding(withBOM));
                writer.Write(str);
                writer.Flush();

                return ms.ToArray();
            }
        }

        static void DisplayBytes(byte[] bytes)
        {
            Console.WriteLine(string.Join(" ", bytes.Select<byte, string>(x => x.ToString("X2"))));
        }

        static int DecodeLEB128(byte[] bytes, out int size)
        {
            int result = 0;
            int shift = 0;
            size = 0;

            while (true)
            {
                var b = bytes[size];
                size++;
                result |= (b & 0x7F) << shift;
                if ((b & 0x80) == 0)
                {
                    break;
                }
                shift += 7;
            }

            return result;
        }
    }
}

結果

Input = Hello World!

GetBytes (UTF8 with BOM)
48 65 6C 6C 6F 20 57 6F 72 6C 64 21

GetBytes (UTF8 without BOM)
48 65 6C 6C 6F 20 57 6F 72 6C 64 21

BinaryWriter (UTF8 with BOM)
0C 48 65 6C 6C 6F 20 57 6F 72 6C 64 21

BinaryWriter(UTF8 without BOM)
0C 48 65 6C 6C 6F 20 57 6F 72 6C 64 21

StreamWriter (UTF8 with BOM)
EF BB BF 48 65 6C 6C 6F 20 57 6F 72 6C 64 21

StreamWriter (UTF8 without BOM)
48 65 6C 6C 6F 20 57 6F 72 6C 64 21

StreamWriter2 (UTF8 with BOM)
00 48 65 6C 6C 6F 20 57 6F 72 6C 64 21

BinaryWriter (long string, length: 0x100)
80 02 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 4
1 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 4
1 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 4
1 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
DecodeLEB128: Value = 0x100, Size = 2

わかったこと

  • Encoding.GetBytes、BinaryWriter.Write(string)、StreamWriter.Write(string) のすべてで null 終端文字は書き込まれない。
  • BinaryWriter.Write(string) は、文字列データの先頭に文字長プリフィックスなるものがつくらしい。
    • 文字長プリフィックスは LEB128 というフォーマットで文字長を記録しているらしい。
  • StreamWriter,Write(string) は UTF8Encoding の BOM が有効な場合で、かつストリーム位置が先頭のときに限り BOM を書き込む。

気をつけないと予期しない結果になりそうでありました。

2014/06/03

OBS Studio

しばらく見てないうちに OBS の次期バージョンである OBS Studio の開発が進んでたのでビルドしてみた。

動かしてみた図が

image

こんなかんじ。

パッと見てわかるのが、ステレオミキサー機能が追加されてて、音声の管理が楽になったところ。音声ソースとしてプラグインや音声キャプチャが使用でき、それぞれ調整可能なので、いろいろ応用ができそう。

Ustream で配信を試してみたところ

image

ちゃんと配信機能も実装されてる模様。

まだちょっと時間がかかりそうだけど、開発は着実に進んでるっぽいので期待しております。

2014/06/01

4層メモ(学者編)

フェイズ1

セレネを使用。最初にバトボレクイエムが入るので、魔法速度からはじめたほうがいいきがする。

ビークとその爆発で盾を殺さないように気を付ける。危険なポイントは、

  • 初回のメテオストリーム後のビーク
  • 2 回目のメテオストリーム後の毒の爆発
  • 3 回目のメテオストリーム後の毒の爆発

の 3 箇所。ここは鼓舞バリアをしっかりと入れないと盾が死ぬ。

あとは本で殴りつつ全力で攻撃に参加する。学者ががんばれば通常構成でダスト 4 つも割と可能。

 

フェイズ2

回復は白に任せて攻撃に専念。6 連続メテオの 20 秒くらい前(セレネの2回目のバフを発動させた直後あたり)に迅速を使わずにエオスに切り替え、メテオ直前に囁き。メテオ中に迅速で範囲回復。

メガフレア 10 秒前あたりで範囲回復してバリアを張り、そのあとに陣とエオスの魔法防御を張る。

 

フェイズ3

わいヴぁーんのデッドリーに要注意。2 回目の天地後に回復が薄くなりがちなので注意する。

あとは適切にギミックを処理できれば問題なしだとおもう。

天地の集合場所については詩人編と同様。学者の場合は本でネール殴ってるのもいいかも。

 

フェイズ4

未知の領域。5 連クロウで盾を殺さないように注意すること。

4層メモ(詩人編)

フェイズ1

開幕レクイエム+バトルボイス。召喚がいる場合はバトルボイスを召喚がタゲ取る直前に。

開幕のバフ回しで乱れ撃ちを後の方に回してしまうと、2 回目のメテオストリーム時に乱れが撃てない無駄な時間ができるので早めに使うといいかも。でも結局ゴーレムフェイズで調整を入れるから気にする必要はないかもしれない。

2 回目のダラガブダイブのあと辺りに回復するバフは使わずにとっておく。

 

フェイズ2

召喚がいる場合はネールが飛んだ直後にバラード。メテオ 3 個が落ちたらレクイエム。

青のタゲは静者を使ってリューサンあたりに取ってもらって、詩人は 3 体のゴーレムに DoT をばらまいた方が効率が良い。モードチェンジ後、青に静寂スタンバイ。MP500 くらいになったら歌終了。最後のゴーレム倒す直前にバラード開始。

6 連メテオはマラソン方式で、マラソン終了したらバラード終了。TP がきつい場合はパイオンも考慮に入れるけど、基本平気なはず。

捨身と発勁をここで使用。歌はなし。猛者・乱れ・ホークアイは使わない。

 

フェイズ3

召喚がいる場合はネールが落ちてくる直前にレクイエムを歌う。黒の場合は天地の後で良い気がする。

1 匹目のわいヴぁーんに全力を出す感じ。

詩人を含む遠隔職の場合は天地前に集合地点に集まる必要はなく、集合地点から 60~80 度くらい右 or 左回り側に陣取っておけばノヴァも安心。ただし、拘束解除が必要な場合は間に合わなくなる可能性があるので、その辺は柔軟に。

あとは単純に火力を出すだけ。ワイバーンポップ直前に DoT を入れなおすといいかもしれないくらい。

 

フェイズ4

未知の領域。とりあえず、死ななければ火力を詰める必要はあまりないらしい。