Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ object ClockworkConfig {

@ConfigEntry(description = "Gas energy display unit")
var energyDisplayUnit = DuctUnits.EnergyUnit.JOULE

@ConfigEntry(description = "Threshold for high temperature warning. 0.9 = 90% of maximum", min = 0.0, max = 1.0)
var maxTemperatureWarning = 0.9

@ConfigEntry(description = "Threshold for high pressure warning. 0.9 = 90% of maximum", min = 0.0, max = 1.0)
var maxPressureWarning = 0.9
}

class Server {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@ import dev.architectury.platform.Platform
import net.minecraft.ChatFormatting
import net.minecraft.client.Minecraft
import net.minecraft.network.chat.Component
import org.valkyrienskies.clockwork.ClockworkGasses
import org.valkyrienskies.clockwork.ClockworkConfig
import org.valkyrienskies.clockwork.ClockworkLang
import org.valkyrienskies.clockwork.ClockworkMod
import org.valkyrienskies.clockwork.ClockworkModClient
import org.valkyrienskies.clockwork.util.gui.DuctTextUtil
import org.valkyrienskies.clockwork.util.gui.DuctTextUtil.gasComponent
import org.valkyrienskies.clockwork.util.gui.IHaveDuctStats
import org.valkyrienskies.kelvin.util.INodeBlockEntity
import org.valkyrienskies.kelvin.util.KelvinExtensions.toMinecraft
Expand All @@ -28,59 +29,71 @@ interface IClockworkNodeBE: INodeBlockEntity, IHaveGoggleInformation {
var found = false

kelvin.nodeInfo[pos]?.totalVolume?.let { volume ->

found = true
ClockworkLang.builder().apply {
add(ClockworkLang.translate("gui.ductInfo.volume").add(ClockworkLang.text(": ")).style(ChatFormatting.GREEN))
add(DuctTextUtil.translateVolume(ClockworkLang.builder(), volume, true).style(ChatFormatting.GREEN))
space()
add(ClockworkLang.translate(
"gui.ductInfo.volume",
DuctTextUtil.translateVolume(ClockworkLang.builder(), volume, true)
).style(ChatFormatting.GREEN))
forGoggles(tooltip, 0)
}
}
kelvin.getTemperatureAt(pos).let { temp ->
found = true
ClockworkLang.builder().apply {
add(ClockworkLang.translate("gui.ductInfo.temperature").add(ClockworkLang.text(": ")).style(ChatFormatting.GOLD))
add(DuctTextUtil.translateTemperature(ClockworkLang.builder(), temp, true).style(ChatFormatting.GOLD))
val max = blockStats?.getMaximumTemperature()
val critical = if (max != null) temp > max * ClockworkConfig.CLIENT.maxTemperatureWarning else false
val indents = if (critical) -2 else 0

if (critical) text("!! ")
add(ClockworkLang.translate(
"gui.ductInfo.temperature",
DuctTextUtil.translateTemperature(ClockworkLang.builder(), temp, true)
))
style(ChatFormatting.GOLD)

if (isPlayerSneaking)
blockStats?.getMaximumTemperature()?.let { max ->
add(ClockworkLang.text(" / ")
.add(DuctTextUtil.translateTemperature(ClockworkLang.builder(), max, true))
.style(ChatFormatting.DARK_GRAY)
)
if (max != null) {
add(ClockworkLang.translate(
"gui.ductInfo.out_of",
DuctTextUtil.translateTemperature(ClockworkLang.builder(), max, true)
).style(ChatFormatting.DARK_GRAY))
}
space()

forGoggles(tooltip, 0)
forGoggles(tooltip, indents)
}
}
kelvin.getPressureAt(pos).takeIf { it > 0.0 }?.let { pressure ->
found = true
ClockworkLang.builder().apply {
add(ClockworkLang.translate("gui.ductInfo.pressure").add(ClockworkLang.text(": ")).style(ChatFormatting.BLUE))
add(DuctTextUtil.translatePressure(ClockworkLang.builder(), pressure, true).style(ChatFormatting.BLUE))
val max = blockStats?.getMaximumPressure()
val critical = if (max != null) pressure > max * ClockworkConfig.CLIENT.maxPressureWarning else false
val indents = if (critical) -2 else 0

if (critical) text("!! ")
add(ClockworkLang.translate(
"gui.ductInfo.pressure",
DuctTextUtil.translatePressure(ClockworkLang.builder(), pressure, true)
))
style(ChatFormatting.BLUE)

if (isPlayerSneaking)
blockStats?.getMaximumPressure()?.let { max ->
add(ClockworkLang.text(" / ")
.add(DuctTextUtil.translatePressure(ClockworkLang.builder(), max, true))
.style(ChatFormatting.DARK_GRAY)
)
if (max != null) {
add(ClockworkLang.translate(
"gui.ductInfo.out_of",
DuctTextUtil.translatePressure(ClockworkLang.builder(), max, true)
).style(ChatFormatting.DARK_GRAY))
}
space()

forGoggles(tooltip, 0)
forGoggles(tooltip, indents)
}
}
if (isPlayerSneaking)
kelvin.getHeatEnergy(pos).takeIf { it > 0.0 }?.let { energy ->
found = true
ClockworkLang.builder().apply {
add(ClockworkLang.translate("gui.ductInfo.energy").add(ClockworkLang.text(": ")).style(ChatFormatting.RED))
add(DuctTextUtil.translateEnergy(ClockworkLang.builder(), energy, true).style(ChatFormatting.RED))
space()

add(ClockworkLang.translate(
"gui.ductInfo.energy",
DuctTextUtil.translateEnergy(ClockworkLang.builder(), energy, true)
).style(ChatFormatting.RED))
forGoggles(tooltip, 0)
}
}
Expand All @@ -94,41 +107,27 @@ interface IClockworkNodeBE: INodeBlockEntity, IHaveGoggleInformation {
.mapNotNull { (gas, amount) ->
if (amount <= 0.0) return@mapNotNull null
totalGasMass += amount

val component = Component.empty().apply {
append(Component.literal(ClockworkGasses.getDisplayCharacterCode(gas))
.withStyle { it.withFont(ClockworkGasses.ICON_FONT_LOCATION) })
if (isPlayerSneaking) {
append(Component.literal(" ${gas.name} ").withStyle(ChatFormatting.GRAY))
} else {
append(Component.literal(" "))
}
append(DuctTextUtil.translateMass(ClockworkLang.builder(), amount, true).component())
}
finishedComponents.add(component)
finishedComponents.add(gasComponent(gas, amount, isPlayerSneaking))
}
if (finishedComponents.isEmpty()) return@let

ClockworkLang.translate("gui.ductInfo.title.contents").forGoggles(tooltip)

val rows = mutableListOf<Pair<Component, Component>>()
for (num in finishedComponents.indices step 2) {
if (num + 1 < finishedComponents.size) {
rows.add(Pair(finishedComponents[num], finishedComponents[num + 1]))
} else {
rows.add(Pair(finishedComponents[num], Component.empty()))
}
}
for (row in rows) {
val rowComponent = Component.empty()
.append(row.first)
.append(Component.literal(" "))
.append(row.second)
ClockworkLang.builder().add(rowComponent).forGoggles(tooltip, 1)
for (row in finishedComponents.chunked(2)) {
ClockworkLang.builder().add(
ClockworkLang.builder().apply {
add(row[0])
if (row.size > 1) {
text(" ")
add(row[1])
}
}
).forGoggles(tooltip, 1)
}

if (isPlayerSneaking && finishedComponents.size > 1)
ClockworkLang.translate("gui.ductInfo.mass_total").add(
ClockworkLang.translate(
"gui.ductInfo.mass_total",
DuctTextUtil.translateMass(ClockworkLang.builder(), totalGasMass, true)
).style(ChatFormatting.GRAY).forGoggles(tooltip, 1)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,42 +1,52 @@
package org.valkyrienskies.clockwork.content.logistics.gas.generation.compressor

import net.minecraft.ChatFormatting
import net.minecraft.core.BlockPos
import net.minecraft.nbt.CompoundTag
import net.minecraft.network.chat.CommonComponents
import net.minecraft.network.chat.Component
import net.minecraft.world.level.block.entity.BlockEntityType
import net.minecraft.world.level.block.state.BlockState
import org.valkyrienskies.clockwork.ClockworkConfig;
import org.valkyrienskies.clockwork.ClockworkLang
import org.valkyrienskies.clockwork.ClockworkMod
import org.valkyrienskies.clockwork.util.AerodynamicUtils
import org.valkyrienskies.clockwork.util.KNodeKineticBlockEntity
import org.valkyrienskies.clockwork.util.gui.ClockworkTooltipHelper
import org.valkyrienskies.clockwork.util.gui.DuctTextUtil
import org.valkyrienskies.kelvin.impl.registry.GasTypeRegistry
import org.valkyrienskies.mod.api.dimensionId
import org.valkyrienskies.mod.api.getShipManagingBlock
import org.valkyrienskies.mod.common.util.toJOMLD
import org.valkyrienskies.mod.common.toWorldCoordinates
import kotlin.math.abs
import kotlin.math.max

class AirCompressorBlockEntity(typeIn: BlockEntityType<*>, pos: BlockPos, state: BlockState) : KNodeKineticBlockEntity(typeIn, pos, state) {
var isActivated: Boolean = false
private set
enum class CompressorStatus {
ACTIVE,
INACTIVE,
EXHAUSTED,
OBSTRUCTED
}
var status: CompressorStatus = CompressorStatus.INACTIVE
set(value) { if (field != value) { field = value; sendData() } }

var clientParticles: Boolean = false
var clientSize: Float = 0.0f

private val airGas = GasTypeRegistry.getGasType("kelvin", "air")
private val heliumGas = GasTypeRegistry.getGasType("vs_clockwork", "aether")

fun getAirDensity(): Double {

val ship = level.getShipManagingBlock(blockPos)
val position = ship?.transform?.toWorld?.transformPosition(blockPos.toJOMLD()) ?: blockPos.toJOMLD()
val active get() = status == CompressorStatus.ACTIVE
val exhausted get() = status == CompressorStatus.EXHAUSTED
val obstructed get() = status == CompressorStatus.OBSTRUCTED

fun getAirDensity(): Double {
val position = level.toWorldCoordinates(blockPos)
return AerodynamicUtils.getAirDensityForY(position.y, level!!.dimensionId)
}

fun getAirTemperature(): Double {
val ship = level.getShipManagingBlock(blockPos)
val position = ship?.transform?.toWorld?.transformPosition(blockPos.toJOMLD()) ?: blockPos.toJOMLD()

val position = level.toWorldCoordinates(blockPos)
return AerodynamicUtils.getAirTemperatureForY(position.y, level!!.dimensionId)
}

Expand All @@ -50,38 +60,72 @@ class AirCompressorBlockEntity(typeIn: BlockEntityType<*>, pos: BlockPos, state:
val kelvin = ClockworkMod.getKelvin()
kelvin.getNodeAt(getDuctNodePosition()) ?: return

val pressure = kelvin.getPressureAt(getDuctNodePosition())
val speed = abs(getSpeed())
if (level!!.getBlockState(blockPos.above()).isAir) {
if (speed > 0) {
// Should this depend on actual air pressure outside? If we are in vacuum,
// no way this compressor thing will still pump 10 ground atmospheres.
// Maybe something airCompressorMaxPressureFactor instead?
if (kelvin.getPressureAt(getDuctNodePosition()) < ClockworkConfig.SERVER.airCompressorMaxPressure) {
status = CompressorStatus.ACTIVE
// Future: proper API for defining atmospheric composition?
val heliumShare = max(
0.0,
1 - getAirDensity() / ClockworkConfig.SERVER.airCompressorHeliumAirDensity
)
val deltaVolume = ClockworkConfig.SERVER.airCompressorSpeed * speed
kelvin.addGasAtTemperature(
getDuctNodePosition(),airGas, (1 - heliumShare) * deltaVolume, getAirTemperature()
)
kelvin.addGasAtTemperature(
getDuctNodePosition(),heliumGas, heliumShare * deltaVolume, getAirTemperature()
)
} else status = CompressorStatus.EXHAUSTED
} else status = CompressorStatus.INACTIVE
} else status = CompressorStatus.OBSTRUCTED
}

if (speed>0 && pressure< ClockworkConfig.SERVER.airCompressorMaxPressure) {
if (!isActivated) {
isActivated = true
sendData()
override fun addToGoggleTooltip(tooltip: List<Component>?, isPlayerSneaking: Boolean): Boolean {
if (status != CompressorStatus.INACTIVE) {
ClockworkLang.translate("gui.air_compressor.info.title").forGoggles((tooltip as MutableList))
when (status) {
CompressorStatus.OBSTRUCTED -> {
ClockworkTooltipHelper.addHint(tooltip, "gui.air_compressor.info.obstructed")
}
CompressorStatus.EXHAUSTED -> {
ClockworkTooltipHelper.addHint(tooltip, "gui.air_compressor.info.exhausted")
}
CompressorStatus.ACTIVE -> {
ClockworkLang
.translate("gui.air_compressor.info.active.title").style(ChatFormatting.GREEN)
.forGoggles(tooltip)
ClockworkLang
.translate(
"gui.air_compressor.info.active",
DuctTextUtil.translateTemperature(
ClockworkLang.builder(), getAirTemperature(), true
).style(ChatFormatting.GOLD)
).style(ChatFormatting.GRAY)
.forGoggles(tooltip)
}
else -> {}
}


val heliumShare = max(0.0, (ClockworkConfig.SERVER.airCompressorHeliumAirDensity - getAirDensity())) / ClockworkConfig.SERVER.airCompressorHeliumAirDensity
val deltaVolume = ClockworkConfig.SERVER.airCompressorSpeed*speed

kelvin.addGasAtTemperature(getDuctNodePosition(),airGas, (1-heliumShare)*deltaVolume, getAirTemperature())
kelvin.addGasAtTemperature(getDuctNodePosition(),heliumGas, heliumShare*deltaVolume, getAirTemperature())
} else if (isActivated) {
isActivated = false;
sendData()
tooltip.add(CommonComponents.EMPTY)
}
return super.addToGoggleTooltip(tooltip, isPlayerSneaking)
}

override fun remove() {
super.remove()
}

override fun read(tag: CompoundTag, clientPacket: Boolean) {
isActivated = tag.getBoolean("isActivated")
status = CompressorStatus.valueOf(tag.getString("status"))
super.read(tag, clientPacket)
}

override fun write(tag: CompoundTag, clientPacket: Boolean) {
tag.putBoolean("isActivated",isActivated)
tag.putString("status", status.toString())
super.write(tag, clientPacket)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ class AirCompressorRenderer(context: BlockEntityRendererProvider.Context?) : Kin
val sizeMultiplier = when {
minecraft.isPaused -> 0f
// Deflate if particles were spawned OR if the compressor is off
be.clientParticles || !be.isActivated -> -1f
be.clientParticles || !be.active -> -1f
else -> 1f
}

Expand Down
Loading