約 3,863,981 件
https://w.atwiki.jp/nwxss/pages/212.html
クロスオーバーSS(クロスSS)におけるテクニック、用語、参考URLへのリンクなどのまとめ。 適宜追加していってください。 用語 創作/二次創作で用いられる用語 レシオ、レシオ調整 レシオ(rario)とは、比率や割合を表す英語。格闘ゲーム「CAPCOM VS SNK」で採用されたレシオシステムが有名。クロスSSにおいては、NWとクロス先作品の両方を大切に、片方の登場人物が一方的に活躍するSSは避けようという概念。 再構成、本編再構成 公式のストーリーをなぞるタイプのSS。NWのクロスオーバーSSであれば、「○○という作品の主人公が柊だったら」など。 投稿時のテクニックに関するもの 連投規制 連続投稿規制。同一IPアドレスから連続で投稿すると荒らしと間違われて規制されてしまうことがある。他のIPアドレスからの投稿を挟めば問題ないらしい。これを回避するには他の住人からの支援レスが有効。 投下予告 さるさん 支援、支援レス
https://w.atwiki.jp/mfiler2tutorial/
Minnu s Filer2とはなんですか? UNIX(Linux, FreeBSD, MacOSX)で動くファイラーです。 UNIXというのは普通のパソコンに入っているWindowsとは違う種類のパソコン(OS)です。 Windowsは事務処理やネットサーフィンをするのに向いていますが UNIXは大学のワークステーションやウェブサーバー、組み込み機器などに利用され プロフェッショナルな用途に向いています。 Minnu s Filer2はそのUNIX上でコンピューティング全般の操作を簡単にするために開発されました。 ファイラーというのはファイルのコピーや作成、プログラムの起動など基本的なコンピュータ操作全般を行います。同じことを行うのにUNIXではシェルというプログラムを使いますが ファイラーはそれをよりビュジュアル的に行います。 同じくそれをビュジュアル的に行うソフトにファイルマネージャーというものがありますが、こちらはキーボードよりマウスでの操作が主体です。 それにたいしてファイラーはキーボードでの操作が主体となっている点が異なります。 Minnu s Filer2はキーボード主体のファイラーの中でもコンソールという文字だけのインターフェースを使ったものです。シェルも同じようにコンソール上で動くのでMinnu s Filer2はシェルの一種だと見ることもできます。事実内部的にはシェルを内蔵しています。このようなソフトをビュジュアルシェルと呼ぶこともあります。Minnu s Filer2はファイラーの良さとシェルの良さを兼ね備えたソフトなのです。 ファイラーの歴史 歴史的にはファイラーは少し前のパーソナルコンピュータ上のOS, MS-DOS上で発展してきました。日本ではFD, 海外ではNorton Commanderというソフトがよく使われてきました。Windowsの時代になりMS-DOS時代のファイラーの流れを組むWindows用のファイラーもたくさん生まれましたが、Windowsに付属するエキスプローラーの出来が良かったこともあり、現在ではファイラーを使う人は少なくなっています。しかし、ファイラーには長い歴史があり、いいファイラーソフトが生まれれば、新規ユーザーも増えていくのではないかと考えています。最近はファイルマネージャー、ファイラーともにスクリプトを内蔵する傾向にあり、Minnu s Filer2もRubyを内蔵しています。スクリプトを内蔵すると単調な処理をスクリプトで自動化することができます。 インストール インストールはMinnu s Filer2ホームページを見てください。 まだパッケージが用意されていないので、少々敷居が高いと思います。 各OSのメンテナにパッケージ化を頼もうと思っています。 さあ、mfiler2を使ってみよう。まずはコピーだ! インストールが無事すめば、シェル上でmfiler2というコマンドを実行すればMinnu s Filer2が起動します。左右二つにディレクトリが表示されていると思います。 アクティブなディレクトリは上部のパス名表示部分が強調されています。 逆側のディレクトリをスリープディレクトリと呼びます。 コピーなどのファイル操作の処理は大体アクティブなディレクトリからスリープディレクトリにされます。 まずはコピーの下準備。ディレクトリを移動しましょう。 カーソルキー上下でカーソルが移動します。ディレクトリの上にカーソルを持っていってENTERキーを押せば、そのディレクトリの中に入ります。 逆にBSキーを押せば親ディレクトリに移動します。 カーソルキー左右を押せばアクティブなディレクトリを左右移動できます。 とりあえず、コピーのテストができるようにアクティブなディレクトリをコピーしてもいいような小さいファイルがあるディレクトリ、スリープディレクトリに/tmp, $HOME/tmpなど、一時ファイルを置けるディレクトリに移動してみましょう。 さあ、ファイルのコピーです。まずはファイルのマーク。スペースキーを押せばカーソル下のファイルがマークされます。 マークされたファイルは*がファイル名の横に表示されたはずです。 ここでF5キーかcキーを押せば、スリープディレクトリにマークされたファイルがコピーされるはずです。できましたか?mfiler2によるファイルコピー操作はこれだけです。わずらわしいディレクトリ指定など要りません。非常に直感的に簡単にコピーできる気がしませんか? 次はコピーしたファイルを削除してみましょう。スリープディレクトリに移動するため、左右どちらかのキーを押して、スリープディレクトリをアクティブにして、コピーされたファイルをマークしてください。その後、F8かdキーを押してください。確認の質問文が表示されます。Yesを選択してEnterキーを押してください。これでファイルがごみ箱($HOME/mtrashbox)に移動されます。誤操作で消したファイルは($HOME/mtrashbox)に置いてあるので、そこから復活させてください。本当にファイルを削除したい場合は、Dキーを押してメニューからdeleteを選択してください。ファイルが本当に削除されるはずです。 ファイルの移動は同様にディレクトリを移動して、ファイルをマークしたあとに、F6かmキーでできます。 いちいちファイル選択するのがめんどくさいよ!シェルなら*.cppとかで一括に選択できるのに! ごもっともです。そのためにMinnu s Filer2には豊富な一括マーク操作を用意しています。 まずは全体選択です。HOMEキーを押すとディレクトリ以外のファイルがすべて選択されます。これはマークするのではなくてマークを反転します。つまりすでに選択されていたファイルは逆にマークが外されます。これはいろいろ応用範囲が広いので、覚えて置いてください。 ENDキーを押すとディレクトリを含むすべてのファイルが選択されます。 「これだけだとシェルで言う*という機能しかないじゃん!*.cppとかの方が便利だ」 大丈夫です。mfiler2には*.cppなどのグロブ(ワイルドカード)によるマークもサポートしています。*を押してください。メニューが表示されたはずです。 glob mark (f)ileを選んでください。 glob_mark * , * , * , * と表示されたはずです。 *.cppのマーク場合 glob_mark *.cpp , * , * , * で全てのcppファイルがマークされます。 toggle mark?と聞かれますがnoと答えてください。 ほかの引数の意味。 第一引数はファイル名の指定で*.cppとすれば拡張子がcppのファイルをマークできます。 第二引数はユーザー名の指定でrootと指定すればrootのファイルがマークできます。 第三引数はグループ名の指定。 第四引数はパーミッションの指定です。 マークには反転マーク(toggle mark)と単なるマークオンがあります。 toggle markの使い方の例。 まず全ての*.cppファイルをマークする glob_mark *.cpp , * , * , * toggle mark? no 次に所有者がrootのファイルを取り除く glob_mark *.cpp , root , * , * toggle mark? yes 次にmから始まるcppファイルを取り除く glob_mark m*.cpp , * , * , * toggle mark? yes などという使い方ができます。 逆にtoggle mark? noの使い方は まず全ての*.cppファイルをマークする glob_mark *.cpp , * , * , * toggle mark? no 次に全ての*.cファイルをマークする glob_mark *.c , * , * , * toggle mark? no です。 ほかにも glob mark (f)ile ファイルのみのワイルドカードマーク glob mark (a)ll ディレクトリなども含むワイルドカードマーク glob mark (d)irectory ディレクトリのみのワイルドカードマーク glob mark (e)xecutable 実行ファイルのみのワイルドカードマーク glob mark (r)eadable 読み込み可能ファイルのみのワイルドカードマーク glob mark (w)ritable 書き込み可能ファイルのみのワイルドカードマーク glob mark (s)ymlink シンボリックリンクファイルのワイルドカードマーク regex mark (F)ile 正規表現によるマーク mark (c)lear マークのクリア mark a(l)l files ファイルのみのマークの反転 mark a(L)l 全てのファイルのマーク反転 mark with c(o)mparison 2画面時左右のファイルを比較して同じファイルのみマーク 一括マークができるのはカレントディレクトリだけじゃんか!カレントディレクトリ以下すべての*.cppファイルに操作が行いたい Fによるファイル検索の仮想ディレクトリを使えば可能です。F - allでカレントディレクトリ以下のすべてのファイルを表示できます。このあと*のマークメニューのグロブによるマークで*.cppとしてcppファイルを選択すればいいでしょう。Fは他にも、あるサイズ以下のファイルを表示したり、ある更新日のファイルを表示したりできます。 ファイルの編集がしたい!UNIXではプログラミングやシステム管理でテキストファイルの編集を多用するし。 編集したいファイルの上にカーソルを移動して、F4かeを押してください。環境変数$EDITORで指定したエディッタが立ち上がるはずです。この場合vimやemacs -nwなどコンソール上で動くものだと、編集途中にファイル操作などがしたくなったらCTRL-Zでサスペンドすることができます。サスペンドするとmfiler2のファイラー画面の下に番号とサスペンドしたファイルのファイル名が表示されるので、もう一度エディッタ画面に戻りたい場合はその番号のキー(1なら1キー)を押せば、またエディッタ画面に戻ることができます。 X-Windowシステム上のエディッタ(gvim, xemacs, geditなど)を使用したい場合はカスタマイズする必要があります。それは後述。 いちいちファイルを探すのが面倒だ。やっぱりシェルでファイル名を入力する方が早い そのためにmfiler2にはファイルのインクリメンタルサーチが実装されています。fか/キーを押してください。そして目的のファイル名を入力すれば、そのファイルにカーソルが移動します。Enterキーで確定です。migemoつきでmfiler2をコンパイルしていれば日本語ファイルもローマ字で検索することができます。日本語ファイルを含むコマンドをシェルから起動する場合とても大変ですがmfiler2を使えば、とても簡単に日本語ファイルを扱えます。 コピー、移動、削除、編集、以外のファイル操作は? ファイルの作成はF10かnです。%r%Q mark_new_fileと表示されるのでの間に作りたいファイル名を入力すればファイルが作成されます。 ディレクトリの作成も同様にF9かkで行えます。 ファイル名の改名はファイル名を変えたいファイルの上にカーソルを持っていってF2かrです。 するとコマンドラインに以下のように表示されるので %Q%r rename 改名前のファイル名 , 改名後のファイル名 を入力してEnterを押してください。このときCTRL-Wによる後方単語削除が便利につかえると思います。 マークしてF2かrを押すと正規表現による一括ファイル改名が行えます。 試しにアクティブディレクトリにa.cpp, b.cppというファイルを作ってください。 a.cpp, b.cppをマークしましょう。 そしてF2かrを押してください。 gsub_rename //, "" と表示されたはずです。 正規表現をご存知でない方はUNIXでは正規表現を多用するので、このさい勉強しておきましょう。 /(.+).cpp/, "¥¥1.c" と入力すると確認用のページが表示されるので、ちゃんとa.c, b.cに改名されているか確認してください。Yesを選択するとa.cppがa.cにb.cppがb.cに改名されたのがわかると思います。 Rubyを利用してこの機能を作成しているので正規表現はRubyに準拠しています。詳細はRubyのページや本を見てください。 ファイル操作は便利にできることは分かった。でも、それ以外の処理をするにはやっぱりシェルが必要だ! ご安心を。mfiler2はシェルを内蔵していて、カスタマイズ可能で高機能な補完機能がついたコマンドラインがあります。hかF10を押すとコマンドラインに移行します。そこで好きなコマンドを入力してEnterを押せば、そのコマンドが実行されます。 TABを押せば補完候補が上の方に表示されますが、さらにTABキーを押せば補完候補をカーソルキーで選択できます。 カーソル下のファイルに何かのコマンドを実行したい場合、そのファイルにカーソルを合わせてF11かxを押せば、便利です。(ほんとはファイル実行なんのですが、こういう利用法もあります) マークした複数のファイルにコマンドを実行したい場合はファイルをマークしてからENTERを押してください。 %mと表示されますが、%mはマークされた複数のファイルに変換されるマクロです。 cat %mならマークされいた全てのファイルの内容が全て表示されるはずです。 「最近のシェルは高機能だからなぁ。ヒストリ検索とかもあんの?」 あります。検索したい語を入力したあとCTRL-Rを入力すれば、その語を含むコマンドライン履歴が表示されメニューから選択できます。 Rubyスクリプトによる処理の自動化 Meta+x(Escを押してからすぐx。もしくはAlt + x)を押してください。そうすると$EDITORが立ち上がります。そこにRubyによるスクリプトを書けば処理を自動化することができます。 試しにマークした全てのファイルのファイル名の拡張子の前に連番を付ける処理を書いてみましょう。 まず連番を付けたいファイルをマークします。そしてMeta+xを押してRubyスクリプト編集用のエディッタを立ち上げましょう。 で、以下を入力します。 n = 1 adir_mark.each do |f| ret = (f.scan /(.+)\.(.+)/)[0] File.reanme f, ret[0] + n.to_s + ret[1] n += 1 end エディッタを保存して終了するとスクリプトを実行して良いか聞いてくるのでYesと答えてください。正しく実行されるはずです。a.txt, b.txt, c.txt -- a1.txt, b2.txt, c3.txtなど。 adir_markはmfiler2組み込みの関数で、マークされたファイルのファイル名の配列を返します。scanなどはRubyを勉強して理解してください。そんなに難しいことはしていません。 処理が気に入った場合、オリジナルのコマンドとしてmfiler2に登録しましょう。次のカスタマイズの章で登録の仕方を教えます。 カスタマイズ mfiler2をカスタマイズするには/usr/local/etc/.mfilerをホームディレクトリにコピーして$HOME/.mfilerを編集します。 エディッタをgvim, xemacs, geditなどXウィンドウ上のものを使いたい場合は $HOME/.mfilerに keycommand NOMETA, KEY_e, "*", "shell( %q%o xemacs %f , %f )" keycommand NOMETA, KEY_F4, "*", "shell( %q%o xemacs %f , %f )" を追加してください。 keycommandはキーバインドを設定するコマンドでNOMETA, KEY_eはMetaキー無しのeキーという意味で、"*"はカーソル下の拡張子はなんでもOKという意味、 "shell( %q%o xemacs %f , %f )"は実行するコマンドです。 %qはコマンド待ちをしないマクロ %oはコマンド実行後マークをクリアしないマクロ %fはカーソル下のファイル名に変換されるマクロです。 shellはシェルコマンドを実行するコマンドです。 この場合eキーを押せばxemacsが起動します。 オリジナルコマンドを追加する。登録する関数がset_renbanだとするとset_renbanの定義をmfiler内に追加して mfiler末尾の defmenu("my_commands", "(1) set_number_at_head", KEY_1, "set_number_at_head()", "(2) del_number_at_head", KEY_2, "del_number_at_head()" ); keycommand NOMETA, KEY_y, "*", "menu( my_commands )" を defmenu("my_commands", "(1) set_number_at_head", KEY_1, "set_number_at_head()", "(2) del_number_at_head", KEY_2, "del_number_at_head()", "(3) set_renban", KEY_3, "set_renban" ); keycommand NOMETA, KEY_y, "*", "menu( my_commands )" としてください。 yを押せばメニューが追加されているはずです
https://w.atwiki.jp/elliciasp2nd/pages/181.html
2014/?内容変更後版 始まりの地 [精霊の導き] 依頼:NPC アリシアに名前を告げる 報酬:1/1 exp :カレッジリング×1 [初めての戦い] 依頼:MOB討伐 Lv2 グーミー×5 報酬:12/12 exp :[グーミーの欠片]×1 [冒険者の教え1] 依頼:説明を受ける 報酬:35/35 exp :- [冒険者の教え2] 依頼:MOB討伐 Lv4[クレメリア]×5 報酬:40/40 exp :[薬草]×10 [冒険者の教え3] 依頼:薬草を使う 報酬:-/- exp :- [冒険者の教え4] 依頼:復活ポイントを設定する アイテムを売る アイテムを買う 報酬:120/120 exp :初心者駅馬車券×1 [光の石と闇の胎動] 依頼:MOB討伐後、光る石を手に入れる Lv魔剣士シオン×1 報酬:800/800 exp :- リール野営地 [冒険者としての第一歩] 依頼:アイテム輸送 リール野営地の商人に 冒険者メダルを届ける 報酬:240/240 exp :- [モンスターと戦おう] 依頼:アイテム収集 [魔族の毛皮]×2 ・Lv7[イントルーダー]よりドロップ 報酬:240/240 exp :- [モンスターを退治しよう] 依頼:MOB討伐 Lv7[イントルーダー]×6 報酬:240/240 exp :- [アイテムを集めよう] 依頼:アイテム収集 [ゼリー]×1 [爪]×1 報酬:240/240 exp :- [商人へ届けよう] 依頼:アイテム輸送 商人に冒険者メダルを届ける 報酬:240/240 exp :- [アーデンとの出会い] 依頼:NPC[アーデン]に会う 報酬:100/100 exp :- ・依頼:NPC[マシュー]に地図を渡す ・報酬:100/100 exp :- [洞窟の魔物] 依頼:MOB討伐 Lv7[ゴルギス]×5 報酬:100/100 exp :- [封じられた扉] 依頼:アイテム収集 [小さな鍵]×5 ・Lv9[グルギス]よりドロップ 報酬:450/450 exp :- [暗闇に潜む魔族] 依頼:MOB討伐 Lv11[ギルギス]×1 報酬:1200/1200 exp :- [冒険者マシューとの冒険] 依頼:[洞窟の魔物]、 [封じられた扉]、 [暗闇に潜む魔族]をクリア後 アーデンに報告 報酬:1600/1600 exp :-
https://w.atwiki.jp/akasatanahama/pages/142.html
概要 レシピを追加する。 前のチュートリアルまで実装している段階でのコードである。 ソースコード 残念!ソースコードの追加実装などいらないのだよ!! あくまでも前のチュートリアルまで実装できていればだが、レシピの実装はjson側で行うため追加コードは必要ない。 アセット aluminium_block.json[recipe] src/main/resources/assets/aluminiummod/recipes/に配置する { "type" "minecraft crafting_shaped", "pattern" [ "###", "###", "###" ], "key" { "#" { "item" "aluminiummod aluminium" } }, "result" { "item" "aluminiummod aluminium_block" } } aluminium.json[recipe] { "type" "minecraft crafting_shapeless", "ingredients" [ { "item" "aluminiummod aluminium_block" } ], "result" { "item" "aluminiummod aluminium", "count" 9 } } 解説 MC1.12より、今までのレシピの登録方法が非推奨となり、代わりにjson形式でレシピを登録することになった。 その為、バニラにレシピを追加するだけのMODなら最悪@Modをつけたクラスを作成するだけでjavaに触れるのは終わる。 名称はそのままforge側に登録され、/recipeコマンドで使われるため作られるアイテムのレジスター名にするのが最適である。 まず、type要素でクラフトタイプを指定する。"minecraft crafting_shaped"で定形レシピ、minecraft crafting_shapelessで不定形レシピを指定する。 次に、定形レシピではpatternでレシピの形を指定し、その文字に当てはまるアイテムをkeyで指定する。 不定形レシピではingredientsで指定する。 最後に、resultで結果を登録する。 それぞれ で区切ってある前がMapのkey、後ろがvalueであると考えれば良い。 item要素で modid レジスター名 、count要素で個数、data要素でメタデータ(アイテムなのでblockstateは登録できない)を指定する。 アイテムの種類を増やしたいときはkey若しくはingredientsを下のように変更すれば良い。 +... 定形 "key" { "#" { "item" "aluminiummod aluminium" }, "A" { "item" "minecraft skull", "data" 4 }, 不定形 "ingredients" [ { "item" "aluminiummod aluminium_block" }, { "item" "minecraft skull", "data" 4 ], レシピ追加通知 MC1.12からの新機能として、「レシピブック」がある。 また、バニラのアイテムは入手したとき右上に「新規レシピ追加」という通知が出る。 今回はアイテムを大量に追加するMOD用に「レシピブック」とイベントを使って通知を出す。 (進捗のシステムを使ってレシピを出すことも出来るが、書くべきjsonファイル数が多くなる。そのやり方は進捗の追加チュートリアルで記載予定。) +... AluminiumMod.java クラス末尾に追加する。 @Mod.Instance("aluminiummod") public static AluminiumMod aluminiumInstance; @Mod.EventHandler public void init(FMLInitializationEvent event) { HOLDER.register(); } //アイテムを拾ったときのイベント。 @SubscribeEvent public void onPickupItem(EntityItemPickupEvent event) { this.aluminiumUnlockRecipes(event.getItem().getItem(), event.getEntityPlayer()); } //コンテナを閉じたとき(チェストやプレイヤーインベントリなど)のイベント。 @SubscribeEvent public void onCloseContainer(PlayerContainerEvent.Close event) { for (ItemStack itemStack event.getEntityPlayer().inventoryContainer.getInventory()) { this.aluminiumUnlockRecipes(itemStack, event.getEntityPlayer()); } } private void aluminiumUnlockRecipes(ItemStack stack, EntityPlayer player) { if (FMLCommonHandler.instance().getSide().isClient()) { Item item = stack.getItem(); int meta = stack.getMetadata(); ItemStack itemStack = new ItemStack(item, 1, meta); //もしレシピを保持するリストに合致すれば if (!this.HOLDER.map.isEmpty() this.HOLDER.map.containsKey(itemStack)) { List ResourceLocation list = this.HOLDER.map.get(itemStack); //player.unlockRecipes(ResourceLocation[] locations)でレシピブックに追加する。 player.unlockRecipes(list.toArray(new ResourceLocation[list.size()])); } } } AluminiumRecipeHolder.java レシピをリソースから読み取って保持するクラス。 package com.tntmodders.tutorial; import com.google.gson.Gson; import com.google.gson.JsonObject; import com.google.gson.stream.JsonReader; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.util.ResourceLocation; import net.minecraftforge.fml.common.FMLCommonHandler; import java.io.*; import java.net.URL; import java.util.*; import java.util.jar.JarEntry; import java.util.jar.JarFile; public class AluminiumRecipeHolder { //ItemStackよりそのアイテムが鍵となるレシピを取得できるようにする。 public static final Map ItemStack, List ResourceLocation map = new ItemStackHashMap(); public void register() { if (FMLCommonHandler.instance().getSide().isClient()) { //assets/ modid /recipes/よりリソースを取得する。 this.getResource("assets/aluminiummod/recipes/"); } } public void getResource(String path) { ClassLoader loader = AluminiumMod.class.getClassLoader(); URL url = loader.getResource(path); //jarファイル内か否かで処理が変化する。 if (url.getProtocol().equals("jar")) { String[] strings = url.getPath().split(" "); String leadPath = strings[strings.length - 1].split("!")[0]; File f = new File(leadPath); JarFile jarFile; try { //jarファイル自体を取得する。(zipファイル・jarファイルとして扱う事ができる。) jarFile = new JarFile(f); Enumeration JarEntry enumeration = jarFile.entries(); while (enumeration.hasMoreElements()) { JarEntry entry = enumeration.nextElement(); String s = entry.getName(); if (s != null s.startsWith(path) s.endsWith(".json")) { InputStream stream = null; try { stream = loader.getResourceAsStream(s); //inputstreamを使ってjarファイル内のjsonを読み込む。 this.readStream(stream, s); stream.close(); } catch (Exception e) { e.printStackTrace(); } } } } catch (IOException e) { e.printStackTrace(); } } else { List File list = this.getListFile(path); if (list.size() 0) { for (File recipe list) { InputStream stream = null; try { stream = new FileInputStream(recipe); this.readStream(stream, recipe.getName()); stream.close(); } catch (Exception e) { e.printStackTrace(); } } } } } //ファイルを全て取得する。これもjarか否かによって変わる。 private List File getListFile(String path) { List File files = new ArrayList (); ClassLoader loader = AluminiumMod.class.getClassLoader(); URL url = loader.getResource(path); if (url.getProtocol().equals("jar")) { String[] strings = url.getPath().split(" "); String leadPath = strings[strings.length - 1].split("!")[0]; File f = new File(leadPath); JarFile jarFile; try { jarFile = new JarFile(f); Enumeration JarEntry enumeration = jarFile.entries(); while (enumeration.hasMoreElements()) { JarEntry entry = enumeration.nextElement(); String s = entry.getName(); if (s != null s.startsWith(path) s.endsWith(".json")) { files.add(new File(loader.getResource(s).getPath())); } } } catch (IOException e) { e.printStackTrace(); } } else { File packFile = FMLCommonHandler.instance().findContainerFor(AluminiumMod.aluminiumInstance).getSource(); File newFile = new File(packFile.toURI().getPath() + path); files = Arrays.asList(newFile.listFiles()); } return files; } private void readStream(InputStream stream, String name) { //inputstreamよりJSONを読み込む。 JsonReader reader = new JsonReader(new InputStreamReader(stream)); JsonObject jsonObject = new Gson().fromJson(reader, JsonObject.class); //文字列の中にパスが紛れ込んだ場合それを消す。また、".json"を抜いてResourceLocationとして保存する。 ResourceLocation location = new ResourceLocation("aluminiummod", name.replaceAll("assets/aluminiummod/recipes/", "") .replaceAll(".json", "")); //定形レシピでキーを"#"にしたアイテムを鍵とする。 if (jsonObject.has("key") jsonObject.getAsJsonObject("key").has("#")) { Item item = Item.getByNameOrId(jsonObject.getAsJsonObject("key").getAsJsonObject("#").get("item").getAsString()); int i = 0; if (jsonObject.getAsJsonObject("key").getAsJsonObject("#").has("data")) { i = jsonObject.getAsJsonObject("key").getAsJsonObject("#").get("data").getAsInt(); } ItemStack stack = new ItemStack(item, 1, i); List ResourceLocation locations = map.containsKey(stack) ? map.get(stack) new ArrayList ResourceLocation (); locations.add(location); map.put(stack, locations); } //不定形レシピで一番上に書いたアイテムを鍵とする。 else if (jsonObject.has("ingredients") jsonObject.getAsJsonArray("ingredients").get(0).getAsJsonObject().has("item")) { String s = jsonObject.getAsJsonArray("ingredients").get(0).getAsJsonObject().get("item").getAsString(); Item item = Item.getByNameOrId(s); int i = 0; if (jsonObject.getAsJsonArray("ingredients").get(0).getAsJsonObject().has("data")) { i = jsonObject.getAsJsonArray("ingredients").get(0).getAsJsonObject().get("data").getAsInt(); } ItemStack stack = new ItemStack(item, 1, i); List ResourceLocation locations = map.containsKey(stack) ? map.get(stack) new ArrayList ResourceLocation (); locations.add(location); map.put(stack, locations); } } //ItemStackを使ったマップを定義する。 public static class ItemStackHashMap K extends ItemStack, V extends List ResourceLocation extends HashMap K, V { public V get(Object key) { if (key instanceof ItemStack this.containsKey(key)) { for (Map.Entry K, V entry this.entrySet()) { if (entry.getKey().getItem() == ((ItemStack) key).getItem() entry.getKey().getMetadata() == ((ItemStack) key).getMetadata()) { return entry.getValue(); } } } return null; } @Override public boolean containsKey(Object key) { if (key instanceof ItemStack) { ItemStack itemStack = ((ItemStack) key); for (ItemStack stack this.keySet()) { if (stack.getItem() == itemStack.getItem() stack.getMetadata() == itemStack.getMetadata()) { return true; } } } return false; } } } コメント この項目に関する質問などをどうぞ。 名前
https://w.atwiki.jp/mfiler2tutorial/pages/11.html
画面制御コマンド minitscr() 湊cursesの開始。画面制御コマンドを使う前に呼び出す必要あり。 mendwin() 湊cursesの終了。 mmove(y, x) メモリ上のカーソルをx,yに移動 mmove_immediately(y, x) 画面上のカーソルをy,xに移動 mprintw("", ...) メモリ上のカーソル位置にメモリ上のバッファに文字列を描写 mvprintw(y,x, "", ...) y,xに文字列を描写 mattron(attrs) 文字列の描写属性を設定。以後の文字列描写は設定した属性になる。 MA_REVERSE 反転 MA_BOLD 強調 MA_UNDERLINE 下線 MA_WHITE 白 MA_BLUE 青 MA_CYAN シアン MA_GREEN 緑 MA_YELLOW 黄色 MA_MAGENTA マジェタ MA_RED 赤 mattroff() 文字列の描写属性を初期化。 magetmaxx() 端末のX方向の最大文字数 mgetmaxy() 端末のy方向の最大文字数 mclear_immediately() 画面の消去 mclear() メモリ上の画面を消去 mclear_online(y) y行だけメモリ上の画面を消去 mbox(y,x,width,height) ボックスを描写 mrefresh() メモリ上の画面を実際の画面に描写 mgetch() キー入力待ちして押されたキーを[meta, key]で返す。metaはメタキーが押されていたら1押されていなかったら0, keyはキーコード。 mgetch_nonblock() キー入力しないmgetch() mis_curses() 湊カーシスが起動されていたらtrueを返す dir_move(dir, rdir) dirが0なら左のディレクトリウィンドウ 1なら右のディレクトリウィンドウ rdirのディレクトリにディレクトリを移動する。 set_sort_kind(dir, sort_kind), sort_kind(dir) dirのソートの種類 "name", "name_rev", "extension", "extension_rev" "size, "size_rev", "time", "time_rev" "user", "user_rev", "group", "group_rev" "permission", "permission_rev", "random", "none" sort(dir) 現在のソートの種類で実際にソートする adir() 現在のアクティブなディレクトリの番号を返す 0 - 左のディレクトリ 1 - 右のディレクトリ sdir() 現在の非アクティブなディレクトリの番号を返す view_nameonly(dir),set_view_nameoly(dir,value) ネームオンリーモード view_focusback(dir), set_view_focusback(dir, value) dirのディレクトリのファイル名を後方にフォーカスして表示するかどうか view_removedir(dir), set_view_removedir(dir, value) ファイル名のディレクトリ部分を表示するかどうか set_view_filer(option). view_filer() 現在のファイラー描写の仕方 "all" "one_dir" "one_dir2" "one_dir3" "one_dir5" view_color(), set_view_color(boolean) カラーで表示するかどうか view_size(), set_view_size(boolean) サイズ表示するかどうか view_group(), set_view_group(boolean) グループ表示するかどうか view_user(), set_view_user(boolean) ユーザー表示するかどうか view_nlink(), set_view_nlink(boolean) nlinkを表示するかどうか view_permission(), set_view_permission(boolean) パーミッション表示するかどうか view_mtime(), set_view_mtime(boolean) モディファイタイム表示 set_view_color_mark(color) マークしたファイルのカラー set_view_color_exe(color) 実行ファイルのカラー set_view_color_link(color) リンクファイルのカラー set_view_bold_exe(boolean) 実行ファイルをBOLDにするか set_view_bold_dir(boolean) ディレクトリをBOLDにするか set_cmdline_escape_key(boolean), cmdline_escape_key() コマンドラインでESCAPEキーでファイラー画面に戻るかどうか set_kanjicode_filename(name), kanjicode_filename() "sjis", "utf8", "utf8-mac", "eucjp", "unknown" set_kanjicode(name), kanjicode() "sjis", "utf8", "eucjp" tab_max() タブの数 tab_new(num, path, scrolltop, cursor) タブを作る。 num タブ番号 path ディレクトリ位置 scrolltop スクロールトップ位置 cursor カーソル位置 tab_select() タブ選択メニュー tab_close(num) num番号のタブを閉じる tab_up(num) タブを前面に出す num タブ番号 tab_path(num) タブ番号のパス tab_scrolltop(num) タブ番号のスクロールトップ tab_cursor(num) カーソル位置 cursor_name(), cursor_name_convert() カーソル位置のファイル名 cursor_path(), cursor_path_convert() カーソル位置のファイル名のパス cursor_ext(), cursor_ext_convert() カーソル位置のファイルの拡張子 cursor_noext(), cursor_noext_convert() カーソル位置の拡張子を覗いたファイル名 active_dir(), active_dir_convert() アクティブディレクトリのファイル名 sleep_dir(), sleep_dir_convert() 非アクティブディレクトリのファイル名 left_dir(), left_dir_convert() 左ディレクトリのファイル名 right_dir(), right_dir_convert() adir_path(), adir_path_convert() アクティブディレクトリのパス sdir_path(), sdir_path_convert() 非アクティブディレクトリのパス ldir_path(), ldir_path_convert() 左ディレクトリのパス rdir_path(), rdir_path_convert() adir_mark(), adir_mark_convert() マークファイルのファイル名の配列 sdir_mark(), sdir_mark_convert() 非アクティブディレクトリ adir_mark_fullpath(), adir_mark_fullpath_convert() マークファイルのパス名の配列 ldir_mark(), ldir_mark_convert() 左ディレクトリのマークファイル rdir_mark(), rdir_mark_convert() ldir_mark_fullpath(), ldir_mark_fullpath_convert() rdir_mark_fullpath(), rdir_mark_fullpath_convert() set_change_terminal_title(boolean), change_terminal_title() 端末のタイトルを変えるかどうか change_sort() ファイルの並び替え set_isearch_option1(boolean), isearch_option1() インクリメンタルサーチのオプション set_menu_scroll_cycle(boolean), menu_scroll_cycle() メニューのサイクル set_view_fname_divide_ext(boolean), view_fnmae_divide_ext() 拡張子をファイル名を分離して表示するかどうか keycommand(meta, keycode, extension, command) meta, keycodeのキー。 extesionは"*"で拡張子を指定しない、".c" 拡張子cのファイル ".dir"だとディレクトリ 、".execute"で実行ファイル ".link"でsymbolic link、".mark"でマークファイrk-c"で拡張子cのマークファイル時 "fname" fnameのファイル名のファイル時 commandはバインドするrubyコマンド。 cursor_move(dir, value) dirのディレクトリのvalueの位置にカーソルを移動 cursor_left() 左ディレクトリに移動 cursor_right() version() バージョン文字列を返す mark_all() マークオール mark_all_files() マークオールファイル mark_clear() マークをクリア mark(dir, num, value) num位置のファイルのマークをvalueに設定 is_marked(dir, num) num位置のファイルのマーク marking(dir) マーク中か cmdline_c(command, postion, cmd) cmdline_convert(command, position, cmd) cmdline_noconvert(command, position, cmd) shell(cmd, title) 内部シェルでcmdを実行 defmenu(name, item_name, item_key, item_cmd, ...) menu(name) set_mask(dir, mask) マスクを設定 refresh() reread(dir)
https://w.atwiki.jp/mfiler2tutorial/pages/2.html
メニュー トップページ Minnu's Filer2オフィシャルページ
https://w.atwiki.jp/legendofnorrath/pages/227.html
TUTORIAL7 - Tactics Combat ~戦術と戦闘について~ このチュートリアルでは、Tacticカード、それをプレイする状態と、戦闘の基礎について学びます。 *Tacticカードについて *状態について *戦闘について === あなたの対戦相手は、プレイマットにどんなアイテムや、アビリティやユニットが置かれているかを見ることが出来ます。 そこから、あらゆる戦闘に対する成功率を見積もることは容易でしょう。 彼が知らないことは、あなたの手札にTacticカードがあるかどうかです。 Tacticは驚きと逆転をもたらします。それらは戦闘中のみプレイできます。 いったん戦闘が開始すれば、アタッカーが先手で、交互にアクションを起こします。 あなたのターンが回ってきたとき、あなたはプレイマットに置かれたカードを使用するか、手札からTacticを使用することが出来ます。 ちょっと、この Tactic をどう表現するか困ったので、 Tactic で行かせてもらいます。 ItemやAbilityもそのままでよかったんじゃないか、とか今更思ったりしてますが… === 他のカードのように、Tacticもアーキタイプが設定されています。 また、GenericのTacticも存在し、どんなデッキにも組み込むことが可能です。 多くのTacticは、プレイするためのコストを持ちません。 コストを持つTacticを対戦相手のターンに使用するためには、自分の前のターンでPowerを節約しなくてはいけません。 Tacticはふつう、自身のゲームテキストに、どのようにプレイ出来るか、という制限事項が書かれています。いくつかはあなたが攻撃中か防御中か、そしていくつかは対象とするのがユニットかアバターか、ということです(どちらも、というわけではなく) Tacticカードがプレイされたとき、その効果が発動し、すぐに捨て札に納められます。 3つ目の文章の制限ですが、要するに攻撃時/防御時/攻撃・防御時と、ユニット対象/アバター対象/どちらも対象といった2つの条件があって、その両方か、あるいはどちらかだけが設定されているということです。 A AND Bではなく、A OR Bの関係・・・てことでしょうか。蛇足でした。 === では、戦闘がどのように進行し、Tacticがどのように相手を驚かせるかを見てみましょう。まず、前提として、あなたは手札に、対戦相手のアバターと先頭を始めるアビリティを持っています。 手札のASSAULTをダブルクリックしてプレイしましょう。 === 戦闘が始まりました!プレイマット中央の戦闘アイコンがあなたのトータル攻撃力と対戦相手のトータル防御力を示しています。 双方の数字は0から始まります。 攻撃と防御は戦闘の勝者を決めるために比較されます。 もしそれらが等しい場合、戦闘は引き分けになります。 どちらか勝利した方が(もしくは両方が…引き分けの場合)、相手にダメージを与えられます。 双方の戦闘アイコンの上と下に、ダメージアイコンが現れました。 1つづつのアイコンがそこにあるならば、どちらのプレイヤーも、戦闘に勝利、もしくは引き分けた場合、1ダメージを与えられます。 攻撃と防御は、どれだけダメージを与えられるかには影響しません:ダメージボーナスとカードの効果が、ベースのダメージを追加できます。 === 全ての戦闘には4つのステージがあり、以下の順番によります: 1.戦闘アクションを行う。 2.勝者を決定する。 3.カードをダメージボーナスのためにExertする。 4.ダメージを与える。 双方のプレイヤーは戦闘においてアクションを起こすことができ、攻撃側プレイヤーが先攻で、 交互に行われます。 あなたの行動するターンにおいて、あなたは1つのアクションを起こすかパスすることができます。 双方のプレイヤーが続けてパスした場合、あなたは 勝者を決定すること に同意したことになります。 === 戦闘アクションにおいて攻撃側が可能なことは、以下のようになります: *カードをExertしてトータル攻撃力に加える *あなたの戦闘要員の、 攻撃時発動 能力を発動する *Tacticカードをプレイする あなたが攻撃側で、最初のアクションを起こすので、あなたのアバターをExertして、トータル攻撃力に加えましょう: あなたのカードを行動させるには2通りの方法があります。 ふつうは、あなたのカードをダブルクリックすればうまくいくでしょう。 また、あなたのカードを左クリックし、ホールドすることでアクションボタンの 放射状 メニューを出すことができます。 今回は、これをあなたのアバターに試してみてください。TERINを左クリックし、ホールドして剣のボタンを選択し、カードを攻撃するためにExertしてください。 TERINを左クリックし、ホールドして剣のボタンを選択してください。 ここのメニューは前章の補足でチラっと書きましたが・・・ 要するに、左クリック長押し、です。 === ここであなたはアバターをExertして攻撃に加えたため、それをExertしてダメージボーナスを追加することはできなくなりました。 これはトレードオフの関係にあり、同じ戦闘で両方の特質を使用することはできません。 === 防御側のできることは以下になります: *カードをExertして、トータル防御力に加える。 *あなたの戦闘要員の、 防御時発動 能力を発動する *Tacticカードをプレイする あなたの対戦相手はアバターをExertして防御に加えました。 あなたは2対2で引き分けました。 戦闘が引き分けで終わると、双方のプレイヤーが対戦相手にダメージを与えられます。 あなたが対戦相手より多くのHealthをもっている場合、双方が1ダメージを受けるような、このシチュエーションは多分いいものです。 PASSをクリックしてください。 === あなたの対戦相手は彼女のアビリティFORGE AHEADをExertして防御力に1を加えました。 あなたは2対3で戦闘に負けてしまいそうです。 現在プレイマット上には、攻撃に加えられるようなカードはありませんが、 あなたはプレイ可能なTacticカードを手札に持っています。 PIERCEをダブルクリックしてプレイしてください。 === 拡大版のPIERCEがプレイマットに現れ、双方のプレイヤーにTacticがプレイされたことを気づかせます。 これは扱いやすいTacticで、トータル攻撃力に2を加えます。 順を追って何が起こったかを見てみましょう: ステージ1、 戦闘アクションの発動 -- 双方のプレイヤーが選択できるものがなくなったため、 自動的にパスが双方に適用されて、このステージが終了しました。 ステージ2、 勝者の決定 -- あなたが4対3で勝利しました。 ステージ3、 カードをExertしてダメージボーナスに加える -- 双方が、そうできるカードを残していません。 ステージ4、 ダメージを与える -- 今こそ対戦相手に戦闘によるダメージを与えるときです。 あなたの戦闘アイコンの下には1つのダメージアイコンがあるため、あなたは1ダメージを彼女に与えます。 === あなたの対戦相手は戦闘に負け、1ダメージを受けました。 あなたのアバターを戦闘に加える代わりに、Exertしてダメージボーナスを与えることもできましたが。 その両方は選べません! ゲーム中に行う多くの決定はトレードオフの関係にあります。 その決定はあなたに何かを与えますが、同時に対戦相手に対して隙を与えてしまいます。 ちょっと最後端折りましたが、だいたい意味的にそんなところです。 戻る
https://w.atwiki.jp/akasatanahama/pages/65.html
概要 メタデータを使用し、一つのIDで複数のブロックを追加したり、向きを持つブロックを追加したりする。 ソースコード AluminiumMod.java package tutorial.aluminiummod; import net.minecraft.block.Block; import cpw.mods.fml.common.Mod; import cpw.mods.fml.common.Mod.EventHandler; import cpw.mods.fml.common.event.FMLPreInitializationEvent; import cpw.mods.fml.common.registry.GameRegistry; @Mod(modid = AluminiumMod.MODID, name = AluminiumMod.MODNAME, version = AluminiumMod.VERSION) public class AluminiumMod { public static final String MODID = "AluminiumMod"; public static final String MODNAME = "Aluminium Mod"; public static final String VERSION = "1.0.0"; public static Block blockAluminiumColored; @EventHandler public void perInit(FMLPreInitializationEvent event) { //ここは通常のブロックと同様。 blockAluminiumColored = new ColoredAluminiumBlock() .setBlockName("blockAluminiumColored") .setBlockTextureName("aluminiummod colored_aluminium_block"); GameRegistry.registerBlock(blockAluminiumColored, ItemColoredAluminiumBlock.class, "blockAluminiumColored"); } } ColoredAluminiumBlock.java package tutorial.aluminiummod; import java.util.List; import net.minecraft.block.Block; import net.minecraft.block.material.Material; import net.minecraft.client.renderer.texture.IIconRegister; import net.minecraft.creativetab.CreativeTabs; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.util.IIcon; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; public class ColoredAluminiumBlock extends Block { private IIcon[] iicon = new IIcon[16]; protected ColoredAluminiumBlock() { super(Material.rock); this.setCreativeTab(CreativeTabs.tabBlock); this.setHardness(5.0F); this.setResistance(10.0F); this.setStepSound(Block.soundTypeMetal); this.setHarvestLevel("pickaxe", 2); this.setLightLevel(0.0F); } @Override @SideOnly(Side.CLIENT) public void registerBlockIcons(IIconRegister register) { for (int i = 0; i 16; i ++) { this.iicon[i] = register.registerIcon(this.getTextureName() + "-" + i); } } @Override @SideOnly(Side.CLIENT) public IIcon getIcon(int side, int meta) { return iicon[meta]; } @Override @SideOnly(Side.CLIENT) public void getSubBlocks(Item item, CreativeTabs creativeTab, List list) { for (int i = 0; i 16; i ++) { list.add(new ItemStack(item, 1, i)); } } @Override public int damageDropped(int meta) { return meta; } } ItemColoredAluminiumBlock.java package tutorial.aluminiummod; import net.minecraft.block.Block; import net.minecraft.item.ItemBlockWithMetadata; import net.minecraft.item.ItemStack; public class ItemColoredAluminiumBlock extends ItemBlockWithMetadata { public ItemColoredAluminiumBlock(Block block) { super(block, block); } @Override public String getUnlocalizedName(ItemStack itemStack) { return this.getUnlocalizedName() + "." + itemStack.getItemDamage(); } } 解説 GameRegistry Block registerBlock(Block block, Class ? extends ItemBlock itemclass, String name) GameRegistryに追加ブロックを登録するメソッド。 対応するItemBlockを指定できる。 デフォルトではItemBlockを指定している。 Block void registerBlockIcons(IIconRegister register) ブロックのテクスチャを指定するメソッド。 Itemと同じ。 IIcon getIcon(int side, int meta) 描画時に呼ばれる。 第一引数では面を、第二引数ではメタデータを取得できる。 このメソッドを使えば面によって違うテクスチャを返したり、かまどのように向きを変えたりできる。 第一引数については下の「sideについて」で。 void getSubBlocks(Item item, CreativeTabs creativeTab, List list) クリエイティブタブに登録するメソッド。 Itemと同じ。 int damageDropped(int meta) ドロップアイテムのダメージを指定するメソッド。 Blockでは常に0を返しているのでオーバーライドする。 ItemBlockWithMetadata ItemBlockのサブクラスで、メタデータを使用するブロック用のクラス。 コンストラクタ(Block block, Block localBlock) 第一引数はスーパークラスのコンストラクタに渡し、第二引数はこのクラスで保持する。 String getUnlocalizedName(ItemStack itemStack) アイテムと同じ。 sideについて getIconの第一引数などのintは、面の方角を表している。 向きと座標の関係は、net.minecraft.util.FacingのoffsetsXForSide/offsetsYForSide/offsetsZForSideを使えばわかる side 向き 座標 0 下 y- 1 上 y+ 2 北 z- 3 南 z+ 4 西 x- 5 東 x+ 使用例 オファレンブロックを追加している部分。 +オファレンMOD OfalenModCore.java package nahama.ofalenmod; /*略*/ /**@author Akasata Nahama*/ @Mod(modid = OfalenModCore.MODID, name = OfalenModCore.MODNAME, version = OfalenModCore.VERSION) public class OfalenModCore { public static final String MODID = "OfalenMod"; public static final String MODNAME = "Ofalen Mod"; public static final String VERSION = "[1.7.10]1.0.0"; /*略*/ /**最初に行われる処理。アイテム・ブロックの追加などを行う*/ @EventHandler public void preInit(FMLPreInitializationEvent event) { /*略*/ //ブロックを設定するメソッドを実行 OfalenModBlockCore.registerBlock(); /*略*/ } /*略*/ } OfalenModBlockCore.java package nahama.ofalenmod.core; /*略*/ public class OfalenModBlockCore { *略*/ public static Block blockOfalen; /*略*/ /**ブロックを設定する*/ public static void registerBlock () { /*略*/ blockOfalen = new OfalenBlock() .setBlockName("blockOfalen") .setBlockTextureName("ofalenmod ofalen_block-"); GameRegistry.registerBlock(blockOfalen, ItemOfalenBlock.class, "blockOfalen"); /*略*/ } } OfalenBlock.java package nahama.ofalenmod.block; import java.util.List; import nahama.ofalenmod.OfalenModCore; import net.minecraft.block.Block; import net.minecraft.block.material.Material; import net.minecraft.client.renderer.texture.IIconRegister; import net.minecraft.creativetab.CreativeTabs; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.util.IIcon; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; public class OfalenBlock extends Block { private IIcon[] iicon = new IIcon[4]; public OfalenBlock() { super(Material.rock); this.setCreativeTab(OfalenModCore.tabOfalen); this.setHardness(7.5F); this.setResistance(15.0F); this.setStepSound(Block.soundTypeMetal); this.setLightLevel(1.0F); this.setHarvestLevel("pickaxe", 3); } /**メタデータ違いのテクスチャを登録する*/ @Override @SideOnly(Side.CLIENT) public void registerBlockIcons(IIconRegister register) { for (int i = 0; i 4; i ++) { this.iicon[i] = register.registerIcon(this.getTextureName() + i); } } /**メタデータにより返すIIconを変える*/ @Override @SideOnly(Side.CLIENT) public IIcon getIcon(int side, int meta) { return iicon[meta 3]; } /**メタデータ違いのブロックを登録する*/ @Override @SideOnly(Side.CLIENT) public void getSubBlocks(Item item, CreativeTabs creativeTab, List list) { for (int i = 0; i 4; i ++) { list.add(new ItemStack(item, 1, i)); } } /**メタデータによりドロップ品を変える*/ @Override public int damageDropped(int meta) { return meta 3; } } ItemOfalenBlock.java package nahama.ofalenmod.itemblock; import net.minecraft.block.Block; import net.minecraft.item.ItemBlockWithMetadata; import net.minecraft.item.ItemStack; public class ItemOfalenBlock extends ItemBlockWithMetadata { public ItemOfalenBlock(Block block) { super(block, block); } /**メタデータにより内部名を変える*/ @Override public String getUnlocalizedName(ItemStack itemStack) { return this.getUnlocalizedName() + "." + itemStack.getItemDamage(); } } コメント この項目に関する質問などをどうぞ。 かまどみたいに置く向きによって変わるのってどうして作るんですか? - 名無しさん 2015-10-12 21 07 02 onBlockPlacedByをオーバーライドし、置いたプレイヤーの向きによって、メタデータを設定します。バニラのBlockFurnaceや、オファレンMODのBlockSmeltingMachineなどが参考になるかと思います。 - 赤砂蛇凪浜 2015-10-13 08 36 08 メタデータによって上面のテクスチャだけを変えるにはどうすればいいですか? - 名無しさん 2016-06-10 23 03 47 IIconをあらかじめ用意しておき、getIconでsideとmetadataの判定をして返すIIconをかえればよいです。 - 赤砂蛇凪浜 2016-06-11 06 52 52 Optifineのように隣り合ったガラスの縁を消すのにはメタデータの違うブロックを置き換えればよいですか? - 名無しさん 2016-06-12 00 31 06 BFOのフチなしガラスでは、getIcon(IBlockAccess,int,int,int,int)で判定を行い、IIconを返しています。メタデータを使う必要はありません。 - 赤砂蛇凪浜 2016-06-12 06 59 29 通常のブロック追加では一つ画像のみでいくらブロックをおいても同じ柄ですが、8×8の64枚の画像をrepeatの形で適応させるにはどう作れば良いのですか?? - 名無しさん 2016-06-14 17 45 47 返答遅くなりまして申し訳ありません。アニメーションさせたい場合は、まず、アニメーションさせたいブロックのテクスチャを、アニメーション順に縦に並べてください。次に、ブロックのテクスチャと同じ階層に[ブロック名].png.mcmeta というファイルを作って、以下のように記述してください。 { "animation" { "frametime" 2 } } アニメーションの速度が速ければ、"frametime"の数値を上げてください。バニラのリソースでは、火や溶岩が参考になるかと思います。- Tom Kate 2016-06-25 11 36 47 メタ付の半ブロックを追加するにはどうすればいいのでしょうか? - 名無しさん 2017-04-20 19 50 42 返信が遅くなってしまい申し訳ありません。コメントを別のページから移動させて頂きました。ご了承ください。単純なものであれば、BlockStoneSlabやBlockWoodSlabをコピペし、各メソッド内でインスタンスの呼び出しをしている部分を置き換えればよいです。ただし、BlockSlabの一部メソッドやItemなど他のクラスでもインスタンスを呼び出しているので、それらも考慮する必要があると思われます。今後、ハーフブロックの追加に関するチュートリアルを作成する予定です。 こちらはマイクラバージョン1.10や1.11などでも使えるのでしょうか...? - 名無しさん 2017-06-08 23 17 07 ver1.8以降はBlockStateと言うものを利用いたしますのでこのチュートリアルは使用できません。 - Tom Kate 2017-06-09 19 13 51 かまどではなく、原木や柱状クオーツのように横から置くとtopの部分が横を向くようにするには、どうすればよいでしょうか? - 名無しさん 2017-06-21 21 22 17 返信が遅くなってしまい申し訳ありません。単純なものでしたら、BlockRotatedPillarを継承し、BlockHayを参考にgetSideIconとregisterBlockIconsをオーバーライドすればできます。継承関係があり少々複雑ですが、原木のクラス(BlockLog, BlockOldLog, BlockNewLog)を見れば一つのIDで四種類まで追加できるかと思います。BlockRotatedPillarでは、getRenderTypeで柱状のレンダーを指定し、横向き設置時にテクスチャを回転させています。また、onBlockPlacedで設置する支えとなったブロックの面によりメタデータで向きを設定し、getIconでメタデータにより断面のテクスチャの向きを変更しています。 - 赤砂蛇凪浜 2017-07-08 18 06 57 名前
https://w.atwiki.jp/akasatanahama/pages/126.html
概要 村人の職業を追加し、専用の家を村に生成させる。 ソースコード AluminiumMod.java package tutorial.aluminiummod; import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.common.Mod; import cpw.mods.fml.common.event.FMLInitializationEvent; import cpw.mods.fml.common.event.FMLPreInitializationEvent; import cpw.mods.fml.common.registry.GameRegistry; import cpw.mods.fml.common.registry.VillagerRegistry; import net.minecraft.block.Block; import net.minecraft.creativetab.CreativeTabs; import net.minecraft.item.Item; import net.minecraft.util.ResourceLocation; import net.minecraft.world.gen.structure.MapGenStructureIO; @Mod(modid = "AluminiumMod", name = "Aluminium Mod", version = "1.0.0") public class AluminiumMod { /** * 村人IDの宣言 * 0~4は既存の村人として設定されているため、使ってはいけない */ public static final int metalVillagerID = 334; //追加するアイテム・ブロックの宣言 public static Item aluminium; public static Block oreAluminium; //村人の宣言 @Mod.EventHandler public void preInit(FMLPreInitializationEvent event) { //アイテム・ブロックの実装 aluminium = new Item() .setCreativeTab(CreativeTabs.tabMaterials) .setUnlocalizedName("aluminium") .setTextureName("aluminiummod aluminium"); GameRegistry.registerItem(aluminium, "aluminium"); oreAluminium = new AluminiumOre() .setBlockName("oreAluminium") .setBlockTextureName("aluminiummod aluminium_ore"); GameRegistry.registerBlock(oreAluminium, "oreAluminium"); } @Mod.EventHandler public void init(FMLInitializationEvent event) { //村人IDの登録 VillagerRegistry.instance().registerVillagerId(metalVillagerID); //村人の登録 VillagerRegistry.instance().registerVillageTradeHandler(metalVillagerID, new AluminiumTrade()); if (FMLCommonHandler.instance().getSide().isClient()) { VillagerRegistry.instance().registerVillagerSkin(metalVillagerID, new ResourceLocation("aluminiummod textures/mobs/metal_villager.png")); } //村人生成の登録 VillagerRegistry.instance().registerVillageCreationHandler(new AluminiumVillageCreation()); //構造物の登録 MapGenStructureIO.registerStructure(AluminiumHouse.class, "AluminiumHouse"); MapGenStructureIO.func_143031_a(AluminiumHouse.class, "AluminiumHouse_"); } } AluminiumOre.java 鉱石の追加 と同様 AluminiumTrade.java package tutorial.aluminiummod; import cpw.mods.fml.common.registry.VillagerRegistry; import net.minecraft.entity.passive.EntityVillager; import net.minecraft.init.Items; import net.minecraft.item.ItemStack; import net.minecraft.village.MerchantRecipe; import net.minecraft.village.MerchantRecipeList; import java.util.Random; public class AluminiumTrade implements VillagerRegistry.IVillageTradeHandler { //村人の交換を追加する @Override public void manipulateTradesForVillager(EntityVillager villager, MerchantRecipeList recipeList, Random random) { //アルミニウム一個をエメラルド一個と交換する recipeList.add(new MerchantRecipe(new ItemStack(AluminiumMod.aluminium, 1), new ItemStack(Items.emerald, 1))); //アルミニウム鉱石一個とエメラルド二個とアルミニウム一個を交換する recipeList.add(new MerchantRecipe(new ItemStack(AluminiumMod.oreAluminium, 1),new ItemStack(Items.emerald, 1) , new ItemStack(AluminiumMod.aluminium, 1))); } } AluminiumVillageCreation.java package tutorial.aluminiummod; import cpw.mods.fml.common.registry.VillagerRegistry; import net.minecraft.util.MathHelper; import net.minecraft.world.gen.structure.StructureVillagePieces; import java.util.List; import java.util.Random; public class AluminiumVillageCreation implements VillagerRegistry.IVillageCreationHandler { //その村人がどのくらいの頻度で生成されるかを決める @Override public StructureVillagePieces.PieceWeight getVillagePieceWeight(Random random, int i) { return new StructureVillagePieces.PieceWeight(getComponentClass(), 50, MathHelper.getRandomIntegerInRange(random, i, i + 1)); } //建築物のクラスを渡す @Override public Class ? getComponentClass() { return AluminiumHouse.class; } //建築物生成時に呼ばれる @Override public Object buildComponent(StructureVillagePieces.PieceWeight villagePiece, StructureVillagePieces.Start startPiece, List pieces, Random random, int p1, int p2, int p3, int p4, int p5) { return AluminiumHouse.func_74915_a(startPiece, pieces, random, p1, p2, p3, p4, p5); } } AluminiumHouse.java package tutorial.aluminiummod; import net.minecraft.block.material.Material; import net.minecraft.init.Blocks; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.world.World; import net.minecraft.world.gen.structure.StructureBoundingBox; import net.minecraft.world.gen.structure.StructureComponent; import net.minecraft.world.gen.structure.StructureVillagePieces; import net.minecraftforge.common.ChestGenHooks; import java.util.List; import java.util.Random; import static net.minecraftforge.common.ChestGenHooks.VILLAGE_BLACKSMITH; public class AluminiumHouse extends StructureVillagePieces.Village { private boolean hasMadeChest; public AluminiumHouse() { } public AluminiumHouse(StructureVillagePieces.Start p_i2103_1_, int p_i2103_2_, Random p_i2103_3_, StructureBoundingBox p_i2103_4_, int p_i2103_5_) { super(p_i2103_1_, p_i2103_2_); this.coordBaseMode = p_i2103_5_; this.boundingBox = p_i2103_4_; } //構造物を生成するメソッド public boolean addComponentParts(World p_74875_1_, Random p_74875_2_, StructureBoundingBox p_74875_3_) { if (this.field_143015_k 0) { this.field_143015_k = this.getAverageGroundLevel(p_74875_1_, p_74875_3_); if (this.field_143015_k 0) { return true; } this.boundingBox.offset(0, this.field_143015_k - this.boundingBox.maxY + 6 - 1, 0); } //ブロックを指定した範囲内に敷き詰める this.fillWithBlocks(p_74875_1_, p_74875_3_, 0, 1, 0, 9, 4, 6, Blocks.air, Blocks.air, false); this.fillWithBlocks(p_74875_1_, p_74875_3_, 0, 0, 0, 9, 0, 6, Blocks.cobblestone, Blocks.cobblestone, false); this.fillWithBlocks(p_74875_1_, p_74875_3_, 0, 4, 0, 9, 4, 6, Blocks.cobblestone, Blocks.cobblestone, false); this.fillWithBlocks(p_74875_1_, p_74875_3_, 0, 5, 0, 9, 5, 6, Blocks.stone_slab, Blocks.stone_slab, false); this.fillWithBlocks(p_74875_1_, p_74875_3_, 1, 5, 1, 8, 5, 5, Blocks.air, Blocks.air, false); this.fillWithBlocks(p_74875_1_, p_74875_3_, 1, 1, 0, 2, 3, 0, Blocks.iron_block, Blocks.iron_block, false); this.fillWithBlocks(p_74875_1_, p_74875_3_, 0, 1, 0, 0, 4, 0, Blocks.log, Blocks.log, false); this.fillWithBlocks(p_74875_1_, p_74875_3_, 3, 1, 0, 3, 4, 0, Blocks.log, Blocks.log, false); this.fillWithBlocks(p_74875_1_, p_74875_3_, 0, 1, 6, 0, 4, 6, Blocks.log, Blocks.log, false); //指定した相対座標にブロックを設置する this.placeBlockAtCurrentPosition(p_74875_1_, Blocks.iron_block, 0, 3, 3, 1, p_74875_3_); this.fillWithBlocks(p_74875_1_, p_74875_3_, 3, 1, 2, 3, 3, 2, Blocks.iron_block, Blocks.iron_block, false); this.fillWithBlocks(p_74875_1_, p_74875_3_, 4, 1, 3, 5, 3, 3, Blocks.iron_block, Blocks.iron_block, false); this.fillWithBlocks(p_74875_1_, p_74875_3_, 0, 1, 1, 0, 3, 5, Blocks.iron_block, Blocks.iron_block, false); this.fillWithBlocks(p_74875_1_, p_74875_3_, 1, 1, 6, 5, 3, 6, Blocks.iron_block, Blocks.iron_block, false); this.fillWithBlocks(p_74875_1_, p_74875_3_, 5, 1, 0, 5, 3, 0, Blocks.fence, Blocks.fence, false); this.fillWithBlocks(p_74875_1_, p_74875_3_, 9, 1, 0, 9, 3, 0, Blocks.fence, Blocks.fence, false); this.fillWithBlocks(p_74875_1_, p_74875_3_, 6, 1, 4, 9, 4, 6, Blocks.cobblestone, Blocks.cobblestone, false); this.placeBlockAtCurrentPosition(p_74875_1_, Blocks.flowing_lava, 0, 7, 1, 5, p_74875_3_); this.placeBlockAtCurrentPosition(p_74875_1_, Blocks.flowing_lava, 0, 8, 1, 5, p_74875_3_); this.placeBlockAtCurrentPosition(p_74875_1_, Blocks.iron_bars, 0, 9, 2, 5, p_74875_3_); this.placeBlockAtCurrentPosition(p_74875_1_, Blocks.iron_bars, 0, 9, 2, 4, p_74875_3_); this.fillWithBlocks(p_74875_1_, p_74875_3_, 7, 2, 4, 8, 2, 5, Blocks.air, Blocks.air, false); this.placeBlockAtCurrentPosition(p_74875_1_, Blocks.cobblestone, 0, 6, 1, 3, p_74875_3_); this.placeBlockAtCurrentPosition(p_74875_1_, Blocks.furnace, 0, 6, 2, 3, p_74875_3_); this.placeBlockAtCurrentPosition(p_74875_1_, Blocks.furnace, 0, 6, 3, 3, p_74875_3_); this.placeBlockAtCurrentPosition(p_74875_1_, Blocks.double_stone_slab, 0, 8, 1, 1, p_74875_3_); this.placeBlockAtCurrentPosition(p_74875_1_, Blocks.glass_pane, 0, 0, 2, 2, p_74875_3_); this.placeBlockAtCurrentPosition(p_74875_1_, Blocks.glass_pane, 0, 0, 2, 4, p_74875_3_); this.placeBlockAtCurrentPosition(p_74875_1_, Blocks.glass_pane, 0, 2, 2, 6, p_74875_3_); this.placeBlockAtCurrentPosition(p_74875_1_, Blocks.glass_pane, 0, 4, 2, 6, p_74875_3_); this.placeBlockAtCurrentPosition(p_74875_1_, Blocks.fence, 0, 2, 1, 4, p_74875_3_); this.placeBlockAtCurrentPosition(p_74875_1_, Blocks.wooden_pressure_plate, 0, 2, 2, 4, p_74875_3_); this.placeBlockAtCurrentPosition(p_74875_1_, Blocks.iron_block, 0, 1, 1, 5, p_74875_3_); this.placeBlockAtCurrentPosition(p_74875_1_, Blocks.stone_stairs, this.getMetadataWithOffset(Blocks.stone_stairs, 3), 2, 1, 5, p_74875_3_); this.placeBlockAtCurrentPosition(p_74875_1_, Blocks.stone_stairs, this.getMetadataWithOffset(Blocks.stone_stairs, 1), 1, 1, 4, p_74875_3_); int i; int j; if (!this.hasMadeChest) { i = this.getYWithOffset(1); j = this.getXWithOffset(5, 5); int k = this.getZWithOffset(5, 5); if (p_74875_3_.isVecInside(j, i, k)) { this.hasMadeChest = true; this.generateStructureChestContents(p_74875_1_, p_74875_3_, p_74875_2_, 5, 1, 5, ChestGenHooks.getItems(VILLAGE_BLACKSMITH, p_74875_2_), ChestGenHooks.getCount(VILLAGE_BLACKSMITH, p_74875_2_)); } } for (i = 6; i = 8; ++i) { if (this.getBlockAtCurrentPosition(p_74875_1_, i, 0, -1, p_74875_3_).getMaterial() == Material.air this.getBlockAtCurrentPosition(p_74875_1_, i, -1, -1, p_74875_3_).getMaterial() != Material.air) { this.placeBlockAtCurrentPosition(p_74875_1_, Blocks.stone_stairs, this.getMetadataWithOffset(Blocks.stone_stairs, 3), i, 0, -1, p_74875_3_); } } for (i = 0; i 7; ++i) { for (j = 0; j 10; ++j) { this.clearCurrentPositionBlocksUpwards(p_74875_1_, j, 6, i, p_74875_3_); this.func_151554_b(p_74875_1_, Blocks.cobblestone, 0, j, -1, i, p_74875_3_); } } this.spawnVillagers(p_74875_1_, p_74875_3_, 7, 1, 1, 1); return true; } //家に生成させる村人のIDを渡す protected int getVillagerType(int p_74888_1_) { return AluminiumMod.metalVillagerID; } //以下 StructureVillagePieces.Village.House2よりコピペ public static AluminiumHouse func_74915_a(StructureVillagePieces.Start p_74915_0_, List p_74915_1_, Random p_74915_2_, int p_74915_3_, int p_74915_4_, int p_74915_5_, int p_74915_6_, int p_74915_7_) { StructureBoundingBox structureboundingbox = StructureBoundingBox.getComponentToAddBoundingBox(p_74915_3_, p_74915_4_, p_74915_5_, 0, 0, 0, 10, 6, 7, p_74915_6_); return canVillageGoDeeper(structureboundingbox) StructureComponent.findIntersecting(p_74915_1_, structureboundingbox) == null ? new AluminiumHouse(p_74915_0_, p_74915_7_, p_74915_2_, structureboundingbox, p_74915_6_) null; } protected void func_143012_a(NBTTagCompound p_143012_1_) { super.func_143012_a(p_143012_1_); p_143012_1_.setBoolean("Chest", this.hasMadeChest); } protected void func_143011_b(NBTTagCompound p_143011_1_) { super.func_143011_b(p_143011_1_); this.hasMadeChest = p_143011_1_.getBoolean("Chest"); } } 解説 VillagerRegistry void registerVillagerId(int id) 村人のIDを登録するメソッド。 コメントにある通り、村人IDは0~4が既存の村人として設定されているため、それ以外の数値を与える必要がある。 競合を防ぐためには、config等で変更できるようにするとよい。 また、IDはいろいろなところで使うためstatic finalな定数に格納すると便利。 void registerVillageTradeHandler(int villagerId, IVillageTradeHandler handler) 指定したIDの村人に特定の交換を登録するメソッド。 なお、すべての村人(MOD追加されたもの含む)に特定の交換を実装するなら、以下のようなコードが効率的。 (VillagerRegistry.instance().registerVillageTradeHandler(metalVillagerID, new AluminiumTrade());の部分を以下のコードに書き換える。) for(Integer integer VillagerRegistry.getRegisteredVillagers()){ VillagerRegistry.instance().registerVillageTradeHandler(integer, new AluminiumTrade()); } void registerVillagerSkin(int villagerId, ResourceLocation villagerSkin) 指定したIDの村人にスキンを追加するメソッド。 void registerVillageCreationHandler(IVillageCreationHandler handler) 村人の家と村人の生成を登録するメソッド。 MapGenStructureIO ワールドへの構造物生成を管理するクラス。 void registerStructure(Class p_143034_0_, String p_143034_1_) void func_143031_a(Class p_143031_0_, String p_143031_1_) どちらも構造物を登録するメソッド。 registerStructureを先に呼ぶ。 MerchantRecipe これを使ったインスタンスをIVillageTradeHandlerを実装したクラスのmanipulateTradesForVillagerで、第二引数recipeListに追加して村人の交換を管理する。 コンストラクター(ItemStack p_i1942_1_, ItemStack p_i1942_2_) 村人の交換を実装するメソッド。第一引数に渡すもの、第二引数に受け取るものを渡す。 下のコンストラクターを用いてnew MerchantRecipe(p_i1942_1_, (ItemStack)null, p_i1942_2_);と記述するのと同じ意味。 コンストラクター(ItemStack p_i1941_1_, ItemStack p_i1941_2_, ItemStack p_i1941_3_) 村人の交換を実装するメソッド。第一引数・第二引数に渡すもの、第三引数に受け取るものを渡す。 StructureComponent StructureVillagePiecesはこのクラスを継承している。 void fillWithBlocks(World worldObj, StructureBoundingBox structBB, int minX, int minY, int minZ, int maxX, int maxY, int maxZ , Block placeBlock, Block replaceBlock, boolean alwaysreplace) x,y,z(structBBで指定された直方体内の相対座標)座標にブロックを敷き詰める。 min**は始点、max**は終点を示している。また、placeBlockは先に設置するブロック、replaceBlockは後に設置するブロック、(基本同じ物を渡す)、alwaysreplaceはreplaceBlockを使用するか否かを それぞれ示している。 コメント この項目に関する質問などをどうぞ。 名前
https://w.atwiki.jp/mfiler2tutorial/pages/3.html
更新履歴 取得中です。