提供: Minecraft Modding Wiki
移動先: 案内検索
(ディメンションの生成まで作成)
 
(Dimension間移動について、PlayerList#transferEntityToWorldは私の方で転送に成功していない(詳しくは未検証)ので、強引な手法を記述)
130行目: 130行目:
  
 
==== Teleporter ====
 
==== Teleporter ====
 +
「net.minecraft.world.Teleporter」は移動するEntityの現在座標をもとにポータルを生成するクラスです。
 +
 +
EntityがDimension移動するのに使われる「net.minecraft.entity.Entity#changeDimension」では、「net.minecraft.world.WorldServer#getDefaultTeleporter」を呼び出し、「WorldServer#worldTeleporter」を得ています。
 +
 +
===== PlayerList#transferEntityToWorldを利用する場合 =====
 +
(未検証)
 +
 +
===== 強引にEntity#changeDimensionを利用する場合 =====
 +
# AccessTransformerを使って、「private final」な「WorldServer#worldTeleporter」、SRG名「field_85177_Q」のアクセス修飾子を「public」にする(下ソース参照、net.minecraftforge.fml.relauncher.ReflectionHelperでも可)。
 +
# 転送時、元々のWorldServer#worldTeleporterを退避して、好きなTeleporterインスタンスを代入。Entity#changeDimensionを呼んでEntityを移動させ、WorldServer#worldTeleporterを復元する。
 +
 +
META-INF/<modid>_at.cfg
 +
<source lang="text">
 +
public-f net.minecraft.world.WorldServer field_85177_Q #worldTeleporter non-final
 +
</source>
 +
 +
2の例
 +
<source lang="java" line>
 +
public static <T extends Entity> void transferEntity(World worldIn, BlockPos portalPos, T entityIn,
 +
                                                    int destDimension, Function<WorldServer, Teleporter> funcTeleporter,
 +
                                                    Consumer<T> callback) {
 +
    entityIn.setPortal(portalPos);
 +
    entityIn.timeUntilPortal = 10;
 +
 +
    if (!worldIn.isRemote && !entityIn.isDead) {
 +
        MinecraftServer server = entityIn.getServer();
 +
        WorldServer destServer = server.worldServerForDimension(destDimension);
 +
 +
        Teleporter teleporter = funcTeleporter.apply(destServer);
 +
        Teleporter cache = destServer.worldTeleporter; // Access Transformer | private final -> public
 +
 +
        destServer.worldTeleporter = teleporter;
 +
        T clone = (T) entityIn.changeDimension(destDimension);
 +
        callback.accept(clone); // 座標設定等
 +
 +
        destServer.worldTeleporter = cache;
 +
 +
    }
 +
}
 +
</source>

2017年3月26日 (日) 02:19時点における版

この記事は"Minecraft Forge Universal 13.19.0.xxx~"を前提MODとしています。

Stone pickaxe.png
中級者向けのチュートリアルです。
C world.png
Worldに関係のあるチュートリアルです。

ディメンションの追加

ディメンションを生成する

DimensionType

「net.minecraft.world.DimensionType」は、ディメンションを登録する列挙型です。

ForgeがDimensionTypeに列挙子を追加するメソッド「DimensionType#register」を用意してくれているので、これを使います。

  1. 「net.minecraftforge.common.DimensionManager#getNextFreeDimId」から、使用可能なディメンションID(int)を取得します。
  2. 「DimensionType#register」を呼び出し、「DimensionType」型の戻り値を得ます。これが追加された列挙子で、WorldProviderで使います。
    • 第一引数(String):ディメンションの名前(e.g. Overworld、Nether、The End)
    • 第二引数(String):ディメンションのセーブデータ等で使う後置詞(e.g. _nether、_end)
    • 第三引数(int):1で取得したID
    • 第四引数(Class<? extends WorldProvider>):WorldProviderのクラス(下で解説)
    • 第五引数(boolean):ディメンションをアンロードしないかどうか
  3. 「DimensionManager#registerDimension」を呼び出し、こちらにもディメンションを登録します。

WorldProvider

「net.minecraft.world.WorldProvider」は、ワールドの振る舞いを決定する抽象クラスです。

  1. 「WorldProvider」のサブクラスを作成します。
  2. コンストラクタから「WorldProvider#init」が呼ばれるので、WorldProviderのフィールド(下表参照)を好きなように変更してください。
  3. 「DimensionType」の項で得た、このWorldProviderに対応する「DimensionType」列挙子を「getDimensionType」から返します。
フィールド名 影響 参考
doesWaterVaporize 水の蒸発の有無
  • net.minecraft.item.ItemBucket
  • net.minecraft.block.BlockDynamicLiquid
  • net.minecraft.block.BlockIce
hasNoSky 地図の描画、スポーン座標
  • net.minecraft.world.WorldProvider#getActualHeight
  • net.minecraft.item.ItemMap
hasSkyLight 日光の有無
  • net.minecraft.world.chunk.Chunk
biomeProvider バイオームの決定 下で解説


メソッド名 影響 参考
calculateCelestialAngle 昼夜の移り変わり 0fで真昼(エンド)、.5fで真夜中(ネザー)
  • net.minecraft.world.World#getCelestialAngleRadians
  • net.minecraft.item.ItemClock
  • net.minecraft.block.BlockDaylightDetector
  • net.minecraft.client.renderer.RenderGlobal#renderSky
  • net.minecraft.village.VillageSiege
createChunkGenerator チャンクの地形等、生成手法の決定 net.minecraft.world.chunk.IChunkGeneratorを実装したクラスのインスタンスを作成して返す。詳しくは下で解説。
canRespawnHere リスポーンの可否
isSurfaceWorld 空の描画の有無
getVoidFogYFactor 奈落の霧(Japan Wiki)の開始Y座標
getHorizon 地平線の高さ
doesXZShowFog 霧の描画の有無
  • net.minecraft.client.renderer.EntityRenderer#setupFog
getWelcomeMessage ディメンション入場時のメッセージ?(未使用)
getDepartMessage ディメンション退場時のメッセージ?(未使用)

BiomeProvider

「net.minecraft.world.biome.BiomeProvider」は、バイオームを決定するクラスです。

サブクラス「net.minecraft.world.biome.BiomeProviderSingle」は、単一バイオームのディメンションを作成するのに使うことができます(ネザー、エンドで使用)。

オーバーワールドでは、「net.minecraft.world.gen.layer.GenLayer#initializeAllBiomeGenerators」、「net.minecraft.world.biome.BiomeProvider#getModdedBiomeGenerators」を通じて得られた「GenLayer」の「#getInts」からバイオームIDを取得しています。

IChunkGenerator

「net.minecraft.world.chunk.IChunkGenerator」は、チャンクの地形や構造物を生成するインターフェースです。

  1. 「IChunkGenerator」を実装したクラスを作成します。コンストラクタでWorldProviderからWorldのインスタンスを受け取ってください。チャンクのインスタンス化に使います。
  2. 「#provideChunk」を実装します。第一引数はチャンクのX座標、第二引数はチャンクのZ座標です。
    1. 「net.minecraft.world.chunk.ChunkPrimer」をインスタンス化します。
    2. 上のWorld、ChunkPrimerを使って「net.minecraft.world.chunk.Chunk」をインスタンス化します。
    3. Chunk#setBlockStateなどを使って、上のChunkに地形を生成します。
    4. Chunkにバイオームを割り当てます。
      • net.minecraft.world.chunk.ChunkProviderHellの手法
      1. Chunk#getBiomeArrayの戻り値としてバイオーム割り当てに使用するバイオームIDのbyte配列を得ます。
      2. 上のWorldからBiomeProviderを取得し、BiomeProvider#getBiomesから、チャンク座標に対応するバイオームのBiome配列を得ます。
      3. byte配列のindexに対応するバイオームIDをBiome配列から取り出して代入します(配列はオブジェクトなので、Chunkが持つ配列が変更されます)。
メソッド名 操作 参考
provideChunk チャンクのインスタンス化、地形生成
populate 湖、鉱石、ダンジョン等の生成
generateStructures 構造物の追加生成(海底遺跡で使用)
getPossibleCreatures EntityCreatureの自然スポーン設定
  • 通常スポーン
    • Biome#getSpawnableListから取得
  • ダンジョン内等の特殊スポーン
    • 好きなリストを返す
  • net.minecraft.world.WorldServer#getSpawnListEntryForTypeAt
  • net.minecraft.world.WorldEntitySpawner
getStrongholdGen ダンジョンを生成するブロック座標を返す。なければnull。 オーバーワールドの要塞を見つけるエンダーアイで使用。
  • net.minecraft.world.WorldServer#findNearestStructure
  • net.minecraft.item.ItemEnderEye
recreateStructures ダンジョン等MapGenBaseのサブクラスのインスタンスがあればMapGenBase#generateを呼ぶ。

チャンクをファイルから読み込む時に呼ばれる模様。ブロック生成以外の構造物のデータを読み込む?

  • net.minecraft.world.gen.ChunkProviderServer#loadChunkFromFile
  • net.minecraftforge.common.chunkio.ChunkIOProvider#syncCallback
  • net.minecraft.world.gen.MapGenBase#generate
  • net.minecraft.world.gen.structure#MapGenStructure#recursiveGenerate


ポータルを作成する

Teleporter

「net.minecraft.world.Teleporter」は移動するEntityの現在座標をもとにポータルを生成するクラスです。

EntityがDimension移動するのに使われる「net.minecraft.entity.Entity#changeDimension」では、「net.minecraft.world.WorldServer#getDefaultTeleporter」を呼び出し、「WorldServer#worldTeleporter」を得ています。

PlayerList#transferEntityToWorldを利用する場合

(未検証)

強引にEntity#changeDimensionを利用する場合
  1. AccessTransformerを使って、「private final」な「WorldServer#worldTeleporter」、SRG名「field_85177_Q」のアクセス修飾子を「public」にする(下ソース参照、net.minecraftforge.fml.relauncher.ReflectionHelperでも可)。
  2. 転送時、元々のWorldServer#worldTeleporterを退避して、好きなTeleporterインスタンスを代入。Entity#changeDimensionを呼んでEntityを移動させ、WorldServer#worldTeleporterを復元する。

META-INF/<modid>_at.cfg

public-f net.minecraft.world.WorldServer field_85177_Q #worldTeleporter non-final

2の例

public static <T extends Entity> void transferEntity(World worldIn, BlockPos portalPos, T entityIn,
                                                     int destDimension, Function<WorldServer, Teleporter> funcTeleporter,
                                                     Consumer<T> callback) {
    entityIn.setPortal(portalPos);
    entityIn.timeUntilPortal = 10;

    if (!worldIn.isRemote && !entityIn.isDead) {
        MinecraftServer server = entityIn.getServer();
        WorldServer destServer = server.worldServerForDimension(destDimension);

        Teleporter teleporter = funcTeleporter.apply(destServer);
        Teleporter cache = destServer.worldTeleporter; // Access Transformer | private final -> public

        destServer.worldTeleporter = teleporter;
        T clone = (T) entityIn.changeDimension(destDimension);
        callback.accept(clone); // 座標設定等

        destServer.worldTeleporter = cache;

    }
}