跑跑车游戏网
游戏
网游单机小游戏专题排行榜攻略资讯评测
软件
11应用专题排行榜教程
关于
广告合作网站地图意见反馈

我的世界工业2实验版作物架植物生长速度详解

佚名2016/01/15评论 (0)

  小编为大家带来了《我的世界》工业2实验版作物架植物生长速度详解,作物架,在代码中是一个名字为TileEntityCrop的类,顾名思义是一个TileEntity。TileEntity会在被加载的每个tick被调用一次updateEntity()方法,因此我们先来看看TileEntityCrop的updateEntity()方法(TileEntityCrop.txt, 行139~行162):

super.updateEntity();

this.ticker = ((char) (this.ticker + '\001'));

if ((this.ticker % tickRate) == 0) {

    tick();

}

if (this.dirty) {

    this.dirty = false;

    this.worldObj.markBlockForUpdate(this.xCoord, this.yCoord, this.zCoord);

    this.worldObj.updateLightByType(EnumSkyBlock.Block, this.xCoord, this.yCoord, this.zCoord);

    if ((IC2.platform.isSimulating()) && (!IC2.platform.isRendering())) {

        for (String field : getNetworkedFields()) {

            ((NetworkManager) IC2.network.get()).updateTileEntityField(this, field);

        }

    }

}

复制代码

第一行调用了父类TileEntity的更新方法,不管它;if (this.dirty) {...} 这里处理的是光照计算、电网计算,和作物生长也没有直接联系;我们主要看中间部分:ticker域每tick加1,tickRate是一个等于256的常数。因此中间部分的作用,就是每256tick调用一次tick()方法。所以接下来我们来看看tick()方法,先看前半部分(TileEntityCrop.txt, 行182~行192):

if ((this.ticker % (tickRate << 2)) == 0) {

    this.humidity = updateHumidity();

}

if (((this.ticker + tickRate) % (tickRate << 2)) == 0) {

    this.nutrients = updateNutrients();

}

if (((this.ticker + (tickRate * 2)) % (tickRate << 2)) == 0) {

    this.airQuality = updateAirQuality();

}

复制代码

这里点出了影响作物生长速度的三大因素:湿度、营养和空气质量。这三个参数都是每1024个tick(即51.2s)更新一次。我们来一个一个看看它们的具体计算方式。

首先是湿度(humidity)。也就是updateHumidity()方法(TileEntityCrop.txt, 行910~行924):

int value = Crops.instance.getHumidityBiomeBonus(this.worldObj.getBiomeGenForCoords(this.xCoord, this.zCoord));

if (this.worldObj.getBlockMetadata(this.xCoord, this.yCoord - 1,this.zCoord) >= 7) {

    value += 2;

}

if (this.waterStorage >= 5) {

    value += 2;

}

value += ((this.waterStorage + 24) / 25);

return (byte) value;

复制代码

这个value的初始值,不知道是我没研究清楚还是IC本来就还没来得及做这一块内容,根据IC2Crops类的内容,后面的一长串东西似乎一直是0。也就是说湿度不受生物群系影响(我也觉得很奇怪,具体有待核实,希望有能力的同学帮我看一看)。因此重点看后面的。"this.worldObj.getBlockMetadata(this.xCoord, this.yCoord - 1,this.zCoord) >= 7"这个判断条件,是判断作物下方的泥土是否是耕地,如果是耕地,湿度加2;waterStorage和浇水有关,如果不浇水就一直是0;如果浇了水,水浇得越多湿度越大。

第二个因素是营养。这里是updateNutrients()方法(TileEntityCrop.txt, 行928~行941):

int value = Crops.instance.getNutrientBiomeBonus(this.worldObj.getBiomeGenForCoords(this.xCoord, this.zCoord));

for (int i = 2; i < 5; i++) {

    if (this.worldObj.getBlock(this.xCoord, this.yCoord - i, this.zCoord) != Blocks.dirt) {

        break;

    }

    value++;

}

value += ((this.nutrientStorage + 19) / 20);

return (byte) value;

复制代码

“Crops.instance.getNutrientBiomeBonus(this.worldObj.getBiomeGenForCoords(this.xCoord, this.zCoord))”这一长串和湿度部分的那些很相似,但是根据IC2Crops类,生物群系却是会影响营养值的,具体请看IC2Crops.txt的第82~94行。第二部分是在检测作物下方的泥土深度。如果泥土深度2层就+1,深度三层就+2,4层就+3。最后一部分是和肥料有关,肥料越多营养值越高。

最后一个影响因素是空气质量。请看updateAirQuality()方法(TileEntityCrop.txt, 行945~行979):

int value = 0;

int height = (this.yCoord - 64) / 15;

if (height > 4) {

    height = 4;

}

if (height < 0) {

    height = 0;

}

value += height;

int fresh = 9;

