本帖最后由 heidada 于 2011-5-12 21:33 编辑

首先我阅读了这个教程的大概的内容,我觉得这对我来说是个很大的挑战,不管结果如何我觉得还是要把这个文章翻译出来,因为我觉得我的抛砖引玉能够激起未来的轩然大波。不幸的是首先我不懂JAVA,没有进行过任何JAVA的编程经验,虽然我少年时候的理想是做个编游戏的人,你知道,有的时候理想总是远离现实。其次我的英文确实够次,斗胆翻译这个文章我觉得我可能会误人子弟,呵呵!好吧不管怎么说我决定做第一个吃螃蟹的人啦!!!再次我觉得制作MOD需要很多专业知识,我可能真的不够格,我自己也没有任何实践,希望有错误的时候大家耐心指导,拍砖什么的我无所谓,我脸皮够厚,所以大家就省了,有错误就点评指出吧……我虚心接受。

本贴持续更新中……给出原帖地址心急的童鞋可以自己去看哈~

另外说句题外话,我为什么要极力推荐MC这个游戏,因为这个游戏是我有史以来见到最牛逼的游戏,它产生的意义是跨时代的,也是我梦想中想要制作的游戏!他可以借助简单的物品合成原理制造世界,我向很多人推荐这个游戏时候他们总是以画面太烂而放弃玩这个游戏,我知道,现在很多玩家以游戏画面作为评判一个游戏的标准,我得说,这是无知。当年的神作即时战略鼻祖沙丘魔堡2出来的时候那画面用现在的话说就是一坨屎啊!但是其意义影响到现在,星际,魔兽,红警,帝国,那个敢说其作品里没有DUNE2的血??!minecraft,它将是未来游戏发展的趋势,我断言,未来10年内,这个游戏的子孙后代将大量繁衍,衍生出新鲜的血液,如同QUAKE当年不走红CS却走红一样道理。为什么我盛赞这个游戏,因为,未来你可以在这个世界里创造所有能创造的东西,甚至一些现实社会不能创造的东西,这根本就是虚拟现实世界的伟大一步。请大家也记住我,一个伟大的预言家~~大大哥!!




第一节、准备工作和流程解释
(牛X的同学可以略过这节,不过我真不相信有人那么牛X,如果你牛X请快现身吧!!)
一、准备工作和需求
好了,废话这么多该开始了,首先讲下需求,要想制作MINECRAFT的MOD,以下四条一定要有:
1.Java Development Kit 6 (JDK6) 大概78MJDK下载地址   
2.minecraft编码包,这里我下载了MCP2.9A版本的编码包,因为他是对应1.3.01BETA版本的对应编码包,如果大家有相应的版本请去MCP编码包汇总下载地址查找自己想要的软件包
3.EditPlus/Notepad++/Eclipse/Netbeans (文本编辑语法高亮)
4.编程知识,优秀的JAVA编程技术~呵呵,我看到这里就呆了,我知道我应该可以知难而退了

二、如何开始
1.1首先安装编码包MCP1.2解压缩ZIP文件包到你电脑上的目录比如C:\MCP

1.2解压缩压缩包到电脑,比如C:\MCP
1.3复制整个 .minecraft/bin 和 .minecraft/resources目录到C:\MCP\JAR下.
1.4运行decompile.bat

打开两个窗口,一个是 C:\MCP\sources\minecraft\net\minecraft\src the other to
                另一个是 C:\MCP\

三、MODS的运行
要运行您的MODS的你首先需要编译,调试和测试。
1.首先编译运行'recompile.bat'所有的minecraft类文件。
2.转到C:C:\MCP\logs\minecraft_compile.log 和搜索 ^,如果没有找到这个字,则没有编译错误。如果有,你需要修复您的代码中的错误,并尝试重新编译。
3.如果没有错误,运行'test_game.bat'。
4.这将弹出一个已经安装了MOD的minecraft替代版本-用来测试你的mod。


