提供: 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();
    }
}