for (int x = this.xCoord - 1; (x < (this.xCoord + 1)) && (fresh > 0); x++) {

    for (int z = this.zCoord - 1; (z < (this.zCoord + 1)) && (fresh > 0); z++) {

        if ((this.worldObj.isBlockNormalCubeDefault(x, this.yCoord, z, false)) || (this.worldObj.getTileEntity(x, this.yCoord, z) instanceof TileEntityCrop)) {

            fresh--;

        }

    }

}

value += (fresh / 2);

if (this.worldObj.canBlockSeeTheSky(this.xCoord, this.yCoord + 1, this.zCoord)) {

    value += 2;

}

return (byte) value;

复制代码

首先是和高度有关,当高度为124以上时空气质量+4,为109~123时+3,为94~122时+2,为79~93时+1,否则+0。也就是说高度越高空气质量越好。其次,周围的方块也会影响空气质量。不过这里IC开发组的代码似乎又写错了,它的本意fresh值初始为9,它周围3*3的区域每有一个是普通方块或者作物时fresh值-1,然后空气质量加上fresh除以二向下取整。但是它的循环语句写错了,实际上只检测了2*2的范围。最后,它还检测了这个方块"能否看到天空",机制和检测太阳能发电机能否工作是相同的;如果能看到天空,则空气质量+2。

知道了这三个因素的计算方法之后,我们回到tick()方法(TileEntityCrop.txt,行213~行225):

if (this.crop.canGrow(this)) {

    this.growthPoints += calcGrowthRate();

    if (this.crop == null) {

        return;

    }

    if (this.growthPoints >= this.crop.growthDuration(this)) {

        this.growthPoints = 0;

        this.size += 1;

        this.dirty = true;

    }

}

复制代码

作物的canGrow()方法,对于常规作物一般是直接返回true的,我们也默认它是true了。可以看到作物有个growthPoints属性,每次增加calcGrowthRate()方法返回的值。如果growthPoints达到了作物的growthDuration(this),则计算为生长了一个阶段。

首先来看看calcGrowthRate()方法,它是对几个生长因素(湿度、营养、空气质量、作物本身属性)的综合计算(TileEntityCrop.txt,行1014~行1046):

if (this.crop == null) {

    return 0;

}

int base = 3 + IC2.random.nextInt(7) + this.statGrowth;

int need = ((this.crop.tier() - 1) * 4) + this.statGrowth + this.statGain + this.statResistance;

if (need < 0) {

    need = 0;

}

int have = this.crop.weightInfluences(this, getHumidity(), getNutrients(), getAirQuality()) * 5;

if (have >= need) {

    base = (base * (100 + (have - need))) / 100;

} else {

    int neg = (need - have) * 4;

    if ((neg > 100) && (IC2.random.nextInt(32) > this.statResistance)) {

        reset();

        base = 0;

    } else {

        base = (base * (100 - neg)) / 100;

        if (base < 0) {

            base = 0;

        }

    }

}

return base;

复制代码

这里的tier()是物种的本身属性,只能通过代码看到,最常见的小麦、南瓜等是一级作物,而马铃薯、胡萝卜、西瓜、甘蔗等则是二级作物。这里的statGrowth(生长)\statGain(收获)\statResistance(抗性)是这个作物的属性,可以用作物分析仪看到,作弊模式下也可以使用NBT Edit查看,对于天然作物默认为1。base值等于一个3~9的随机数加上作物的生长速度属性(天然植物默认为1),代表着作物本身的生长速度;need值等于作物的三围之和加上(作物等级-1)*4,说明作物越高阶、属性越好,对生长环境的要求也越高;have值等于湿度、营养、空气质量这些外部环境对作物的影响程度*5,代表外部生长环境。具体的计算因不同作物而异,对于一般的作物就是等于湿度、营养、空气质量三项之和。

后面是base,need,have的具体计算。这个还是看代码比较直观一些。当have<need时,作物有几率枯萎,枯萎率和作物的抗性有关。一般情况下have>=need,此时一次tick()增加的growthPoint就是"(base*(100+(have-need)))/100"。

growthPoint计算出来了,接下来就是计算作物的growthDuration,这是作物的本身属性。一般来说就是作物的等级*200。

至于生长阶段,不同的作物也是不一样的。其中比较有趣的是马铃薯,它的生长阶段是4段,从第三阶段开始允许收获。第三阶段是生马铃薯,第四阶段收获下来就变成毒马铃薯了。如果需要毒马铃薯来做杀虫剂,不妨多种点马铃薯,然后放很久不去管它,过一会儿就变成毒马铃薯了。

我现在终于知道,那些看起来花哨的新MOD,玩起来不知怎的总是不如老MOD带劲儿:农业只是IC中比较冷门的一个部分,而作物生长速度更是IC的农业部分中一个很小的环节。然而就是这么看似微不足道的东西,却涉及到了好几页的代码,牵扯到了无数的影响因素;那些新兴MOD想要做到像IC这种经典MOD那样丰富、有趣、富有内涵,还是需要一段时间的积淀和完善才行啊。

上一篇我的世界渲染作品美图第二十二弹

下一篇我的世界生存教程火力全开

网友评论
取消

累计评论0

展开其余评论

相关阅读

上滑或点击查看更多...