提供: Minecraft Modding Wiki
この記事は"ModLoader"を前提MODとしています。 |
ソース解説[編集]
mod_hogeliquidクラスを作成[編集]
package net.minecraft.src; public class mod_hogeliquid extends BaseMod { /* * 動く部分のBlockIDと、水源部分のBlockIDの2つで1つの液体となります。 */ public static Block hogeLiquidMoving; public static Block hogeLiquidStill; public mod_hogeliquid() { } public String getVersion() { return "1.1"; } public void load() { /* * 長々と定義していますがやってることは単純です。 * BlockFlowingHogeクラスでBlockIDを100で設定し、水と同じ動作をさせます。 * 全く新しいものを作るのであれば、Materialを基本に別クラスから取得させる。 * setHardnessで100Fを設定(壊すものじゃないので) * setLightOpacityは溶岩のように光るかどうかをintで設定します。 */ hogeLiquidMoving = new BlockFlowingHoge(100, Material.water); hogeLiquidMoving.setHardness(100F); hogeLiquidMoving.setLightOpacity(3); hogeLiquidMoving.setBlockName("Hoge Moving"); hogeLiquidMoving.disableStats(); hogeLiquidMoving.setRequiresSelfNotify(); /* * 上とおなじ。 */ hogeLiquidStill = new BlockStationaryHoge(101, Material.water); hogeLiquidStill.setHardness(100F); hogeLiquidStill.setLightOpacity(3); hogeLiquidStill.setBlockName("Hoge Still"); hogeLiquidStill.disableStats(); hogeLiquidStill.setRequiresSelfNotify(); /* * ブロックとして登録する。 */ ModLoader.RegisterBlock(hogeLiquidMoving); ModLoader.RegisterBlock(hogeLiquidStill); /* * 表示名を設定する。 */ ModLoader.AddName(hogeLiquidMoving, "Hoge Moving"); ModLoader.AddName(hogeLiquidStill, "Hoge Still"); } }
BlockFlowingHogeクラスを作成[編集]
長々と書きますがやってることは単純です。 既存の「BlockFlowing」クラスをコピペし、クラス名に依存してる部分修正。
package net.minecraft.src; import java.util.Random; public class BlockFlowingHoge extends BlockFluid { int numAdjacentSources; boolean isOptimalFlowDirection[]; int flowCost[]; protected BlockFlowingHoge(int i, Material material) { super(i, material); numAdjacentSources = 0; isOptimalFlowDirection = new boolean[4]; flowCost = new int[4]; } /* *コピペだけじゃ芸がないので、ここ液体の色を設定できます。 */ public int colorMultiplier(IBlockAccess iblockaccess, int i, int j, int k) { return 0xffffff; } private void updateFlow(World world, int i, int j, int k) { int l = world.getBlockMetadata(i, j, k); world.setBlockAndMetadata(i, j, k, blockID + 1, l); world.markBlocksDirty(i, j, k, i, j, k); world.markBlockNeedsUpdate(i, j, k); } public void updateTick(World world, int i, int j, int k, Random random) { int l = getFlowDecay(world, i, j, k); byte byte0 = 1; if (blockMaterial == Material.lava && !world.worldProvider.isHellWorld) { byte0 = 2; } boolean flag = true; if (l > 0) { int i1 = -100; numAdjacentSources = 0; i1 = getSmallestFlowDecay(world, i - 1, j, k, i1); i1 = getSmallestFlowDecay(world, i + 1, j, k, i1); i1 = getSmallestFlowDecay(world, i, j, k - 1, i1); i1 = getSmallestFlowDecay(world, i, j, k + 1, i1); int j1 = i1 + byte0; if (j1 >= 8 || i1 < 0) { j1 = -1; } if (getFlowDecay(world, i, j + 1, k) >= 0) { int l1 = getFlowDecay(world, i, j + 1, k); if (l1 >= 8) { j1 = l1; } else { j1 = l1 + 8; } } if (numAdjacentSources >= 2 && blockMaterial == Material.water) { if (world.getBlockMaterial(i, j - 1, k).isSolid()) { j1 = 0; } else if (world.getBlockMaterial(i, j - 1, k) == blockMaterial && world.getBlockMetadata(i, j, k) == 0) { j1 = 0; } } if (blockMaterial == Material.lava && l < 8 && j1 < 8 && j1 > l && random.nextInt(4) != 0) { j1 = l; flag = false; } if (j1 != l) { l = j1; if (l < 0) { world.setBlockWithNotify(i, j, k, 0); } else { world.setBlockMetadataWithNotify(i, j, k, l); world.scheduleBlockUpdate(i, j, k, blockID, tickRate()); world.notifyBlocksOfNeighborChange(i, j, k, blockID); } } else if (flag) { updateFlow(world, i, j, k); } } else { updateFlow(world, i, j, k); } if (liquidCanDisplaceBlock(world, i, j - 1, k)) { if (blockMaterial == Material.lava && world.getBlockMaterial(i, j - 1, k) == Material.water) { world.setBlockWithNotify(i, j - 1, k, Block.stone.blockID); triggerLavaMixEffects(world, i, j - 1, k); return; } if (l >= 8) { world.setBlockAndMetadataWithNotify(i, j - 1, k, blockID, l); } else { world.setBlockAndMetadataWithNotify(i, j - 1, k, blockID, l + 8); } } else if (l >= 0 && (l == 0 || blockBlocksFlow(world, i, j - 1, k))) { boolean aflag[] = getOptimalFlowDirections(world, i, j, k); int k1 = l + byte0; if (l >= 8) { k1 = 1; } if (k1 >= 8) { return; } if (aflag[0]) { flowIntoBlock(world, i - 1, j, k, k1); } if (aflag[1]) { flowIntoBlock(world, i + 1, j, k, k1); } if (aflag[2]) { flowIntoBlock(world, i, j, k - 1, k1); } if (aflag[3]) { flowIntoBlock(world, i, j, k + 1, k1); } } } private void flowIntoBlock(World world, int i, int j, int k, int l) { if (liquidCanDisplaceBlock(world, i, j, k)) { int i1 = world.getBlockId(i, j, k); if (i1 > 0) { if (blockMaterial == Material.lava) { triggerLavaMixEffects(world, i, j, k); } else { Block.blocksList[i1].dropBlockAsItem(world, i, j, k, world.getBlockMetadata(i, j, k), 0); } } world.setBlockAndMetadataWithNotify(i, j, k, blockID, l); } } private int calculateFlowCost(World world, int i, int j, int k, int l, int i1) { int j1 = 1000; for (int k1 = 0; k1 < 4; k1++) { if (k1 == 0 && i1 == 1 || k1 == 1 && i1 == 0 || k1 == 2 && i1 == 3 || k1 == 3 && i1 == 2) { continue; } int l1 = i; int i2 = j; int j2 = k; if (k1 == 0) { l1--; } if (k1 == 1) { l1++; } if (k1 == 2) { j2--; } if (k1 == 3) { j2++; } if (blockBlocksFlow(world, l1, i2, j2) || world.getBlockMaterial(l1, i2, j2) == blockMaterial && world.getBlockMetadata(l1, i2, j2) == 0) { continue; } if (!blockBlocksFlow(world, l1, i2 - 1, j2)) { return l; } if (l >= 4) { continue; } int k2 = calculateFlowCost(world, l1, i2, j2, l + 1, k1); if (k2 < j1) { j1 = k2; } } return j1; } private boolean[] getOptimalFlowDirections(World world, int i, int j, int k) { for (int l = 0; l < 4; l++) { flowCost[l] = 1000; int j1 = i; int i2 = j; int j2 = k; if (l == 0) { j1--; } if (l == 1) { j1++; } if (l == 2) { j2--; } if (l == 3) { j2++; } if (blockBlocksFlow(world, j1, i2, j2) || world.getBlockMaterial(j1, i2, j2) == blockMaterial && world.getBlockMetadata(j1, i2, j2) == 0) { continue; } if (!blockBlocksFlow(world, j1, i2 - 1, j2)) { flowCost[l] = 0; } else { flowCost[l] = calculateFlowCost(world, j1, i2, j2, 1, l); } } int i1 = flowCost[0]; for (int k1 = 1; k1 < 4; k1++) { if (flowCost[k1] < i1) { i1 = flowCost[k1]; } } for (int l1 = 0; l1 < 4; l1++) { isOptimalFlowDirection[l1] = flowCost[l1] == i1; } return isOptimalFlowDirection; } private boolean blockBlocksFlow(World world, int i, int j, int k) { int l = world.getBlockId(i, j, k); if (l == Block.doorWood.blockID || l == Block.doorSteel.blockID || l == Block.signPost.blockID || l == Block.ladder.blockID || l == Block.reed.blockID) { return true; } if (l == 0) { return false; } Material material = Block.blocksList[l].blockMaterial; if (material == Material.portal) { return true; } return material.blocksMovement(); } protected int getSmallestFlowDecay(World world, int i, int j, int k, int l) { int i1 = getFlowDecay(world, i, j, k); if (i1 < 0) { return l; } if (i1 == 0) { numAdjacentSources++; } if (i1 >= 8) { i1 = 0; } return l >= 0 && i1 >= l ? l : i1; } private boolean liquidCanDisplaceBlock(World world, int i, int j, int k) { Material material = world.getBlockMaterial(i, j, k); if (material == blockMaterial) { return false; } if (material == Material.lava) { return false; } else { return !blockBlocksFlow(world, i, j, k); } } public void onBlockAdded(World world, int i, int j, int k) { super.onBlockAdded(world, i, j, k); if (world.getBlockId(i, j, k) == blockID) { world.scheduleBlockUpdate(i, j, k, blockID, tickRate()); } } }
BlockStationaryHogeクラスを作成[編集]
長々と書きますがやってることは単純です。 既存の「BlockStationary」クラスをコピペし、クラス名に依存してる部分修正。
package net.minecraft.src; import java.util.Random; public class BlockStationaryHoge extends BlockFluid { protected BlockStationaryHoge(int i, Material material) { super(i, material); setTickOnLoad(false); if (material == Material.lava) { setTickOnLoad(true); } } /* *コピペだけじゃ芸がないので、ここ液体の色を設定できます。 */ public int colorMultiplier(IBlockAccess iblockaccess, int i, int j, int k) { return 0xffffff; } public void onNeighborBlockChange(World world, int i, int j, int k, int l) { super.onNeighborBlockChange(world, i, j, k, l); if (world.getBlockId(i, j, k) == blockID) { setNotStationary(world, i, j, k); } } private void setNotStationary(World world, int i, int j, int k) { int l = world.getBlockMetadata(i, j, k); world.editingBlocks = true; world.setBlockAndMetadata(i, j, k, blockID - 1, l); world.markBlocksDirty(i, j, k, i, j, k); world.scheduleBlockUpdate(i, j, k, blockID - 1, tickRate()); world.editingBlocks = false; } public void updateTick(World world, int i, int j, int k, Random random) { if (blockMaterial == Material.lava) { int l = random.nextInt(3); for (int i1 = 0; i1 < l; i1++) { i += random.nextInt(3) - 1; j++; k += random.nextInt(3) - 1; int j1 = world.getBlockId(i, j, k); if (j1 == 0) { if (isFlammable(world, i - 1, j, k) || isFlammable(world, i + 1, j, k) || isFlammable(world, i, j, k - 1) || isFlammable(world, i, j, k + 1) || isFlammable(world, i, j - 1, k) || isFlammable(world, i, j + 1, k)) { world.setBlockWithNotify(i, j, k, Block.fire.blockID); return; } continue; } if (Block.blocksList[j1].blockMaterial.blocksMovement()) { return; } } } } private boolean isFlammable(World world, int i, int j, int k) { return world.getBlockMaterial(i, j, k).getCanBurn(); } }