ocelot-desktop/src/main/scala/ocelot/desktop/node/ComputerAwareNode.scala

112 lines
3.9 KiB
Scala

package ocelot.desktop.node
import ocelot.desktop.audio._
import ocelot.desktop.graphics.{Graphics, IconSource}
import ocelot.desktop.inventory.SyncedInventory
import ocelot.desktop.node.ComputerAwareNode._
import ocelot.desktop.node.Node.Size
import ocelot.desktop.ui.UiHandler
import ocelot.desktop.ui.event.BrainEvent
import ocelot.desktop.ui.event.handlers.DiskActivityHandler
import ocelot.desktop.ui.particle.Particle
import ocelot.desktop.util.Messages
import ocelot.desktop.{ColorScheme, Settings => DesktopSettings}
import totoro.ocelot.brain.Settings
import totoro.ocelot.brain.entity.traits.{Entity, Environment, WorkspaceAware}
import totoro.ocelot.brain.event._
import java.util.Calendar
abstract class ComputerAwareNode(entity: Entity with Environment with WorkspaceAware)
extends EntityNode(entity)
with SyncedInventory
with DiskActivityHandler
with OcelotLogParticleNode
with BoomCardFxHandler
with ShiftClickNode {
private lazy val soundCardSounds: (SoundStream, SoundSource) = Audio.newStream(SoundCategory.Records)
private def soundCardStream: SoundStream = soundCardSounds._1
private def soundCardSource: SoundSource = soundCardSounds._2
eventHandlers += {
case BrainEvent(event: MachineCrashEvent) =>
val message = Messages.lift(event.message) match {
case Some(message) =>
logger.info(s"[EVENT] Machine crash (address = ${event.address})! Message code ${event.message}: $message")
message
case None =>
logger.info(s"[EVENT] Machine crash (address = ${event.address})! Message: ${event.message}")
event.message
}
UiHandler.root.workspaceView.particleSystem.add(new ErrorMessageParticle(message))
case BrainEvent(event: BeepEvent) if !Audio.isDisabled =>
BeepGenerator.newBeep(".", event.frequency, event.duration).play()
case BrainEvent(event: BeepPatternEvent) if !Audio.isDisabled =>
BeepGenerator.newBeep(event.pattern, 1000, 200).play()
case BrainEvent(event: SoundCardAudioEvent) if !Audio.isDisabled =>
val samples = SoundSamples(event.data, Settings.get.soundCardSampleRate, SoundSamples.Format.Mono8)
soundCardStream.enqueue(samples)
soundCardSource.volume = event.volume
}
protected def drawOverlay(g: Graphics): Unit = HolidayIcon match {
case Some(icon) if DesktopSettings.get.enableFestiveDecorations =>
val holidayOverlaySize = Size * 1.6f
val offset = (holidayOverlaySize - Size) / 2
g.sprite(
icon,
position.x - offset,
position.y - offset,
holidayOverlaySize,
holidayOverlaySize,
)
case _ =>
}
override def draw(g: Graphics): Unit = {
super.draw(g)
drawOverlay(g)
}
private class ErrorMessageParticle(message: String) extends Particle(speed = ErrorMessageMoveSpeed) {
private val offsetX = size.width / 2 - message.length * 4
private val offsetY = -8
override def draw(g: Graphics): Unit = {
g.setSmallFont()
g.foreground = ColorScheme("ErrorMessage").withAlpha(1 - (2 * time - 1).min(1).max(0))
g.text(position.x + offsetX, position.y + offsetY - MaxErrorMessageDistance * time, message)
g.setNormalFont()
}
}
}
object ComputerAwareNode {
private val MaxErrorMessageDistance: Float = 50f
private val ErrorMessageMoveSpeed: Float = 0.5f
private val HolidayIcon: Option[IconSource] = {
var dayOfYear = Calendar.getInstance().get(Calendar.DAY_OF_YEAR)
val maxDuration = 5
if (dayOfYear >= 365 - maxDuration) {
dayOfYear -= 365
}
val holidays: Array[(Int, IconSource)] = Array(
(1, IconSource.Nodes.Holidays.Christmas),
(45, IconSource.Nodes.Holidays.Valentines),
(305, IconSource.Nodes.Holidays.Halloween),
)
holidays
.find(holiday => dayOfYear >= holiday._1 - maxDuration && dayOfYear <= holiday._1 + maxDuration)
.map(holiday => holiday._2)
}
}