电力方块
电力是原版的能量形式之一,大部分内容都需要电力的参与。电力的生产者为发电机(Generator),传输需要电力节点(PowerNode),存储需要电池(Battery),最终被方块中的电力槽(PowerModule)消耗,而电网(PowerGraph)承担了电力的调度工作。本节将介绍这些类型,给出示例代码,并介绍一些方块的元属性。
发电机
原版有七种具体的发电机,由同一个基类PowerGenerator统领。PowerGenerator类只拥有两个功能,一是在统计面板中显示发电量,二是在被摧毁后产生爆炸。而具体的发电方式由子类声明。通常来说,一个发电机的发电量是其基础发电量powerProduction与建筑发电效率productionEfficiency相乘得到的。
太阳能板(SolarGenerator)
太阳能板的建筑发电效率是由地图的光亮属性light决定的。其计算公式为太阳能电池板的发电倍率 * (地图环境light属性值 + 环境光颜色透明度)。此类型没有可以配置的属性。
solarPanel = new SolarGenerator("tutorial-solar-panel"){{
requirements(Category.power, ItemStack.with(Items.lead, 10, Items.silicon, 8));
powerProduction = 0.12f;
}};solarPanel = SolarGenerator("tutorial-solar-panel").apply{
requirements(Category.power, ItemStack.with(Items.lead, 10, Items.silicon, 8))
powerProduction = 0.12f
}地热发电机(ThermalGenerator)
根据下方地板的属性计算效率,就像工厂中的AttributeCrafter一样。可以设置最低工作效率minEfficiency。埃里克尔上的涡轮冷凝器也是一个“地热发电机”,这是由于蒸汽喷口也是一种属性(即steam),所以地热发电机也被Anuken赋予了outputLiquid字段。
thermalGenerator = new ThermalGenerator("tutorial-thermal-generator"){{
requirements(Category.power, with(Items.copper, 40));
size = 2;
//设置为floating是为了能放置在矿渣地板上
floating = true;
}};thermalGenerator = ThermalGenerator("tutorial-thermal-generator").apply{
requirements(Category.power, with(Items.copper, 40))
size = 2
//设置为floating是为了能放置在矿渣地板上
floating = true
}消耗发电机(ConsumeGenerator)
消耗发电机就是可以像工厂一样设置消耗器的发电机。使用itemDuration来设置消耗一个物品的时长。
发电机的消耗器更多的时候使用的是像ConsumeItemFlammable这样的筛选消耗器(ConsumeFilter)。筛选消耗器消耗的不是固定的某种物品或流体,而是一系列符合某一“标准”的许多物品或流体,比如火力发电机的ConsumeItemFlammable可以消耗的物品包括煤/硫/孢子荚/爆炸混合物,它的标准就是物品的可燃性至少要达到20%,像这样的消耗器还有:
ConsumeItemCharged:筛选物品“放电性”的大小;ConsumeItemExplosive:筛选物品“爆炸性”的大小;ConsumeItemRadioactive:筛选物品“放射性”的大小;ConsumeLiquidFlammable:筛选流体“可燃性”的大小;ConsumeItemExplode:检测物品爆炸性的大小,根据爆炸性对建筑造成伤害,并产生火焰,例如火力发电机。
在发电机中,这些消耗器会根据所消耗物品或流体的属性大小,动态地调整发电效率“倍率”。但是,调整倍率这一功能是发电机特有的,在工厂中即使使用筛选消耗器,也不会因物品属性大小改变实际效率。
这些消耗器原版并没有像普通消耗器一样封装接口,需要通过consume()方法注册。此外,发电机也可以使用普通消耗器,例如原版中的涡轮发电机就兼有ConsumeItemFlammable(消耗燃料)和ConsumeLiquid(消耗水)两个消耗器。
steamGenerator = new ConsumeGenerator("tutorial-steam-generator"){{
requirements(Category.power, with(Items.copper, 35));
powerProduction = 5.5f;
itemDuration = 90f;
consumeLiquid(Liquids.water, 0.1f);
hasLiquids = true;
size = 2;
consume(new ConsumeItemFlammable());
consume(new ConsumeItemExplode());
}}steamGenerator = new ConsumeGenerator("tutorial-steam-generator").apply{
requirements(Category.power, with(Items.copper, 35))
powerProduction = 5.5f
itemDuration = 90f
consumeLiquid(Liquids.water, 0.1f)
hasLiquids = true
size = 2
consume(new ConsumeItemFlammable())
consume(new ConsumeItemExplode())
}产热发电机(HeaterGenerator)、核反应堆(NuclearReactor)和不稳定反应堆(VariableReactor)
这三种发电机并列的原因是,他们都会产生热量,但是产热的逻辑和热量充满后的逻辑不同。
- 产热发电机(HeaterGenerator)的产热速度只与建筑效率有关,热量充满会忽略多余的热量;
- 核反应堆(NuclearReactor)的产热速度和发电量与内部
fuelItem的多少成正比,可以通过消耗流体降低热量,但这种冷却效果并不考虑冷却液的属性,而是由coolantPower字段定义的。核反应堆虽然有fuelItem属性,但是仍然要用消耗器去声明物品和冷却液消耗。热量充满后会产生爆炸,随着热量上升还会使建筑贴图逐渐变红; - 不稳定反应堆(VariableReactor)的热量与产热发电机相同,真正需要控制的是不稳定度。如果没有达到消耗器要求,就会增加不稳定度,且增加速度和减少速度为定值,当不稳定度充满后会产生爆炸。
核反应堆(NuclearReactor)和不稳定反应堆(VariableReactor)都设置了rebuildable这一属性。这一属性设置为false将禁止使用重建功能建造此方块。
neoplasiaReactor = new HeaterGenerator("tutorial-neoplasia-reactor"){{
requirements(Category.power, with(Items.tungsten, 750));
size = 5;
liquidCapacity = 80f;
outputLiquid = new LiquidStack(Liquids.neoplasm, 20f / 60f);
//当输出流体条满时爆炸
explodeOnFull = true;
heatOutput = 60f;
powerProduction = 140f;
itemDuration = 60f * 3f;
itemCapacity = 10;
consumeLiquid(Liquids.arkycite, 80f / 60f);
consumeLiquid(Liquids.water, 10f / 60f);
consumeItem(Items.phaseFabric);
}};
thoriumReactor = new NuclearReactor("tutorial-thorium-reactor"){{
requirements(Category.power, with(Items.lead, 300));
itemDuration = 360f;
powerProduction = 15f;
heating = 0.02f;
fuelItem = Items.thorium;
consumeItem(Items.thorium);
consumeLiquid(Liquids.cryofluid, heating / coolantPower).update(false);
}};
fluxReactor = new VariableReactor("tutorial-flux-reactor"){{
requirements(Category.power, with(Items.graphite, 300));
powerProduction = 265f;
maxHeat = 150f;
consumeLiquid(Liquids.cyanogen, 9f / 60f);
}};neoplasiaReactor = HeaterGenerator("tutorial-neoplasia-reactor").apply{
requirements(Category.power, with(Items.tungsten, 750))
size = 5
liquidCapacity = 80f
outputLiquid = new LiquidStack(Liquids.neoplasm, 20f / 60f)
//当输出流体条满时爆炸
explodeOnFull = true
heatOutput = 60f
powerProduction = 140f
itemDuration = 60f * 3f
itemCapacity = 10
consumeLiquid(Liquids.arkycite, 80f / 60f)
consumeLiquid(Liquids.water, 10f / 60f)
consumeItem(Items.phaseFabric)
}
thoriumReactor = NuclearReactor("tutorial-thorium-reactor").apply{
requirements(Category.power, with(Items.lead, 300))
itemDuration = 360f
powerProduction = 15f
heating = 0.02f
fuelItem = Items.thorium
consumeItem(Items.thorium)
consumeLiquid(Liquids.cryofluid, heating / coolantPower).update(false)
}
fluxReactor = VariableReactor("tutorial-flux-reactor").apply{
requirements(Category.power, with(Items.graphite, 300))
powerProduction = 265f
maxHeat = 150f
consumeLiquid(Liquids.cyanogen, 9f / 60f)
}冲击反应堆(ImpactReactor)
需要时间进行预热,这段时间需要电力输入。在冲击反应堆运行时,对电力输入从未停止,只是在计算实际发电量的时候扣除了耗电量。当消耗器和耗电无法满足时,会迅速把预热降到0。
impactReactor = new ImpactReactor("tutorial-impact-reactor"){{
requirements(Category.power, with(Items.lead, 500));
powerProduction = 130f;
itemDuration = 140f;
consumePower(25f);
consumeItem(Items.blastCompound);
consumeLiquid(Liquids.cryofluid, 0.25f);
}};impactReactor = ImpactReactor("tutorial-impact-reactor").apply{
requirements(Category.power, with(Items.lead, 500))
powerProduction = 130f
itemDuration = 140f
consumePower(25f)
consumeItem(Items.blastCompound)
consumeLiquid(Liquids.cryofluid, 0.25f)
}总结
到目前为此,我们已经见过十多种方块类型了,它们的类型(Kind)大致可分为三种:
- 通用类:一个类有工作的通用模板,在模板之上有一定的自定义空间,通常使用组件来拓展功能,例如通用工厂(
GenericCrafter),消耗发电机(ConsumeGenerator); - 专用类:一个类只负责干单一工作,例如太阳能板(
SolarPanel)、溢流门(OverflowGate),逻辑大多复杂而且不能简单地归入到通用类的框架下; - 标记类:通常是抽象类,用于功能的标记,也可以直接使用,如方块(
Block),电力方块(PowerBlock)
电力节点
电力节点有两种类型,一种是在圆形范围内、有连接数量限制、手动连接的电力节点PowerNode,一种是在范围里自动连接的激光节点BeamNode。此外还有LongPowerNode,只是在绘制上与电力节点稍有区别。你可以让电力节点缓存电力,原版在埃里克尔就是这么做的,因为那里没有电池用。
powerNode = new PowerNode("tutorial-power-node"){{
requirements(Category.power, with(Items.copper, 2, Items.lead, 6));
maxNodes = 10;
laserRange = 6;
underBullets = true;
}};
beamNode = new BeamNode("tutorial-beam-node"){{
requirements(Category.power, with(Items.beryllium, 8));
range = 10;
//它们两个是一伙的
consumesPower = outputsPower = true;
consumePowerBuffered(1000f);
}};powerNode = PowerNode("tutorial-power-node").apply{
requirements(Category.power, with(Items.copper, 2, Items.lead, 6))
maxNodes = 10
laserRange = 6
underBullets = true
}
beamNode = new BeamNode("tutorial-beam-node").apply{
requirements(Category.power, with(Items.beryllium, 8))
range = 10
//它们两个是一伙的
consumesPower = outputsPower = true
consumePowerBuffered(1000f)
}还有一个类型是二极管(PowerDiode),它可以让电力在两个电网之间单向传输。
电池
batteryLarge = new Battery("tutorial-battery-large"){{
requirements(Category.power, with(Items.titanium, 20, Items.lead, 50, Items.silicon, 30));
size = 3;
consumePowerBuffered(50000f);
baseExplosiveness = 5f;
}};电池是用于缓存电力的,而其功能由ConsumePowerBuffered这一消耗器负责。电池也拥有drawer,默认会根据缓存电量变换电池的颜色,由于电池没有设置progress属性,所以大部分drawer无法生效。
其余电力方块
我们在上文提到了“标记类”这一名词,在电力系统中除了PowerGenerator用于标记发电机,还有两个标记类,分别是PowerDistributor和PowerBlock,这两个类设置了一些字段,如默认更新update = true,将方块的组别设置为BlockGroup.power。此外,电力源PowerSource和电力黑洞PowerVoid也在mindustry.world.block.sandbox包里。
灯光方块LightBlock和电力方块在同一包里,它的工作就是用光亮照亮黑暗,但没有探开战争迷雾的功能。它的建筑可见性BuildVisibility稍有不同:
illuminator = new LightBlock("illuminator"){{
requirements(Category.effect, BuildVisibility.lightingOnly, with(Items.graphite, 12));
brightness = 0.75f;
radius = 140f;
consumePower(0.05f);
}};PowerGraph是一个完全不同的类,它并不是方块,而是一个表示电网的实体。在 Mindustry 中,相互连通的电力建筑拥有同一个电网,电网可以调度电力的产生、缓存和消耗。我们将在后文讲解电网的工作原理。
方块元数据
方块元数据是指方块一些用于标记、索引或控制的字段。它们通常是**枚举类型(Enum)**或半枚举类型的。
建筑可见性
建筑可见性(BuildVisibility)是用来控制方块何时在放置栏中可见的,这是一个半枚举类,意思是说功能上类似枚举,但是你也可以添加自己的BuildVisibilty。原版中的建筑可见性包括:
hidden/shown:隐藏或显示,需要注意的是是否显示不只由可见性决定,还要受到地图/星球科技的限制;debugOnly:仅调试模式,实际上就是隐藏,因为在调试模式下无视建筑可见性;editorOnly:仅在地图编辑器中,不包括“游戏内编辑”和“试玩”,地形和废墙系列都采取此设定;coreZoneOnly:仅当地图上有“核心区域”地板,两个星球的初级核心采取此设定;worldProcessorOnly:仅当允许编译世界处理器时,包括在地图编辑器或规则允许时,世界处理器系列物品采取此设定;sandboxOnly:仅在“无限资源”规则激活时,通常是沙盒模式,各种源和黑洞采取此设定;campaignOnly:仅在战役中,行星际发射器采取此设定;legacyLaunchPadOnly:仅启用传统发射台时,需要行星有特殊设置,而且不能是新发射台,旧发射台采取此设定;lightingOnly:仅需照明器时,通常在战役模式或规则允许时,照明器采取此设定;ammoOnly:仅单位需要弹药时,需要规则允许,由于原来的供弹方块“供弹点”已被移除,现版本供弹方块是核心和容器类,所以没有符合此需求的方块,故原版未使用;fogOnly:仅有战争迷雾时,需要规则允许,雷达采取此设定
方块组别
方块组别(BlockGroup)是用来控制方块之间互相是否可以直接覆盖的。这是一个枚举类,意思是说在运行时是无法添加新值的。方块组别包括:
none walls projectors turrets transportation power liquids drills units logic payloads heat
方块标记
方块标记(BlockFlag)是用于游戏内逻辑定位、单位索敌或代码中高效获取特定种类方块。方块标记包括:
core:核心,所有单位的主要攻击目标。storage:存储类方块,如保险库、容器等。generator:发电类方块,能够产生电力。turret:任何炮塔类防御建筑。factory:工厂类方块,能够将原材料加工为其他物品。repair:修理点,能够修复受损单位。battery:电力存储方块,可为周围设施补充电力。reactor:任何反应堆类方块。extinguisher:灭火类方块,能够扑灭火焰。drill:钻头类方块,用于开采资源。shield:力场投射器,能够生成防护力场。launchPad:发射台,用于发射物品或单位(特殊内部标识)。unitCargoUnloadPoint:单位货物卸载点(特殊内部标识)。unitAssembler:单位组装器(特殊内部标识)。hasFogRadius:具有战争迷雾半径的方块(特殊内部标识)。steamVent:蒸汽排放口(特殊内部标识)。blockRepair:方块修理点(特殊内部标识)。synced:同步类方块,需要网络同步(特殊内部标识)。