約 3,588,559 件
https://w.atwiki.jp/mi_ic2/pages/139.html
環境値 バージョン: industrialcraft-2-2.2.828-experimental 概要 支柱は、保水・肥沃・通気といった植物の成長に影響する項目を持っている。これを本サイトでは環境値と呼ぶ。環境値は保水環境値(Humidity)・肥沃環境値(Nutrients)・通気環境値(AirQuality)に分かれている。 各環境値のコードは以下にある。 保水環境値 updateHumidity 肥沃環境値 updateNutrients 通気環境値 updateAirQuality 環境値は周囲のブロックや設置場所などの環境の他、農薬によっても変動する。 保水環境値 計算式は以下の様なものである。 保水環境値 =保水バイオームボーナス + 耕土湿潤ボーナス + 保水農薬値ボーナス耕土湿潤ボーナス = 耕土が湿っていたら(メタデータが7以上)2、そうでなければ0保水農薬値ボーナス = (保水農薬値が5以上で2、そうでなければ0) + (保水農薬値 + 21) / 25 耕土湿潤ボーナスはまず与えられる。なぜなら耕土が乾燥しきると支柱が破壊されるため、耕土を濡らすことは必須だからである。 保水農薬値の後半部分は1から肥沃環境値に1のボーナスを与え、26から2与える。上限はない。 肥沃環境値 計算式は以下の様なものである。 肥沃環境値 =肥沃バイオームボーナス+耕土下土増長ボーナス+肥沃農薬値ボーナス耕土下土増長ボーナス= 耕土の直下何個まで土が存在するか。ただし3個が上限肥沃農薬値ボーナス= (肥沃農薬値 + 19) / 20 耕土の下に土ブロックを設置すると、土1個につき肥沃環境値は1上昇する。最大3個まで認識される。土は連続していなければならなず、支柱・耕土・土・石・土のようにすると1個分として認識される。 肥沃農薬値は1から肥沃環境値に1のボーナスを与え、21から2与える。上限はない。 通気環境値 計算式は以下の様なものである。 通気環境値 =高度ボーナス+隣接ブロックボーナス+直射日光ボーナス高度ボーナス = (Y座標 - 64) / 15 ただし0~4の範囲に丸められる隣接ブロックボーナス = (8 - (同じ高度で8隣接(斜め含む)のうち、普通立方体(isBlockNormalCubeDefault)または支柱であるブロックの個数)) / 2直射日光ボーナス = 支柱から天空が見える(canBlockSeeTheSky)場合に2、そうでなければ0 隣接する8つのブロックが1個埋まると1のペナルティ、その後2個埋まるごとに1のペナルティを生む。 Y座標 高度ボーナス ~78 0 79~93 1 94~108 2 109~123 3 124~ 4 バイオームボーナス バイオームボーナスは保水バイオームボーナスと肥沃バイオームボーナスに分かれている。Minecraftにおいて、バイオームはいくつかのバイオームタイプを持つが、ボーナスはバイオームタイプごとに登録されている。 バイオームボーナスはそのバイオームが持つ各バイオームタイプのボーナスの合計となっているが、バイオームボーナスは0未満にはならず0で止まる。 以下にバイオームタイプごとのボーナスを載せる。ただし、-はそれが登録されていないことを表す。登録されていないものは0と等価である。 バイオームタイプ 保水 肥沃 JUNGLE - 10 SWAMP - 10 MUSHROOM - 5 FOREST - 5 RIVER - 2 PLAINS - 0 SAVANNA - -2 HILLS - -5 MOUNTAIN - -5 WASTELAND - -8 END - -10 NETHER - -10 DEAD - -10 それ以外 - - 見てのとおり、なぜか保水にはボーナスが設定されていない。また、悪影響を及ぼすバイオームタイプの方が多い。 他のMODで追加されたバイオームも、バイオームタイプが登録されていればバイオームボーナスを生じる。 バニラバイオームのボーナス一覧を載せる。 バイオーム 保水 肥沃 Ocean 0 0 Plains 0 0 Desert 0 0 Extreme Hills 0 0 Forest 0 5 Taiga 0 5 TaigaHills 0 0 Swampland 0 10 River 0 2 FrozenOcean 0 0 FrozenRiver 0 2 Ice Plains 0 0 Ice Mountains 0 0 Beach 0 0 DesertHills 0 0 Jungle 0 10 JungleHills 0 5 ForestHills 0 0 Sky 0 0 Hell 0 0 MushroomIsland 0 5 Extreme Hills Edge 0 0 MushroomIslandShore 0 5 JungleEdge 0 15 Deep Ocean 0 0 Stone Beach 0 0 Cold Beach 0 0 Birch Forest 0 5 Birch Forest Hills 0 0 Roofed Forest 0 5 Cold Taiga 0 5 Cold Taiga Hills 0 0 Mega Taiga 0 5 Mega Taiga Hills 0 0 Extreme Hills+ 0 0 Savanna 0 0 Savanna Plateau 0 0 Mesa 0 0 Mesa Plateau F 0 0 Mesa Plateau 0 0 ジャングルや湿地はボーナスが高い。特筆すべきは、JungleEdgeの15であろう。しかしJungleEdgeの面積は限られるため、15のボーナスを安定して得るのは難しいだろう。 一部のバイオームタイプは非常に重いペナルティを有するが、0未満にはならないため実際には平原と同一であり無視してよい。 総評 耕土湿潤により常時+2、土を3個増長すれば+3、Y124以上なら+4、屋外で+2、一部バイオームで概ね+5から+10得られる。 効率を求めるとバイオーム限定となるのが厳しいが、森でも+5得られるので耕土湿潤と土3とY124も合わせて+14は多層型農場にしても比較的楽に得られる。沼地やジャングルに作るとさらに+5、頑張ってJungleEdgeに作ると+10が追加される。
https://w.atwiki.jp/indust-rial/pages/6.html
導入Mod・推奨スペック (サーバースペックも入ってます) 導入Mod industrialcraft2-experimental buildcraft Cutall Mineall 以上。 サーバーPCのスペック IntelCorei7 OC4.2GHz 3970X ExtrimeEdition RAM PC3-12800 32GBSnglechannel VRAM GDDR5 1GB GPU Nvidia QuadoroFX4000 ストレージ(サーバー格納部) 128GB SSD ぐらいですw快適だとイイナw
https://w.atwiki.jp/mi_ic2/pages/111.html
PluginCrops(646) バージョン: industrialcraft-2-2.2.719-experimental 概要 収穫物の数を計算するはさみ 旧版はTileEntityCropクラスごと置換しているので、IC2Expのバージョンアップによって動かない可能性が少しある。だが、当時は517付近のバージョンから始まる農業革命到来前であり、Crop周辺の仕様が変わることはほぼなかったため、そこまで問題視していなかった。 しかし、最近は頻繁に大規模な改革が起こっており、クラスファイルを直接置換するだけではどうしようもないというところまで来ている。これを解決するには、JavaASMを触り発見した問題点(及び機能拡張)を一つ一つ直す必要がある。 機能 旧版が持っている深刻なバグや謎挙動の矯正機能の移植 致命的なバグの例: 支柱に矢でセーブデータが読み込めなくなる問題は、Forge側の更新により今後は気にしなくてもよくなった。 (この後本記事群から公開するかもしれない)作物追加アドオンのためのAPI 折角作物がID競合地獄から解放されたので コンフィグファイルにより修正するバグを選択可能にしたい リリース もしリンク切れしてたら、この記事の下側の添付ファイルリストから落とせるかもしれません。 plugincrops-732-1.3 2015/6/8 対応Ver: ic2exp 開発環境: 732 推奨環境: 732 必要環境: バージョンがずれると問題が起きる可能性あり その他前バージョンと同一 ダウンロード: jar dev src 機能・変更: バージョン概要 ModIdはキャメルケースが正しいっぽいので、それに変えた。旧デバッガーアイテムが消滅します。 最初のCoreMod入りのバージョンであり、バグったら色々やばいことになるかもしれないので、バックアップ推奨。 非開発版(難読化版)環境で、サーバー&クライアントにて(一応)動作確認を行いました。 旧PluginCropsにあったIC2Expバグ矯正用のCoreModの移植。 ON/OFFが切り替え可能で、コンフィグファイルPluginCropsCoreMod.cfgが生成されます。 CoreModの機能一覧(型 プロパティ名=デフォルト値) B bugsOfAttemptCrossing=true 交配時にランダムな植物種がNGスポットに入るバグ 交配レートから作物種を選択するアルゴリズムに関するバグ B calculationOfPicking=true 種袋採取時にドロップ率が収穫後のサイズに依存するバグ B directivityOfAirQuality=true 通気の判定が方角依存になるバグ B directivityOfWeed=true 雑草の繁殖が方角に依存するバグ B growthBoostOfWartsIsDisabled=true 必然変異が発生しない現象 B growthDurationOfStickreed=true 樹液アシの成長が速すぎるバグ B renderingApis=true レンダリングAPI B under24GrowthOfWeed=true 雑草もGrowth24ないと雑草属性状態にならないバグ B weedExIsNotSaved=true チャンク読み込み時にWeedEXの使用状況がリセットされるバグ レンダリングAPI 描画を井形だけでなく×形にできる。 コンフィグファイルから、英名か属性群で指定可能。 S patternsAttribute ×形にする属性群の正規表現 S patternsDisplayName ×形にする英名の正規表現 S patternsNgAttribute ×形にしない属性群の正規表現 S patternsNgDisplayName ×形にしない英名の正規表現 デフォルトでは、PluginCropsの作者が独断と偏見で×形の方がなんかよさそうなやつを×形にしてあります。 配布しているAPIにより、自作のModで自由にレンダリングメソッドを変更可能。 CropCardごとにレンダラーを指定したい! → plugincrops.api.client.ApiCoreModRendererBlockCrop#tableCropCardToHandlerRendering レンダリングハンドラーを指定したい! → plugincrops.api.client.ApiCoreModRendererBlockCrop#handlerRenderings このリストの前に有る順に呼び出されるので、新たに登録する場合は先頭に追加するのが良いだろう。 デバッグアイテムのバグ修正。 IC2APIを732に更新。 ×形レンダリングが適用され、方角依存が修正され、24Growthバグが修正された雑草。 未解決事項: plugincrops-720-1.2 2015/5/31 対応Ver: 前バージョンと同一 ダウンロード: jar dev src 機能: バニラのファイヤーチャージの名称がこのModで上書きされる問題を修正 新たなアイテムを追加 【鉱石辞書の看板】 使用すると登録されているすべての鉱石辞書と登録されているアイテムを表示する。 数が多くて見切れる場合はコンソールからコピーすると全部見れる。 アイテムの説明文を.langファイルに移行 未解決事項: 【鉱石辞書の看板】 アイテムの親Modの特定 ファイルにDump アイテムの説明欄が日本語設定でないと説明文が出てこない plugincrops-720-1.1 2015/5/16 対応Ver: 前バージョンと同一 ダウンロード: jar dev src 機能: デバッグ用アイテムに名前を設定 文字化けを解決 バケツが負のXY座標を持つ地域で利用できなかった問題を修正 デバッグ用アイテムの追加 GGR値をインクリメント/デクリメントする粉 APIを使って設定している。 ScanLevelもいじれる 空中に広大な農業用地を設置できる 未解決事項: plugincrops-646-1.0 2015/5/16 対応Ver: minecraft 1.7.10 forge 開発環境: 10.13.3.1403 推奨環境: 10.13.0.1200以上 必要環境: 無指定 ic2exp 開発環境: 720 推奨環境: 720 必要環境: 720近辺の±50程度までなら互換性がありそう ダウンロード: jar dev src 機能: クリエイティブタブの追加 変色した本の色のタブが増えて、そこに全追加アイテムが入っている。 デバッグ用アイテムの追加 支柱の状態を見るスキャナ Block・TileEntity・ICropTile・CropCard・ITileEntity×CropCardで決定されるパラメータを表示。 周辺を一気に耕すクワ 通常のクワと同じ仕様で、広範囲に耕作の処理を行う。 赤いクワは、元々真上が空気だったらという処理が真上が透過ブロックだったらという処理にしてある。 木や植物系のブロックを破壊する斧 使用地点の周囲のバニラブロック:原木・葉・雑草・花などを消去する。 周辺の農場に水源を設置するバケツ 周囲に、XZ座標が共にmod 8 == 3であり耕土の上4マス分が空気である場所を見つけたら、そこに水源と光源を建てる。 この座標ならチャンク境界で荒地になる問題も起こらないはず・・・ 広範囲のMobを殺す剣 着火なし・破壊なし爆発を起こす。 放火だけをする火薬 着火あり・破壊なし爆発を起こす。 Mobも死ぬ。 ただの大爆発する爆弾 着火なし・破壊あり爆発を起こす。 Mobも死ぬ。 横一面に同じブロックを並べるレンガ 右クリックした物体が横一面に広がる。 本来そのブロックを置けない場所にも問答無用で設置する。 TileEntityを持っているブロックは増殖しない。 交配が成功するまで試行する物体 IC2の非APIメソッドを呼び出して交配を連続で試行する。 (試行にミスした回数+1)*256tickがかかったことになる。 100ミスしたら中断する。 こちらは交配で生まれたGGR値も表示する。 10000回交配した結果を出す物体 IC2の非APIメソッドを呼び出して10000回交配を試行する。 結果出てきた作物種のランキングを発表する。 支柱に一気に時間を流す砂時計 リーチと回数が合計16種類のパターンがあるアイテムである。 NBTを設定した状態の物をコマンドで出せば何でも設定できる。 右クリック地点からY±1、XZ±reachの範囲の支柱のcroptickを連続で呼び出す。 雑草はものすごい勢いで生える。 支柱の状態をコピー・ペーストする矢筒 支柱の作物種・GGR・Scan・Sizeを保持しておける。 このアイテムはクリエイティブタブに入っている全種のIC2種袋を登録する。 GGRは数パターン用意してある。 導入されているCropの一覧を表示する看板 どこで使用しても同じ結果になる。 導入されているCrop同士の交配レートを出力する額縁 交配レートの計算には、(メソッドの宣言上は)支柱ブロックが必要である。支柱ブロックを右クリックしなければならない。 TileEntityCrop#calculateRatioForを直接呼び出している。 これはTileEntityCrop#attemptCrossing()で使われるメソッドである。 作物の株を傷つけずに収穫物を得るはさみ 収穫時に得られる収穫物の数をシミュレートする。 作物の株を傷つけずに種袋を得る種 破壊時に得られる種袋の数をシミュレートする。 一応IC2Expは必須ではないので、単体で動作する。 IC2Expのバージョン変化に強いはず。 APIにCrop関連以外の更新が来ても互換性を維持。 一応マルチサーバーでも動く・・・かも。 まだCoremodではない。 未解決事項: 盛大に文字化けしている 非devでバケツが機能しない アイテム名がまだ未指定 全ての説明文が日本語のみ 説明文の外部化 Coremod部分の実装 GGRをインクリメント/デクリメントしていじれるデバッグアイテム 技術情報
https://w.atwiki.jp/mi_ic2/pages/123.html
CropCardクラスの仕様 バージョン: industrialcraft-2-2.2.720-experimental 概要 ここではic2.api.crops.CropCardの仕様を見ていく。APIなのでソースコードが公開されており大量のコメントが書かれているが、ここではそれらのJavaDocコメント文を全力で無視して各メソッドの品評を行う。コメントはすべて英文なのでJavaDoc出力してGoogleChromeで開くとよい。 CropCardこそが作物種を表すクラスである。Crop追加MODを作成するにあたって、最も重要で基本的なAPIクラスである。 メソッド new() コンストラクタ。modidにLoader.instance().activeModContainer()のgetModId()を突っ込んでいる。 abstract String name() 内部名を返す。 redMushroom のように、先頭が小文字のキャメルケースの半角英数を使う。別に全角文字を入れても大丈夫な気もするが、通常は変数名とかの形でJavaコードにも出現すると思われるので、変数名と同化させるのがよいだろう。 農業革命中に仕様が表示名から内部名へと変わった。それゆえ、古いModでは RedMushroom のように英名が返されている。現在はこのメソッドは内部名を返すことになっている。 String owner() この作物種を追加したModのmodidを返す。オーバーライドしてない場合、コンストラクタで取得されたスレッドから判断されたmodidが使われる。 String displayName() 表示名を返す。これは tile.dirt.name のような形式の翻訳キーで返す。日本語などのローカライズされた名前では返さない(返しても動作は同じはず)。 標準の動作は内部名をそのまま返すというもの。というのも、name()は古い仕様では表示名を返していた。この動作だと翻訳しにくいので是非オーバーライドしよう。 コメントを見ると、owner() + .crop. + name()のような内容にオーバーライドしてくださいと言っている。 tile.dirt.name 側に合わせると、さしずめ crop. + owner() + . + name() + .name だろうか? String discoveredBy() 発見者の名前を書く。デフォルトは unknown 。実在の植物や創作植物の場合はMODのクリエイターの名前を書くのがいいだろう。その他に、バニラから持ってきた物は Notch のように作ったと思われる人物を記述する。 String desc(int i) デフォルトの動作は属性を2列に分けて表示している。書き換えると面白いメッセージを出せるが、表示にしかかかわらないはずなので書き換えなくても特にゲームに影響はない。栽培のノウハウとか書いてみても面白いかも?? 種解析機で表示できる。 int getrootslength(ICropTile crop) 根の長さを返す。デフォルトは1。この長さの分だけ耕土下ブロックの射程が伸びる。 しかし、値の対応が結構謎。以下に対応を載せる。 getrootslength 意味 植物種の例 0 意味をなさない 1 意味をなさない デフォルト 2 意味をなさない 3 耕土の下1ブロックに反応 フェルー・オーレリア 4 耕土の下2ブロックに反応 (ネザー/テラワート) ワート系統はtickメソッドを見るに4でなければならなそうだが、1になっている。 abstractint tier() 植物種のTier(レア度)を返す。解説には1~16までの範囲で指定しろと書いてある。0は雑草である。 限界突破してTierが17以上になったものを超16植物と呼ぶことにしておく。 価値が高く、力強い植物種はこの値が高い。ちなみに最高はIC2のオーレリアで8、GregTechのダイヤアシで12である。 abstractint stat(int n) 植物の交配上のステータス。交配時のレート計算に使われる。0から4までの5通りの呼ばれ方があり、それぞれ返す値が次のような意味づけになっている。 0 Chemistry 科学的(工業的には化学的な使い方をされる) 1 Consumable 消費可能(食物・ポーションなど) 2 Defensive 外敵に対する特殊な防御を持っている(棘や毒など) 3 Colorful カラフルや美しい植物。染料に使いやすい。 4 Weed 雑草に近い(疎まれる)植物は高い。必然的に高Tierほど下がるだろう。 abstractString[] attributes() 植物種の属性を返す。属性の例はこちらの記事にある。new String[] { Leaves , }のようにその場でインスタンスを生成してもよいが、交配の処理場なかなか重くなりそうなのでコンストラクタで生成するのがよいだろう。 abstractint maxSize() 最大成長サイズを返す。様々な部分がこれを参照する。 @SideOnly(Side.CLIENT) void registerSprites(IIconRegister iconRegister) この植物種が使うテクスチャのリソースを登録する。描画系統で特別なことをしない限り、書き換える必要はない・・・・・・と一見思われるが、このメソッドはオーバーライドした方が良い。 このままではテクスチャファイルのドメインがic2固定なので内部名の重複によってリソースの競合が起こるのだ。修正するにはAPIのコードをまるまるコピーし、 textures[i - 1] = iconRegister.registerIcon( ic2 crop/blockCrop. + name() + . + i); の行を textures[i - 1] = iconRegister.registerIcon(owner().toLowerCase() + crop/blockCrop. + name() + . + i); にすればよい。 @SideOnly(Side.CLIENT) IIcon getSprite(ICropTile crop) TileEntityCropが与えられたときにアイコンを返すメソッド。引数がint sizeではなくITileCropなおかげで様々な条件によってテクスチャを切り替えられる。 ただし、めまぐるしく変えようとしても、サーバーからクライアントに移動させる周期とクライアントが再描画する周期があるのでそこの2か所を突破しなければうまくはいかない。せいぜいGGR値によって変えるまでだろう・・・ int growthDuration(ICropTile crop) 最大成長経験値を返す。デフォルトとはTier*200。成長サイズが1段階進むのにかかるポイントである。単位は複雑な単位。 abstractboolean canGrow(ICropTile crop) 成長可能かおよび、設置可能かおよび、交配によって出現可能かを返す。 引数の成長サイズが1以上なら成長時。0で、かつupgraded(リフレクションを使わなければ取得できない)なら交配時、そうでないなら種袋やベースシードでの設置時。 なお、成長サイズ=最大成長サイズの場合はfalseを返すようにしなければ成長が際限なく進みバグる。 int weightInfluences(ICropTile crop, float humidity, float nutrients, float air) デフォルトの動作は3つのfloatを足したものをintにして返す。 これはどのように改変すればよいのかというと、以下はアシのオーバーライドである。 (int) ((double) humidity * 1.2D + (double) nutrients + (double) air * 0.8D) これは保水環境値に大きな荷重がかかっていることを示している。 boolean canCross(ICropTile crop) 交配に参加可能かどうかを返す。デフォルトでは、成長サイズが3以上のときにtrueとなっている。 IC2の中ではオーバーライドしている者は居ない。 最大成長サイズが2以下である場合、これをオーバーライドすること!その植物種は交配に参加できなくなってしまう。 boolean rightclick(ICropTile crop, EntityPlayer player) 右クリック時のイベント。デフォルトの動作はcrop.harvest(true)を呼び出す。 ヴェノミリアはplayerがスニークじゃないなら毒に犯すという処理が挟まれている。どうやら引数のplayerは非nullのようだ。 そのままreturn trueなどすると、収穫不能となる。 abstractint getOptimalHavestSize(ICropTile crop) Cropハーベスターに種解析機を突っ込んだ時にベストな収穫時期として判断されるらしい。通常はreturn maxSize();などと書いておけばよいだろう。 abstractboolean canBeHarvested(ICropTile crop) 右クリックで収穫可能かどうかを返す。このメソッドでは、普通は成長サイズが適切かどうかを判断する処理が入っている。 多くの植物種では最大成長サイズの場合にのみ収穫可能であるので、return crop.getSize() == maxSize();としておけば困らないだろう。これで困るような特殊な植物種には、アシやヴェノミリアなどがある。 float dropGainChance() 収穫物の収穫量にかかわる値である。デフォルトでは0.95^Tierを返している。Tierが高いほど収穫物が出にくいのだ。 フェルーはsuperを半分にしたものを返すようにオーバーライドしている。ネザーワートは2を返している。金属が収穫できるような強力な植物種は、倍率がかかっていることが多い。 abstractItemStack getGain(ICropTile crop) 収穫物を返す。1種類しか返せないが、スイカはIC2.random.nextIntを呼び出してランダムにすることでうまくメロンブロックとメロンの切り身を返している。 byte getSizeAfterHarvest(ICropTile crop) 収穫後の成長サイズ。デフォルトは1。植物種によってまちまちとなるだろう。 boolean leftclick(ICropTile crop, EntityPlayer player) 左クリック時のイベント。デフォルトはreturn crop.pick(true);。 ヴェノミリアはこれをオーバーライドしてsuperのこれを実行する前にplayerを毒に犯している。 雑草はreturn false;することで左クリックで除草できなくしている。 float dropSeedChance(ICropTile crop) 種袋のドロップ率に影響する。このメソッドは面倒なことをしているので書き換えない方が無難だが、高Tierになるほど種袋が取りにくくなるので、救済したい場合は書き換えるとよい。 以下のことを行っている。 収穫時の成長サイズが1なら0を返す 収穫時の成長サイズが2なら0.5*0.8^Tierを返す 収穫時の成長サイズがそれ以外なら0.25*0.8^Tierを返す ItemStack getSeeds(ICropTile crop) 種袋に当たるアイテムを返す。crop.generateSeedsを叩くことでデフォルトの種袋を取得できる。 小麦などがオーバーライドしており、非常に低いGGR値では単なる小麦の種を落とすようにしている。 void onNeighbourChange(ICropTile crop) 近隣のブロックが更新されたときに呼び出されるイベントである。バニラIC2に存在する植物種では使われていない。 int emitRedstone(ICropTile crop) 赤石信号を出力するかどうか。デフォルトは0。 赤石小麦は成長サイズ7で15の赤石信号を出力する。 void onBlockDestroyed(ICropTile crop) 支柱の破壊時のイベント。バニラIC2に存在する植物種では使われていない。 int getEmittedLight(ICropTile crop) 発光する植物の場合、その強度。 赤石小麦は成長サイズ7で7の照明光を出力する。 boolean onEntityCollision(ICropTile crop, Entity entity) エンティティが接触した際に呼ばれるイベント。trueを返した場合、このあと踏み荒らしのイベントを発火する。デフォルトではエンティティがEntityLivingBaseであり疾走状態の時にtrueを返している。 void tick(ICropTile crop) 256MinecraftTickに1回、即ちCropTickごとに呼ばれるメソッド。 デフォルトでは何もしないが、ネザーワートとテラワートでは必然変異に関する処置が書かれている。 boolean isWeed(ICropTile crop) 雑草属性状態であるかどうかを返す。デフォルトは、成長サイズが2以上かつ植物種が雑草と等しいかGrowthが24以上である場合にtrue。 ヴェノミリアはこれを成長サイズが5以上かつGrowthが8以上であるときとしている。 @Deprecatedfinalint getId() 今は非推奨となった整数IDによる識別番号である。指定しなくとも自動的に番号が振られる。 @SideOnly(Side.CLIENT)protectedIIcon textures[]; この変数はregisterSpritesやgetSpriteのデフォルト実装が使っている。protectedなので、サブクラスから参照可能である。
https://w.atwiki.jp/elepro/pages/13.html
Minecraft@ElePro Server MinecraftのEleProサーバーについての情報Wikiです。 お知らせ等はココに載せていくので、思いついたときにでも確認をお願いします。 お知らせ 2012/7/21 工業化 科学Mod導入版サーバー稼働。 Modは以下のサイトを参考に導入してください。 サーバーにログインするには、すべてのModを導入していないと、はじかれてしまうので注意してください。 導入Mod Minecraft Forge 3.3.8.164 IndustrialCraft² v1.97 BuildCraft 2.2.14 RedPower 2.0pr5b2
https://w.atwiki.jp/chikinkaisetu/pages/15.html
Ic2の開発チームに、gregtechの作者(GregoriusT)が加わり、難易度が上昇、テクスチャも工業らしく変わったもの。1.7.10では、もはやgregtechの前提MODと化している。
https://w.atwiki.jp/mi_ic2/pages/134.html
TileEntityCrop 私はこのコードについて真に驚くべき解説ができるが、ここに記すには@Wikiの制限容量が少なすぎる。 バージョン: industrialcraft-2-2.2.828-experimental package ic2.core.crop; import ic2.api.crops.BaseSeed; import ic2.api.crops.CropCard; import ic2.api.crops.Crops; import ic2.api.crops.ICropTile; import ic2.api.network.INetworkDataProvider; import ic2.api.network.INetworkUpdateListener; import ic2.core.IC2; import ic2.core.Ic2Items; import ic2.core.block.machine.tileentity.TileEntityCropmatron; import ic2.core.item.ItemCropSeed; import ic2.core.network.NetworkManager; import ic2.core.util.StackUtil; import ic2.core.util.Util; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Set; import net.minecraft.block.Block; import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Blocks; import net.minecraft.init.Items; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.ChunkCoordinates; import net.minecraft.util.StatCollector; import net.minecraft.world.EnumSkyBlock; import net.minecraft.world.World; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.oredict.OreDictionary; public class TileEntityCrop extends TileEntity implements INetworkDataProvider, INetworkUpdateListener, ICropTile { public byte humidity = -1; public byte nutrients = -1; public byte airQuality = -1; private static final boolean debug = false; private CropCard crop = null; public int size = 0; public int statGrowth = 0; public int statGain = 0; public int statResistance = 0; public int scanLevel = 0; public NBTTagCompound customData = new NBTTagCompound(); public int nutrientStorage = 0; public int waterStorage = 0; public int exStorage = 0; public int growthPoints = 0; public boolean upgraded = false; public char ticker; public boolean dirty; public static int tickRate = 256; public int weedlevel; public int Infestedlevel; public TileEntityCrop() { this.ticker = (char)IC2.random.nextInt(tickRate); this.dirty = true; this.weedlevel = 0; this.Infestedlevel = 0; } public void readFromNBT(NBTTagCompound nbt) { super.readFromNBT(nbt); if (nbt.hasKey( cropOwner ) nbt.hasKey( cropName )) { this.crop = Crops.instance.getCropCard(nbt.getString( cropOwner ), nbt.getString( cropName )); } else if (nbt.hasKey( cropid )) { this.crop = IC2Crops.getCropFromId(nbt.getShort( cropid )); } this.size = nbt.getByte( size ); this.statGrowth = nbt.getByte( statGrowth ); this.statGain = nbt.getByte( statGain ); this.statResistance = nbt.getByte( statResistance ); if (nbt.hasKey( data0 )) { for(int x = 0; x 16; ++x) { this.customData.setShort( legacy + x, nbt.getShort( data + x)); } } else if (nbt.hasKey( customData )) { this.customData = nbt.getCompoundTag( customData ); } this.growthPoints = nbt.getInteger( growthPoints ); this.nutrientStorage = nbt.getInteger( nutrientStorage ); this.waterStorage = nbt.getInteger( waterStorage ); this.exStorage = nbt.getInteger( exStorage ); this.upgraded = nbt.getBoolean( upgraded ); this.scanLevel = nbt.getByte( scanLevel ); this.weedlevel = nbt.getInteger( weedlevel ); this.Infestedlevel = nbt.getInteger( Infestedlevel ); } public void writeToNBT(NBTTagCompound nbt) { super.writeToNBT(nbt); if (this.crop != null) { nbt.setString( cropOwner , this.crop.owner()); nbt.setString( cropName , this.crop.name()); } nbt.setByte( size , (byte)this.size); nbt.setByte( statGrowth , (byte)this.statGrowth); nbt.setByte( statGain , (byte)this.statGain); nbt.setByte( statResistance , (byte)this.statResistance); nbt.setTag( customData , this.customData); nbt.setInteger( growthPoints , this.growthPoints); nbt.setInteger( nutrientStorage , this.nutrientStorage); nbt.setInteger( waterStorage , this.waterStorage); nbt.setInteger( exStorage , this.exStorage); nbt.setBoolean( upgraded , this.upgraded); nbt.setByte( scanLevel , (byte)this.scanLevel); nbt.setInteger( weedlevel , this.weedlevel); nbt.setInteger( Infestedlevel , this.Infestedlevel); } public void updateEntity() { super.updateEntity(); ++this.ticker; if (this.ticker % tickRate == 0) { this.tick();// 256MinecraftTickに1回呼ばれる } if (this.dirty) {// 更新が必要なら更新する this.dirty = false; this.worldObj.markBlockForUpdate(this.xCoord, this.yCoord, this.zCoord); this.worldObj.updateLightByType(EnumSkyBlock.Block, this.xCoord, this.yCoord, this.zCoord); if (IC2.platform.isSimulating()) { Iterator var1 = this.getNetworkedFields().iterator(); while(var1.hasNext()) { String field = (String)var1.next(); ((NetworkManager)IC2.network.get()).updateTileEntityField(this, field); } } } } public List getNetworkedFields() { List ret = new ArrayList(4); ret.add( crop ); ret.add( size ); ret.add( upgraded ); ret.add( customData ); ret.add( weedlevel ); ret.add( Infestedlevel ); return ret; } public void tick() { if (IC2.platform.isSimulating()) { if (this.ticker % (tickRate 2) == 0) {// 1024Minecraftに1度、位相そのまま this.humidity = this.updateHumidity(); } if ((this.ticker + tickRate) % (tickRate 2) == 0) {// 1024Minecraftに1度、上の256tick前 this.nutrients = this.updateNutrients(); } if ((this.ticker + tickRate * 2) % (tickRate 2) == 0) {// 1024Minecraftに1度、上の256tick前 this.airQuality = this.updateAirQuality(); } if (this.crop == null) { if (!this.upgraded || !this.attemptCrossing()) {// upgradedなら何もしない、upgradedでないなら交配試行して成功したらスルー、交配失敗だと内部を実行 if (IC2.random.nextInt(100) != 0 || this.hasEx()) { if (this.exStorage 0 IC2.random.nextInt(10) == 0) { --this.exStorage; } return; } this.reset(); this.crop = IC2Crops.weed; this.size = 1; } assert this.crop != null; } this.crop.tick(this); if (this.crop.canGrow(this)) { this.growthPoints += this.calcGrowthRate(); if (this.crop == null) { return; } if (this.growthPoints = this.crop.growthDuration(this)) { this.growthPoints = 0; ++this.size; this.dirty = true; } } if (this.nutrientStorage 0) { --this.nutrientStorage; } if (this.waterStorage 0) { --this.waterStorage; } if (this.crop.isWeed(this) IC2.random.nextInt(50) - this.statGrowth = 2) { this.generateWeed(); } } } public void generateWeed() { int x = this.xCoord; int y = this.yCoord; int z = this.zCoord; switch(IC2.random.nextInt(4)) { case 0 ++x;// breakが足りない case 1 --x;// breakが足りない case 2 ++z;// breakが足りない case 3 --z; } if (this.worldObj.getTileEntity(x, y, z) instanceof TileEntityCrop) { TileEntityCrop teCrop = (TileEntityCrop)this.worldObj.getTileEntity(x, y, z); CropCard neighborCrop = teCrop.getCrop(); if (neighborCrop == null || !neighborCrop.isWeed(teCrop) IC2.random.nextInt(32) = teCrop.statResistance !teCrop.hasEx()) { int newGrowth = Math.max(this.statGrowth, teCrop.statGrowth); if (newGrowth 31 IC2.random.nextBoolean()) { ++newGrowth; } teCrop.reset(); teCrop.crop = IC2Crops.weed; teCrop.size = 1; teCrop.statGrowth = (byte)newGrowth; } } else if (this.worldObj.isAirBlock(x, y, z)) { Block block = this.worldObj.getBlock(x, y - 1, z); if (block == Blocks.dirt || block == Blocks.grass || block == Blocks.farmland) { this.worldObj.setBlock(x, y - 1, z, Blocks.grass, 0, 7); this.worldObj.setBlock(x, y, z, Blocks.tallgrass, 1, 7); } } } public boolean hasEx() { if (this.exStorage 0) { this.exStorage -= 5; return true; } else { return false; } } public boolean attemptCrossing() { if (IC2.random.nextInt(3) != 0) {// 確率で無条件失敗 return false; } else { List cropTes = new ArrayList(4);// 交配参加可能植物を列挙 this.askCropJoinCross(this.xCoord - 1, this.yCoord, this.zCoord, cropTes); this.askCropJoinCross(this.xCoord + 1, this.yCoord, this.zCoord, cropTes); this.askCropJoinCross(this.xCoord, this.yCoord, this.zCoord - 1, cropTes); this.askCropJoinCross(this.xCoord, this.yCoord, this.zCoord + 1, cropTes); if (cropTes.size() 2) {// 参加可能が2個未満で失敗 return false; } else { CropCard[] crops = (CropCard[])Crops.instance.getCrops().toArray(new CropCard[0]);// 全植物を列挙 if (crops.length == 0) {// 植物がないときは失敗 return false; } else { int[] ratios = new int[crops.length];// ここまでの累積交配比重 int total = 0; int search;// 全植物の交配比重の合計を計算 for(search = 0; search ratios.length; ++search) { CropCard crop = crops[search]; TileEntityCrop te; if (crop.canGrow(this)) { for(Iterator var7 = cropTes.iterator(); var7.hasNext(); total += this.calculateRatioFor(crop, te.getCrop())) { te = (TileEntityCrop)var7.next(); } } ratios[search] = total; } search = IC2.random.nextInt(total);// 累積交配比重に準じた乱数 int min = 0; int max = ratios.length - 1; int count; while(min max) {// minをsearchに対応したcropsのインデックスにする count = (min + max) / 2; int value = ratios[count]; if (search value) { max = count; } else { min = count + 1; } } assert min == max; assert min = 0 min ratios.length; assert ratios[min] search; assert min == 0 || ratios[min - 1] = search; this.upgraded = false; this.crop = crops[min]; this.dirty = true; this.size = 1; this.statGrowth = 0; this.statResistance = 0; this.statGain = 0; TileEntityCrop te;// 交配参加した作物の合計計算 for(Iterator var13 = cropTes.iterator(); var13.hasNext(); this.statGain += te.statGain) { te = (TileEntityCrop)var13.next(); this.statGrowth += te.statGrowth; this.statResistance += te.statResistance; } count = cropTes.size(); this.statGrowth /= count; this.statResistance /= count; this.statGain /= count;// ここまででGGRが交配参加した作物の平均になっている this.statGrowth += IC2.random.nextInt(1 + 2 * count) - count;// -count~count this.statGain += IC2.random.nextInt(1 + 2 * count) - count; this.statResistance += IC2.random.nextInt(1 + 2 * count) - count; this.statGrowth = Util.limit(this.statGrowth, 0, 31); this.statGain = Util.limit(this.statGain, 0, 31); this.statResistance = Util.limit(this.statResistance, 0, 31); return true; } } } } public int calculateRatioFor(CropCard newCrop, CropCard oldCrop) { if (newCrop == oldCrop) {// 同一植物だと500 return 500; } else { int value = 0;// 交配比重、初期値0 int diff;// statが完全に同一の時+10、statが1ずれるごとに-1のペナルティ int delta; for(diff = 0; diff 5; ++diff) { delta = Math.abs(newCrop.stat(diff) - oldCrop.stat(diff)); value += -delta + 2; } String[] var12 = newCrop.attributes();// 属性が大文字小文字無視で一致するごとに+5 delta = var12.length; for(int var6 = 0; var6 delta; ++var6) { String attributeNew = var12[var6]; String[] var8 = oldCrop.attributes(); int var9 = var8.length; for(int var10 = 0; var10 var9; ++var10) { String attributeOld = var8[var10]; if (attributeNew.equalsIgnoreCase(attributeOld)) { value += 5; } } } diff = newCrop.tier() - oldCrop.tier();// Tier増分が正の場合2倍ペナルティ、負の場合1倍ペナルティ if (diff 1) { value -= 2 * diff; } if (diff -3) { value -= -diff; } return Math.max(value, 0); } } public void askCropJoinCross(int x, int y, int z, List crops) { TileEntity te = this.worldObj.getTileEntity(x, y, z); if (te instanceof TileEntityCrop) {// ブロックが支柱で、 TileEntityCrop sideCrop = (TileEntityCrop)te; CropCard neighborCrop = sideCrop.getCrop(); if (neighborCrop != null) {// 植物が存在し、 if (neighborCrop.canGrow(this) neighborCrop.canCross(sideCrop)) {// その植物種が交配後の位置で成長可能であり、交配前の位置で交配可能である場合、 int base = 4;// 初期値4 if (sideCrop.statGrowth = 16) {// Gr16で1のボーナス ++base; } if (sideCrop.statGrowth = 30) {// Gr30で1のボーナス ++base; } if (sideCrop.statResistance = 28) {// Re28以降1ずつペナルティ base += 27 - sideCrop.statResistance; } if (base = IC2.random.nextInt(20)) {// (base + 1) / 20が交配参加確率。 crops.add(sideCrop); } } } } } public boolean leftClick(EntityPlayer player) { if (this.crop == null) { if (this.upgraded) { this.upgraded = false; this.dirty = true; if (IC2.platform.isSimulating()) { StackUtil.dropAsEntity(this.worldObj, this.xCoord, this.yCoord, this.zCoord, new ItemStack(Ic2Items.crop.getItem())); } return true; } else { return false; } } else { return this.crop.leftclick(this, player); } } public boolean pick(boolean manual) { if (this.crop == null) { return false; } else { boolean bonus = this.harvest(false); float firstchance = this.crop.dropSeedChance(this); int drop; for(drop = 0; drop this.statResistance; ++drop) { firstchance *= 1.1F; } drop = 0; int x; if (bonus) { if (IC2.random.nextFloat() = (firstchance + 1.0F) * 0.8F) { ++drop; } float chance = this.crop.dropSeedChance(this) + (float)this.statGrowth / 100.0F; if (!manual) { chance *= 0.8F; } for(x = 23; x this.statGain; ++x) { chance *= 0.95F; } if (IC2.random.nextFloat() = chance) { ++drop; } } else if (IC2.random.nextFloat() = firstchance * 1.5F) { ++drop; } ItemStack[] re = new ItemStack[drop]; for(x = 0; x drop; ++x) { re[x] = this.crop.getSeeds(this); } this.reset(); if (IC2.platform.isSimulating() re.length 0) { for(x = 0; x re.length; ++x) { if (re[x].getItem() != Ic2Items.cropSeed.getItem()) { re[x].stackTagCompound = null; } StackUtil.dropAsEntity(this.worldObj, this.xCoord, this.yCoord, this.zCoord, re[x]); } } return true; } } public boolean rightClick(EntityPlayer player) { ItemStack current = player.getCurrentEquippedItem(); boolean creative = player.capabilities.isCreativeMode; if (current != null) { if (this.crop == null) { if (current.getItem() == Ic2Items.crop.getItem() !this.upgraded) { if (!creative) { --current.stackSize; if (current.stackSize = 0) { player.inventory.mainInventory[player.inventory.currentItem] = null; } } this.upgraded = true; this.dirty = true; return true; } if (this.applyBaseSeed(player)) { return true; } } if (current.getItem() == Items.water_bucket || current.getItem() == Ic2Items.waterCell.getItem()) { if (this.waterStorage 10) { this.waterStorage = 10; return true; } return current.getItem() == Items.water_bucket; } if (current.getItem() == Items.wheat_seeds) { if (this.nutrientStorage = 50) { this.nutrientStorage += 25; --current.stackSize; if (current.stackSize = 0) { player.inventory.mainInventory[player.inventory.currentItem] = null; } return true; } return false; } if (current.getItem() == Items.dye current.getItemDamage() == 15 || current.getItem() == Ic2Items.fertilizer.getItem()) { if (this.applyFertilizer(true)) { if (creative) { return true; } else { --current.stackSize; if (current.stackSize = 0) { player.inventory.mainInventory[player.inventory.currentItem] = null; } return true; } } else { return false; } } if (current.getItem() == Ic2Items.hydratingCell.getItem()) { if (this.applyHydration(true, current, player)) { if (current.stackSize = 0) { player.inventory.mainInventory[player.inventory.currentItem] = null; } return true; } return false; } if (current.getItem() == Ic2Items.weedEx.getItem() this.applyWeedEx(true)) { current.damageItem(1, player); if (current.stackSize = 0) { player.inventory.mainInventory[player.inventory.currentItem] = null; } return true; } } if (this.crop == null) { return false; } else { return this.crop.rightclick(this, player); } } public boolean applyBaseSeed(EntityPlayer player) { ItemStack current = player.getCurrentEquippedItem(); BaseSeed seed = Crops.instance.getBaseSeed(current); if (seed != null) { if (current.stackSize seed.stackSize) { return false; } if (this.tryPlantIn(seed.crop, seed.size, seed.statGrowth, seed.statGain, seed.statResistance, 1)) { if (player.capabilities.isCreativeMode) { return true; } if (current.getItem().hasContainerItem(current)) { if (current.stackSize 1) { return false; } player.inventory.mainInventory[player.inventory.currentItem] = current.getItem().getContainerItem(current); } else { current.stackSize -= seed.stackSize; if (current.stackSize = 0) { player.inventory.mainInventory[player.inventory.currentItem] = null; } } return true; } } return false; } public boolean tryPlantIn(CropCard crop, int si, int statGr, int statGa, int statRe, int scan) { if (crop != null crop != IC2Crops.weed !this.upgraded) { if (!crop.canGrow(this)) { return false; } else { this.reset(); this.crop = crop; this.size = (byte)si; this.statGrowth = (byte)statGr; this.statGain = (byte)statGa; this.statResistance = (byte)statRe; this.scanLevel = (byte)scan; return true; } } else { return false; } } public boolean applyFertilizer(boolean manual) { if (this.nutrientStorage = 100) { return false; } else { this.nutrientStorage += manual ? 100 90; return true; } } public boolean applyHydration(TileEntityCropmatron cropmatron) { if (this.waterStorage = 200) { return false; } else { int apply = 200 - this.waterStorage; FluidStack drain = cropmatron.getFluidTank().drain(apply, true); if (drain != null) { this.waterStorage += drain.amount; return true; } else { return false; } } } public boolean applyHydration(boolean manual, ItemStack itemStack, EntityPlayer player) { if ((manual || this.waterStorage 180) this.waterStorage 200) { int apply = manual ? 200 - this.waterStorage 180 - this.waterStorage; apply = Math.min(apply, itemStack.getMaxDamage() - itemStack.getItemDamage()); if (!player.capabilities.isCreativeMode itemStack.attemptDamageItem(apply, IC2.random)) { player.inventory.mainInventory[player.inventory.currentItem] = Ic2Items.cell; } this.waterStorage += apply; return true; } else { return false; } } public boolean applyWeedEx(boolean manual) { if ((this.exStorage 100 || !manual) this.exStorage 150) { this.exStorage += 50; boolean triggerDecline; if (manual) { triggerDecline = this.worldObj.rand.nextInt(5) == 0; } else { triggerDecline = this.worldObj.rand.nextInt(3) == 0; } if (this.crop != null this.crop.isWeed(this) this.exStorage = 75 triggerDecline) { switch(this.worldObj.rand.nextInt(5)) { case 0 if (this.statGrowth 0) { --this.statGrowth; } case 1 if (this.statGain 0) { --this.statGain; } default if (this.statResistance 0) { --this.statResistance; } } } return true; } else { return false; } } public ItemStack[] harvest_automated(boolean optimal) { if (this.crop == null) { return null; } else if (!this.crop.canBeHarvested(this)) { return null; } else if (optimal this.size != this.crop.getOptimalHavestSize(this)) { return null; } else { double chance = (double)this.crop.dropGainChance(); chance *= Math.pow(1.03D, (double)this.statGain); int dropCount = (int)Math.max(0L, Math.round(IC2.random.nextGaussian() * chance * 0.6827D + chance)); ItemStack[] ret = new ItemStack[dropCount]; for(int i = 0; i dropCount; ++i) { ret[i] = this.crop.getGain(this); if (ret[i] != null IC2.random.nextInt(100) = this.statGain) { ++ret[i].stackSize; } } this.size = this.crop.getSizeAfterHarvest(this); this.dirty = true; return ret; } } public boolean harvest(boolean manual) { ItemStack[] drops = this.harvest_automated(false); if (drops == null) { return false; } else { if (IC2.platform.isSimulating() drops.length 0) { ItemStack[] var3 = drops; int var4 = drops.length; for(int var5 = 0; var5 var4; ++var5) { ItemStack drop = var3[var5]; StackUtil.dropAsEntity(this.worldObj, this.xCoord, this.yCoord, this.zCoord, drop); } } return true; } } public void onNeighbourChange() { if (this.crop != null) { this.crop.onNeighbourChange(this); } } public int emitRedstone() { return this.crop == null ? 0 this.crop.emitRedstone(this); } public void onBlockDestroyed() { if (this.crop != null) { this.crop.onBlockDestroyed(this); } } public int getEmittedLight() { return this.crop == null ? 0 this.crop.getEmittedLight(this); } public byte getHumidity() { if (this.humidity == -1) { this.humidity = this.updateHumidity(); } return this.humidity; } public byte getNutrients() { if (this.nutrients == -1) { this.nutrients = this.updateNutrients(); } return this.nutrients; } public byte getAirQuality() { if (this.airQuality == -1) { this.airQuality = this.updateAirQuality(); } return this.airQuality; } public byte updateHumidity() { int value = Crops.instance.getHumidityBiomeBonus(this.worldObj.getBiomeGenForCoords(this.xCoord, this.zCoord)); if (this.worldObj.getBlockMetadata(this.xCoord, this.yCoord - 1, this.zCoord) = 7) { value += 2; } if (this.waterStorage = 5) { value += 2; } value += (this.waterStorage + 24) / 25; return (byte)value; } public byte updateNutrients() { int value = Crops.instance.getNutrientBiomeBonus(this.worldObj.getBiomeGenForCoords(this.xCoord, this.zCoord)); for(int i = 2; i 5 this.worldObj.getBlock(this.xCoord, this.yCoord - i, this.zCoord) == Blocks.dirt; ++i) { ++value; } value += (this.nutrientStorage + 19) / 20; return (byte)value; } public byte updateAirQuality() { int value = 0; int height = (this.yCoord - 64) / 15; if (height 4) { height = 4; } if (height 0) { height = 0; } int value = value + height; int fresh = 9; for(int x = this.xCoord - 1; x = this.xCoord + 1 fresh 0; ++x) { for(int z = this.zCoord - 1; z = this.zCoord + 1 fresh 0; ++z) { if (this.worldObj.isBlockNormalCubeDefault(x, this.yCoord, z, false) || this.worldObj.getTileEntity(x, this.yCoord, z) instanceof TileEntityCrop) { --fresh; } } } value += fresh / 2; if (this.worldObj.canBlockSeeTheSky(this.xCoord, this.yCoord + 1, this.zCoord)) { value += 2; } return (byte)value; } public int updateMultiCulture() { Set crops = new HashSet(); for(int x = -1; x 1; ++x) { for(int z = -1; z 1; ++z) { TileEntity te = this.worldObj.getTileEntity(x + this.xCoord, this.yCoord, z + this.zCoord); if (te instanceof TileEntityCrop) { CropCard neighborCrop = ((TileEntityCrop)te).getCrop(); if (neighborCrop != null) { crops.add(neighborCrop); } } } } return crops.size() - 1; } public void addIfNotPresent(CropCard crop, LinkedList crops) { for(int i = 0; i crops.size(); ++i) { if (crop == crops.get(i)) { return; } } crops.add(crop); } public int calcGrowthRate() { if (this.crop == null) { return 0; } else { int base = 3 + IC2.random.nextInt(7) + this.statGrowth; int need = (this.crop.tier() - 1) * 4 + this.statGrowth + this.statGain + this.statResistance; if (need 0) { need = 0; } int have = this.crop.weightInfluences(this, (float)this.getHumidity(), (float)this.getNutrients(), (float)this.getAirQuality()) * 5; if (have = need) { base = base * (100 + (have - need)) / 100; } else { int neg = (need - have) * 4; if (neg 100 IC2.random.nextInt(32) this.statResistance) { this.reset(); base = 0; } else { base = base * (100 - neg) / 100; if (base 0) { base = 0; } } } return base; } } public void calcTrampling() { if (IC2.platform.isSimulating()) { if (IC2.random.nextInt(100) == 0 IC2.random.nextInt(40) this.statResistance) { this.reset(); this.worldObj.setBlock(this.xCoord, this.yCoord - 1, this.zCoord, Blocks.dirt, 0, 7); } } } public void onEntityCollision(Entity entity) { if (this.crop != null) { if (this.crop.onEntityCollision(this, entity)) { this.calcTrampling(); } } } public void reset() { this.crop = null; this.size = 0; this.customData = new NBTTagCompound(); this.dirty = true; this.statGain = 0; this.statResistance = 0; this.statGrowth = 0; this.nutrients = -1; this.airQuality = -1; this.humidity = -1; this.growthPoints = 0; this.upgraded = false; this.scanLevel = 0; } public void updateState() { this.dirty = true; } public String getScanned() { if (this.crop == null) { return null; } else if (this.scanLevel = 0) { return null; } else { String name = StatCollector.translateToLocal(this.crop.displayName()); return this.scanLevel = 4 ? String.format( %s - Gr %d Ga %d Re %d S %d/%d , name, this.statGrowth, this.statGain, this.statResistance, this.size, this.crop.maxSize()) String.format( %s - Size %d/%d , name, this.size, this.crop.maxSize()); } } public boolean isBlockBelow(Block reqBlock) { if (this.crop == null) { return false; } else { for(int i = 1; i this.crop.getrootslength(this); ++i) { Block block = this.worldObj.getBlock(this.xCoord, this.yCoord - i, this.zCoord); if (block.isAir(this.worldObj, this.xCoord, this.yCoord - i, this.zCoord)) { return false; } if (block == reqBlock) { return true; } } return false; } } public boolean isBlockBelow(String oreDictionaryName) { if (this.crop == null) { return false; } else { for(int i = 1; i this.crop.getrootslength(this); ++i) { Block block = this.worldObj.getBlock(this.xCoord, this.yCoord - i, this.zCoord); int metaData = this.worldObj.getBlockMetadata(this.xCoord, this.yCoord - i, this.zCoord); if (block.isAir(this.worldObj, this.xCoord, this.yCoord - i, this.zCoord)) { return false; } for(int aux = 0; aux OreDictionary.getOres(oreDictionaryName).size(); ++aux) { ItemStack itemStack = (ItemStack)OreDictionary.getOres(oreDictionaryName).get(aux); if (itemStack.getItem() == Item.getItemFromBlock(block) itemStack.getItemDamage() == metaData) { return true; } } } return false; } } public ItemStack generateSeeds(CropCard crop, byte growth, byte gain, byte resis, byte scan) { return ItemCropSeed.generateItemStackFromValues(crop, growth, gain, resis, scan); } public ItemStack generateSeeds(short plant, byte growth, byte gain, byte resis, byte scan) { return this.generateSeeds(IC2Crops.getCropFromId(plant), growth, gain, resis, scan); } public void onNetworkUpdate(String field) { this.dirty = true; } public CropCard getCrop() { return this.crop; } public short getID() { return (short)Crops.instance.getIdFor(this.crop); } public byte getSize() { return (byte)this.size; } public byte getGrowth() { return (byte)this.statGrowth; } public byte getGain() { return (byte)this.statGain; } public byte getResistance() { return (byte)this.statResistance; } public byte getScanLevel() { return (byte)this.scanLevel; } public NBTTagCompound getCustomData() { return this.customData; } public int getNutrientStorage() { return this.nutrientStorage; } public int getHydrationStorage() { return this.waterStorage; } public int getWeedExStorage() { return this.exStorage; } public int getLightLevel() { return this.worldObj.getBlockLightValue(this.xCoord, this.yCoord, this.zCoord); } public void setCrop(CropCard cropCard) { this.crop = cropCard; this.dirty = true; } public void setID(short id) { this.setCrop(IC2Crops.getCropFromId(id)); } public void setSize(byte size1) { this.size = size1; this.dirty = true; } public void setGrowth(byte growth) { this.statGrowth = growth; } public void setGain(byte gain) { this.statGain = gain; } public void setResistance(byte resistance) { this.statResistance = resistance; } public void setScanLevel(byte scanLevel1) { this.scanLevel = scanLevel1; } public void setNutrientStorage(int nutrientStorage1) { this.nutrientStorage = nutrientStorage1; } public void setHydrationStorage(int hydrationStorage) { this.waterStorage = hydrationStorage; } public void setWeedExStorage(int weedExStorage) { this.exStorage = weedExStorage; } public World getWorld() { return this.worldObj; } public ChunkCoordinates getLocation() { return new ChunkCoordinates(this.xCoord, this.yCoord, this.zCoord); } public int getvisualweedlevel() { return this.weedlevel; } public int getvisualInfestedlevel() { if (this.Infestedlevel 10) { return 0; } else if (this.Infestedlevel 30) { return 1; } else if (this.Infestedlevel 50) { return 2; } else if (this.Infestedlevel 70) { return 3; } else { return this.Infestedlevel 90 ? 4 5; } } }
https://w.atwiki.jp/survivalcraftwiki/pages/17.html
Survivalcraftとは? SurvivalcraftとはMinecraftに似ているサンドボックスゲーム。 Minecraftと同じ無限ワールドでクラフティング方法も同じ。 Minecraftのテクスチャーも存在する。 Minecraftとの違い Survivalcraft(以下SCに省略)にはMinecraft(以下MCに省略)のような自爆したり弓矢を打ってくるようなMOBは存在せず、 プレイヤー以外は全て動物である。 またSCにはMCのレッドストーンの代わりに導線がある。SCはMCのようにマルチプレイは存在しない。 等がある。
https://w.atwiki.jp/kbhyakka/pages/660.html
Industrial Nine Inch Nails Throbbing Gristle
https://w.atwiki.jp/mi_ic2/pages/48.html
収穫 新版記事 728→729で収穫量の仕様が変わったようである。731でも変わった。 準拠: industrialcraft-2-2.2.517-experimental 概要 成長した作物を持つ支柱を右クリックすると、各種パラメータに応じたアイテムをその場にドロップする。このようなIC2Cropからのアイテムの享受を広義の収穫という(TileEntityCrops#harvest)。 収穫はIC2Cropのシステムから恩恵を受けるための最も基本的な手段であり、植えた作物種に応じて食材や加工素材をはじめとする実に様々なアイテムを得ることができる。 狭義の収穫(収穫イベント)はTileEntityCrops#harvestが呼び出されることをいい、本記事群では特に断りの無い限り、収穫といったらこちらを指す。つまり、何も収穫物が得られなくても収穫行為は行われている。 収穫イベントには手動と自動の区別があるが、特に処理に違いは無い。 因みに、狭義の収穫を起こさなくとも収穫物を地面にドロップする方法も存在する。逆に狭義の収穫が行われても必ず収穫物がドロップするとは限らない。 手動収穫が行われる条件 支柱を右クリックすると作物種の右クリックイベント(CropCard#rightclick)が呼び出されるが、そのイベント処理では規定の動作で手動収穫が行われる。 2.2.517現在、IC2Exp本体では植物が存在する支柱を右クリックすると必ず手動収穫が行われ、手動収穫を行うには支柱を右クリックする以外に方法は無い。 自動収穫が行われる条件 植物が存在する支柱を左クリックで破壊しようとしたとき、作物の種と同時に収穫物をドロップする。このとき、収穫は自動収穫として扱われる。 GregTechのハーベスターが自動収穫を行う。 収穫の試み(TileEntityCrop#harvest) 収穫イベントの発生時、支柱は次の処理を行う。この処理により真を返した場合、収穫の試みは成功したという。収穫物の有無にかかわらず、収穫の試みが成功した場合は作物の成長レベルが低下する。 まず、支柱に植物が無いか、収穫可能でない場合、何も行わずに偽を返す。次に、作物種ごとに異なる基本収穫量の値を計算する。 Gain値によって、基本収穫量を1.03^Gain倍にする。 基本収穫量から、その時のドロップ数の計算をする。 ドロップ数の分だけ作物種から収穫物の取得を行い、取得ごとに(Gain+1)%の確率で数量を1増やす。 作物の成長レベルを減衰させる。 全てのドロップすべき収穫物をワールドにドロップする。 真を返す。 収穫可能(CropCard#canBeHarvested) 専ら作物が収穫可能な成長段階かを判断している。 雑草を除くIC2Expに存在するすべての作物種は作物列挙で示されるような収穫可能サイズ以上であるかどうかのみによって収穫可能かどうかを決めている。 雑草は常に収穫不可である。 基本収穫量(CropCard#dropGainChance) 作物列挙にあるような計算式で値を返す。多くはTier依存であり、いくつかの作物は固有の値を持つ。 Gain値による基本収穫量への倍率表 Gain 収穫倍率 種倍率 0 1.0000 1.00000 1 1.0300 1.00000 2 1.0609 1.00000 3 1.0927 1.00000 4 1.1255 1.00000 5 1.1593 1.00000 6 1.1941 1.00000 7 1.2299 1.00000 8 1.2668 1.00000 9 1.3048 1.00000 10 1.3439 1.00000 11 1.3842 1.00000 12 1.4258 1.00000 13 1.4685 1.00000 14 1.5126 1.00000 15 1.5580 1.00000 16 1.6047 1.00000 17 1.6528 1.00000 18 1.7024 1.00000 19 1.7535 1.00000 20 1.8061 1.00000 21 1.8603 1.00000 22 1.9161 1.00000 23 1.9736 1.00000 24 2.0328 0.95000 25 2.0938 0.90250 26 2.1566 0.85738 27 2.2213 0.81451 28 2.2879 0.77378 29 2.3566 0.73509 30 2.4273 0.69834 31 2.5001 0.66342 ドロップ数の計算 結論から言うと、基本収穫量に対するドロップ数の期待値は以下のようになる。 基本収穫量が1以下の場合(C:基本収穫量) 基本収穫量が1以上の場合(C:基本収穫量) 具体的には、次のような処理を行っている。 float chance = 基本収穫量 chance -= 0以上1未満の一様乱数 int drop = 0 while (chance 0) { drop++ chance -= 0以上1未満の一様乱数 } ドロップ数 = drop ドロップ数は基本収穫量から、0以上1未満の一様乱数を引くことができた回数である。それ故、基本収穫量が0に近くとも乱数が0付近をとれば収穫物を得ることができる。 基本収穫量が1以下の場合のドロップ数の分布は正確に以下の式で表される。 (C:基本収穫量 n:ドロップ数) また、基本収穫量が1以下の場合のドロップ数の期待値は正確に次のようになる。 (C:基本収穫量) 基本収穫量が1を超える場合の式は計算するのが面倒臭いので掲載しないが、シミュレーションによる基本収穫量に対するドロップ数分布のグラフと期待値のグラフを掲載する。 ドロップ率分布グラフ(シミュレーション) 期待値グラフ(シミュレーション) 基本収穫量が1を超える場合のドロップ数の期待値はおおよそ以下のように近似できる。 (C:基本収穫量) より正確には以下のようになる。 (C:基本収穫量) 収穫物の取得(CropCard#getGain) 作物種ごとに固有の収穫物をもつ。作物列挙ページの基本収穫物の欄がそうである。 トリビア Gainが31である場合、Gainが0である場合に比べて約2.5倍の収穫物を得られる。種袋の生産量に悪影響のない限界値である23では約2.0倍となる。 ドロップ数とは別にドロップアイテムの個数増加処理がある。このため、Gain値は2重に収穫物の量を上昇させる。 アシ・カカオ豆・スイカのようにスタックされた状態の収穫物を有する作物種は、ドロップアイテムの個数増加処理の恩恵が比較的少ない。 基本収穫量が2.0であるネザーワートをGain31まで育てると、基本収穫量は5.00まで上昇する。この時のドロップ数の期待値は約9.66個となる。更にドロップアイテムの個数増加処理により32%収穫物が増えるので、平均12.76個のアイテムがその場にドロップする。