提供: Minecraft Modding Wiki
移動先: 案内検索
(clolrMultiplier追加)
1行目: 1行目:
このページは<br/>
+
{{前提MOD|reqmod=ModLoader}}
ModLoaderを前提としています。
 
 
 
 
==ソース解説==
 
==ソース解説==
  
180行目: 178行目:
 
             if (blockMaterial == Material.lava && world.getBlockMaterial(i, j - 1, k) == Material.water)
 
             if (blockMaterial == Material.lava && world.getBlockMaterial(i, j - 1, k) == Material.water)
 
             {
 
             {
                 world.setBlockWithNotify(i, j - 1, k, Block.stone.blockID);
+
                 world.setBlockWithNotify(
                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());
 
        }
 
    }
 
}
 
</source>
 
 
 
===BlockStationaryHogeクラスを作成===
 
長々と書きますがやってることは単純です。
 
既存の「BlockStationary」クラスをコピペし、クラス名に依存してる部分修正。
 
<source lang="java">
 
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();
 
    }
 
}
 
</source>
 
 
 
<comments />
 

2012年3月22日 (木) 08:03時点における版

この記事は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」クラスをコピペし、クラス名に依存してる部分修正。 <source lang="java"> 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(