一旦你的MOD编辑完毕,你需要代码混淆(Obfuscated code是:將電腦程式的代碼,轉換成一種功能上等價,但是難於閱讀和理解的形式的行為。

使之可以放入MINECRAFT.JAR里

四、使用Eclipse

你可以使用Eclipse来写你的MOD,调试编码,编译编码,运行编码,当你长时间调试时,它会跟你省下很多时间。
http://v.youku.com/v_show/id_XMjU5Nzc3Njk2.html
ECLIPSE使用视频地址稍后发上来……需要搬运

五、模糊编码(obfuscate暂时翻译为模糊编码好了,希望有人给我指点专业解释
模糊编码允许你的MOD可以在MINECRAFT.JAR运行,并可以被任何人使用
1.打开C:\MCP\conf\client_conf.txt
2.删除文本里所有的东西
3.添加你的class(class是java编译好的类型文件)到文件里,举例如下:

  1. BlockExample
  2. Block
  3. CraftingManager
复制代码
4.运行'reobf.bat'这个文件
5.你生成的class文件将全部放在C:\MCP\final_out\minecraft\目录下,你可以把这些做好的MOD放到MINECRAFT.JAR里面就可以玩自己的MOD了

额~!好了,上面的其实都是一些准备工作,是为了让大家了解真个流程和需要做的准备工作,下面开始就是真家伙了,程序怎么写就看下面的了



第二节、制造新的方块类型

这节我们学习如何制造一个新方块,并且怎么用工作台合成它,这里我们给出程序怎么做一个像石头一样的方块
1.你需要一个叫做BlockExample.java的新文件,并且放置其再src目录下
2.程序语言结构如下:
  1. package net.minecraft.src;

  2. import java.util.Random;

  3. public class BlockExample extends Block
  4. {
  5. public BlockExample(int i, int j)
  6. {
  7. super(i, j, Material.rock);
  8. }

  9. public int idDropped(int i, Random random)
  10. {
  11. return 0;
  12. }
  13. }

复制代码
该死的作者没有解释上面语句是用来干什么的,没关系,抄作业这个我行,不用懂题目怎么做,达到交作业的目的就行 XD
3.现在你需要把这个块添加到程序里以便让程序可以调用,因此,需要打开block.java(俺不知道这个文件放哪里,请实际操作过的同学告诉我)
4.你可以看见文件底部有一大堆对于变量的声明,好吧,我们加上我们的声明
  1. public static final Block example;
复制代码
5.下面你可以看见对于声明的变量初始化,初始化你的方块,语句如下:
  1. example = (new BlockExample(92, 1)).setHardness(1.5F).setResistance(10F).setStepSound(soundStoneFootstep);
复制代码
如我们之前提到的,我们制造了一个新的石头方块
new BlockExample(92, 1)这句的意思是,创造一个新方块,方块ID为92(物品编号是不可以和已经存在的物品重复的,所以你最好参看我另外一个教程编号的可选取数字范围是什么),方块的图片编号为1,也就是说图片和石头的图片一样
setHardness(1.5F)是设置石头硬度和石头一样,硬度就是你需要多久可以破坏石块的时间参数
setResistance(10F)是抗性参数,也就是你的石头对于爆炸的抗性
setStepSound(soundStoneFootstep)是你走在该方块上时候的声音,这里设置和石头一样

这就搞定了方块的创建,哈哈,看似简单啊,不知道实际操作有啥难度,同学们自己尝试去吧,我看热闹~这样创建出来的方块可以使用单机命令或者OP的命令调出来/give 92,你懂的……

下面是关于这个方块的合成语句编写
1.打开CraftingManager.java
2.你可以立即从这个class文件的结构表里找到添加合成菜单功能(addRecipe function)这一项
3.找到这个文件的最后一行然后加入我们的合成菜单公式

  1. addRecipe(new ItemStack(Block.example, 1), new Object[] {"##", "##", Character.valueOf('#'), Block.dirt});
复制代码
这句不难,意思是4块土可以合成一个你制造的新方块
new ItemStack(Block.example, 1)这句表示将生成什么方块,1代表数量
new Object[] {"##", "##", Character.valueOf('#'), Block.dirt}表示这个物品如何合成,相信##,##是代表第一行放2个#第二行也放2个#,后面是对#这个物品的定义,给出的是土块,也就是说由4个土块合成,合成的摆放如下
[dirt] [dirt]
[dirt] [dirt]




第三节、创建新物品类型
1.你需要在scr目录下创建一个新文件ItemExample.java
2.语法结构如下:

  1. package net.minecraft.src;

  2. public class ItemExample extends Item
  3. {
  4.     public ItemFood(int i)
  5.     {
  6.         super(i);
  7.         maxStackSize = 64;
  8.     }

  9.     public ItemStack onItemRightClick(ItemStack itemstack, World world, EntityPlayer entityplayer)
  10.     {
  11.     }
  12. }
复制代码
3.添加该物品到物品清单里,打开item.java这个文件
4.找到文件底部大量的实例变量处,添加一个新的变量
  1. public static Item example = (new ItemExample(95)).setIconIndex(42);
复制代码

这样的话,你将建立一个新的物品,编号ID为256+95,这里我不明白为什么是256+95,还请高手来指点。物品的图像时42号。因此看起来像是一个标志,这个物品没有任何属性,也不能组合得到。但当你编译并运行MOD后会发现这个新物品。


额~原帖的观众提问(1)一起翻译吧,我想应该会碰到同样问题……
THX的这个教程,但是我卡在“recompile.bat“,因为当我运行它,它说:

Thx for this tutorial, but Im stuck at "recompile.bat" because when I run it, it says:

Finding javac.exe... if you want to speed this up, add it to your PATH
'C:\Users\Hypothawits\minecraft' is not recognized as an internal or external command
,
operable program or batch file.
Path set.
Unable to locate javac.exe. Please verify that it is in the PATH.
If you don't know where to get it, please visit
http://www.oracle.com/technetwor
k/java/javase/downloads/index.html and download a JDK.
Press any key to continue . . .
提问者不知道如何更换路径
回答如下
作者说,我想你应该没有足够的程序知识,最基本的应该添加JAVAC到指定路径,GOOGLE可以帮你(我X,等于没说)
例如...这里有一个地址:http://www.phoons.com/john/classes/aboutpath.html
你可以通过键入javac这样一个命令外壳/提示符来测试是否配置正确~~


额~前两天一直无法登陆论坛就把这个帖子放这里了,23日今夜继续

观众提问(2)
观众提问真的是很有意思的一个环节,这里有一个观众提问非常有意思
ManxAndrew小朋友提问到:好吧,我一直在研究我的标枪~你帮我看看我的尝试

  1. package net.minecraft.src;
  2. // Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.
  3. // Jad home page: http://www.kpdus.com/jad.html
  4. // Decompiler options: packimports(3) braces deadcode


  5. public class ItemSpear extends Item
  6. {

  7.     public ItemSpear(int i, int j)
  8.     {
  9.         super(i);
  10.         maxStackSize = 1;
  11.         maxDamage = 44 << j;
  12.         if(j == 3)
  13.         {
  14.             maxDamage *= 4;
  15.         }
  16.         weaponDamage = 4 + j * 2;
  17.     }

  18.     public float getStrVsBlock(ItemStack itemstack, Block block)
  19.     {
  20.         return 1.5F;
  21.     }

  22.     public void hitEntity(ItemStack itemstack, EntityLiving entityliving)
  23.     {
  24.         itemstack.damageItem(1);
  25.     }

  26.     public void hitBlock(ItemStack itemstack, int i, int j, int k, int l)
  27.     {
  28.         itemstack.damageItem(4);
  29.     }

  30.     public int getDamageVsEntity(Entity entity)
  31.     {
  32.         return weaponDamage;
  33.     }

  34.     public boolean isFull3D()
  35.     {
  36.         return true;
  37.     }

  38.     private int weaponDamage;
  39. }
复制代码
文件名 ItemSpear.java
然后是合成菜单公式一个X两个#自左上向右下排列:
  1. craftingmanager.addRecipe(new ItemStack(Item.spear, 1), new Object[] {
  2.        "  X", " # ", "#  ", Character.valueOf('X'), Item.flint, Character.valueOf('#'), Item.sticks
  3.    });
复制代码
下面的合成公式放在RecipesWeapons.java里
最后加上如下程序
  1. public static Item spear (new ItemSpear(101, 0)).setIconIndex(53);
复制代码
唯一看的懂的一句,给出物品代码并赋予图标
做好了以后看起来就像一个棒棒,那又如何?观众很幽默

不过观众问:我重新编译了以后,为什么没有作用,并且已经重新代码混淆,放入minecraft.jar里面也没有效果?怎么办涅?
楼主回答:不知道你有没有看我那篇关于编译日志的文章~
我COPY了你的代码重新编译,发现在编译日志里面有一个错误说"Item.sticks" not found,于是我修改了你文件名为"Item.stick"就搞定了
合成图片如下

同时我也发现你使用了MODLOADER处理craftingmanager.addRecipe(...) ,我没有使用过这个层次的软件,所以我不知道它和MCP是否兼容良好,如果再有问题估计就是上面情况造成的……目前代码都OK可以用了


观众又问,我修改了图片,可发现没用
作者说,你修改的图片路径应该是/temp/minecraft/gui/item.png file.



第四节 制作一个用于火炉的新方块类型

这一节我们学习如何制作一个新的方块类型用于可以在火炉里燃烧的材料,因为功能的需要我们需要把物品加入到火炉燃料类型里。如果你的新方块类型是按照前面的课程制作的,现在你需要做的就是把它转化成一个可熔炼物品。
这里一共需要3个步骤
1、查找火炉定义
首先你需要找到“TileEntityFurnace.java”这个文件,该文件放置于MINECRAFT的SRC目录下。这个文件的位置比较靠下,为了方便查找,你可以使用按T键的方式进行快速检索。
2、定位并增加新定义
"TileEntityFurnace.java"文件里找到"private int getSmeltingResultItem(int i)"这个语句
在这里你可以添加关于你的可熔炼物品的状态。确定你已经有了一个新方块,现在我们需要做的就是把你已经做好的方块和将要熔炼出来的方块做一个信息链接。这将和前面讲的实例有一个连接
  1.     private int getSmeltingResultItem(int i)
  2.     {
  3.         if(i == Block.oreIron.blockID)
  4.         {
  5.             return Item.ingotIron.shiftedIndex;
  6.         }
  7.         if(i == Block.oreGold.blockID)
  8.         {
  9.             return Item.ingotGold.shiftedIndex;
  10.         }
  11.         if(i == Block.oreDiamond.blockID)
  12.         {
  13.             return Item.diamond.shiftedIndex;
  14.         }
  15.         if(i == Block.sand.blockID)
  16.         {
  17.             return Block.glass.blockID;
  18.         }
  19.         if(i == Item.porkRaw.shiftedIndex)
  20.         {
  21.             return Item.porkCooked.shiftedIndex;
  22.         }
  23.         if(i == Item.fishRaw.shiftedIndex)
  24.         {
  25.             return Item.fishCooked.shiftedIndex;
  26.         }
  27.         if(i == Block.cobblestone.blockID)
  28.         {
  29.             return Block.stone.blockID;
  30.         }
  31.         if(i == Item.clay.shiftedIndex)
  32.         {
  33.             return Item.brick.shiftedIndex;
  34.         }
  35.         if(i == Block.example.blockID)
  36.         {
  37.             return Item.example.shiftedIndex;
  38.         } else
  39.         {
  40.             return -1;
  41.         }
  42.     }
复制代码

基于之前的三节课,我们物品名字最好和之前的有一个继承,这样在使用起来更加的方便不会造成混淆。定义物体名字的时候最好有相应的实体类型,比方说你要创造方块,那么你最好物品类型前面加BLOCK,如果是物品,那么你最好都加上ITEM这样的单词,这样一方面便于修改也方面查找,相信编程序的人都知道,这是一个好的习惯。(如BlockBronze, ItemBronzeIngot)
      
  1. if(i == Block.example.blockID)
  2.         {
  3.             return Item.example.shiftedIndex;
  4.         }
复制代码

如果遗漏上面的语句,此语句是关于最后生成熔炼物品的语句,此句是用于定义火炉将方块类型烧成物品类型的关键语句。务必将次语句加在最后一组if和else之间。

3、完成物品并赋予真实物品名
在范例里面我们对于物品名和方块名都采用“Example”的命名方式。这里我们再重复以上步骤方面理解,你可以注意到第一行是方块类型,第二行是物品类型。需要注意的是,你必须重复多个步骤以保证分别创造了方块和物品两个东西。

我们定义(方块类型) BlockOre在Block.java这个文件里

  1. public static final Block blockBronze;
复制代码
同时在方块类型里定义方块的静态属性
  1. blockBronze = (new BlockOre(92, 113)).setHardness(3F).setResistance(5F).setStepSound(soundStoneFootstep);
复制代码

请注意:92是物品的ID,113是调用图片“terrain.png”中的铁块,这里没必要在BLOCK.JAVA文件里添加新方块类型,因为是举例嘛,当然如果你需要制作自己的MOD的时候就需要自己创建一些列的东西啦

新方块和新的金属锭物品

现在我们在ITEM.JAVA里定义新物品
  1. public static Item ingotBronze = (new Item(95)).setIconIndex(60);
复制代码

请注意:95是物品ID,60是调用图片“/gui/items.png”同样这里我们也没有添加任何新的物品类型而只是直接调用item.java里已经有的资料而已,当然你如果要自己闯将新MOD,自然要自己开发啦。

现在我们已经正确的定义了物品和方块,物品已经添加进去。我们看下炉内的燃烧合成状况

最后,把为炉子定义的方块类型和物品类型添加到TileEntityFurnace.java这个文件中去

  1. private int getSmeltingResultItem(int i)
  2.     {
  3.         if(i == Block.blockBronze.blockID)
  4.         {
  5.             return Item.ingotBronze.shiftedIndex;
  6.         } else
  7.         {
  8.             return -1;
  9.         }
  10.     }
复制代码


第五节 制作一个新方块类型

在本教程中我将解释如何创建自定义块的行为,而不是默认的行为。这一切是基于并归结为在Block.class覆盖的方法。这样可以创建一些当点击是会有反馈动作的物品(见下面的例子),是一个具有红石电源功能,爆炸以及...基本上任何事情都有可能..(我想你懂的,你要你能搞出什么怪玩意就加上去吧)
可部署的房子
所以下面我将提供一个加入到我们的例子块类的功能,当此方块被点击后,方块将创建一个基本的房子。
明白什么意思么,当方块被放置后,一旦被点击将创建一个房子~~十分强大啊!!!
此代码将需要添加到BlockExample类里。
  1.    public void onBlockClicked(World world, int i, int j, int k, EntityPlayer entityplayer)
  2.    {
  3.       // Basic Building
  4.       int block = Block.wood.blockID;
  5.       int size = 5;
  6.       for (int i1 = 0; i1 < size; i1++)
  7.       {
  8.          for (int j1 = 0; j1 < size; j1++)
  9.          {
  10.             //Walls
  11.             // i == ++ k == 0
  12.             world.setBlockWithNotify(i+i1,j+j1,k,block);
  13.             // i == ++ k == 4
  14.             world.setBlockWithNotify(i+i1,j+j1,k+(size-1),block);
  15.             // i == 0 k == ++
  16.             world.setBlockWithNotify(i,j+j1,k+i1,block);
  17.             // i == 4 k == ++
  18.             world.setBlockWithNotify(i+(size-1),j+j1,k+i1,block);
  19.             
  20.             //Roof
  21.             world.setBlockWithNotify(i+i1,j+(size-1),k+j1,block);

  22.             //Floor
  23.             world.setBlockWithNotify(i+i1,j,k+j1,block);
  24.          }
  25.       }
  26.       //Door
  27.       world.setBlockWithNotify(i+1,j+2,k,0);
  28.       world.setBlockWithNotify(i+1,j+1,k,0);

  29.       //Windows
  30.       int offset = size % 2 == 0 ? (size / 2) - 1 : (size / 2);
  31.       world.setBlockWithNotify(i,j+offset,k+offset,Block.glass.blockID);
  32.       world.setBlockWithNotify(i+offset,j+offset,k,Block.glass.blockID);
  33.       world.setBlockWithNotify(i+(size-1),j+offset,k+offset,Block.glass.blockID);
  34.       world.setBlockWithNotify(i+offset,j+offset,k+(size-1),Block.glass.blockID);

  35.       //Utilities
  36.       world.setBlockWithNotify(i+1,j+1,k+(size-2),Block.crate.blockID);
  37.       world.setBlockWithNotify(i+(size-2),j+1,k+1,Block.workbench.blockID);
  38.       world.setBlockWithNotify(i+(size-2),j+1,k+(size-2),Block.stoneOvenIdle.blockID);
  39.    }
复制代码
但你搞完上面的代码,就可以得到一个如下的房子啦,凑合住还行吧,哈哈~~
[attach]4262[/attach][attach]4262[/attach][attach]4262[/attach]
此法可以通过覆盖方块类型文件创建诸如上图功能的方块。





































h7EtW.jpg (70.75 KB, 下载次数: 185)

h7EtW.jpg