diff --git a/src/main/kotlin/org/neoflock/neocomputers/NeoComputers.kt b/src/main/kotlin/org/neoflock/neocomputers/NeoComputers.kt index b04a65b..16fda43 100644 --- a/src/main/kotlin/org/neoflock/neocomputers/NeoComputers.kt +++ b/src/main/kotlin/org/neoflock/neocomputers/NeoComputers.kt @@ -19,6 +19,7 @@ import org.neoflock.neocomputers.gui.widget.ComponentRoles import org.neoflock.neocomputers.item.Items import org.neoflock.neocomputers.item.Tabs import org.neoflock.neocomputers.network.Networking +import org.neoflock.neocomputers.sounds.Sounds import org.neoflock.neocomputers.utils.FontProvider import org.neoflock.neocomputers.utils.GenericContainerScreen import org.slf4j.Logger @@ -40,6 +41,7 @@ object NeoComputers { BlockEntities.registerPowerBlocks() Menus.MENUS.register() Tabs.TABS.register() + Sounds.SOUNDS.register() ComponentRoles.mapDefaultTextures() // i dont know why architectury wants two lambdas but whatever EnvExecutor.runInEnv(Env.CLIENT) {{ @@ -92,8 +94,14 @@ object NeoComputers { EnvExecutor.runInEnv(Env.SERVER) {{ // https://github.com/architectury/architectury-api/issues/518 NetworkManager.registerS2CPayloadType(NodeSynchronizer.StatePayload.TYPE, NodeSynchronizer.StatePayload.CODEC) - NetworkManager.registerS2CPayloadType(NodeSynchronizer.ScreenPayload.TYPE, NodeSynchronizer.ScreenPayload.CODEC) + NetworkManager.registerReceiver(NetworkManager.c2s(),NodeSynchronizer.ScreenPayload.TYPE, NodeSynchronizer.ScreenPayload.CODEC, { + packet, ctx -> + val player = ctx.player + if(player is ServerPlayer) { + NodeSynchronizer.screenMap[player]?.processScreenInteraction(player, packet.buffer) + } + }) }} LOGGER.info("Registered!") diff --git a/src/main/kotlin/org/neoflock/neocomputers/block/CaseBlock.kt b/src/main/kotlin/org/neoflock/neocomputers/block/CaseBlock.kt index 8d9e811..ff04f79 100644 --- a/src/main/kotlin/org/neoflock/neocomputers/block/CaseBlock.kt +++ b/src/main/kotlin/org/neoflock/neocomputers/block/CaseBlock.kt @@ -2,28 +2,89 @@ package org.neoflock.neocomputers.block; import dev.architectury.registry.menu.MenuRegistry import net.minecraft.core.BlockPos -import net.minecraft.network.chat.Component +import net.minecraft.core.Direction +import net.minecraft.resources.ResourceLocation import net.minecraft.server.level.ServerPlayer -import net.minecraft.world.InteractionHand +import net.minecraft.sounds.SoundEvent +import net.minecraft.sounds.SoundEvents +import net.minecraft.sounds.SoundSource +import net.minecraft.util.RandomSource +import net.minecraft.world.Containers import net.minecraft.world.InteractionResult -import net.minecraft.world.MenuProvider -import net.minecraft.world.entity.player.Inventory import net.minecraft.world.entity.player.Player -import net.minecraft.world.inventory.AbstractContainerMenu -import net.minecraft.world.item.ItemStack +import net.minecraft.world.level.BlockGetter import net.minecraft.world.level.Level +import net.minecraft.world.level.block.Block import net.minecraft.world.level.block.EntityBlock -import net.minecraft.world.level.block.entity.BlockEntity +import net.minecraft.world.level.block.SoundType import net.minecraft.world.level.block.state.BlockState +import net.minecraft.world.level.block.state.StateDefinition +import net.minecraft.world.level.block.state.properties.BooleanProperty import net.minecraft.world.phys.BlockHitResult import org.neoflock.neocomputers.NeoComputers +import org.neoflock.neocomputers.block.CombustionGeneratorBlock.Companion.COMBUSTGEN_ACTIVE import org.neoflock.neocomputers.entity.BlockEntities -import org.neoflock.neocomputers.entity.ScreenEntity -import org.neoflock.neocomputers.gui.menu.Menus -import org.neoflock.neocomputers.gui.menu.ScreenMenu -import org.neoflock.neocomputers.network.Networking +import org.neoflock.neocomputers.entity.CaseBlockEntity +import org.neoflock.neocomputers.entity.MachineEntity +import org.neoflock.neocomputers.sounds.Sounds + +class CaseBlock() : NodeBlock(Properties.of().sound(SoundType.METAL).lightLevel(CaseBlock::getLuminance)) { // placeholder stuff + companion object { + val COMPUTER_RUNNING = BooleanProperty.create("running")!! + + fun getLuminance(blockState: BlockState): Int { + return if(blockState.getValue(COMPUTER_RUNNING)) 3 else 0 + } + } + + override fun newBlockEntity(blockPos: BlockPos, blockState: BlockState) = CaseBlockEntity(blockPos, blockState) + + override fun createBlockStateDefinition(builder: StateDefinition.Builder) { + builder.add(COMPUTER_RUNNING) + } + + fun getMachine(level: BlockGetter, blockPos: BlockPos): CaseBlockEntity { + return level.getBlockEntity(blockPos) as CaseBlockEntity + } + + override fun getSignal( + blockState: BlockState, + blockGetter: BlockGetter, + blockPos: BlockPos, + direction: Direction + ): Int { + return getMachine(blockGetter, blockPos).redstoneOut[dirToIdx(direction.opposite)] + } + + override fun onPlace( + blockState: BlockState, + level: Level, + blockPos: BlockPos, + blockState2: BlockState, + bl: Boolean + ) { + if(!level.isClientSide) { + level.updateNeighborsAt(blockPos, this) + getMachine(level, blockPos).refetchAllRedstone() + } + super.onPlace(blockState, level, blockPos, blockState2, bl) + } + + override fun neighborChanged( + blockState: BlockState, + level: Level, + blockPos: BlockPos, + block: Block, + blockPos2: BlockPos, + bl: Boolean + ) { + super.neighborChanged(blockState, level, blockPos, block, blockPos2, bl) + if(!level.isClientSide) { + val dir = Direction.getNearest(blockPos2.center.subtract(blockPos.center)) + getMachine(level, blockPos).refetchRedstone(dir) + } + } -class CaseBlock() : BaseBlock() { // placeholder stuff override fun useWithoutItem( blockState: BlockState, level: Level, @@ -32,13 +93,21 @@ class CaseBlock() : BaseBlock() { // placeholder stuff blockHitResult: BlockHitResult ): InteractionResult { if(!level.isClientSide) { - MenuRegistry.openMenu(player as ServerPlayer, object : MenuProvider { - override fun getDisplayName(): Component = Component.literal("Computer") - override fun createMenu(i: Int, inventory: Inventory, player: Player): AbstractContainerMenu { - return Menus.CASE_MENU.get().create(i, inventory); - } - }) + val ent = level.getBlockEntity(blockPos, BlockEntities.CASE_ENTITY.get()).get() + MenuRegistry.openMenu(player as ServerPlayer, ent) + NodeSynchronizer.registerPlayerScreen(player, ent) } return InteractionResult.SUCCESS } + + override fun onRemove( + blockState: BlockState, + level: Level, + blockPos: BlockPos, + blockState2: BlockState, + bl: Boolean + ) { + Containers.dropContentsOnDestroy(blockState, blockState2, level, blockPos) + super.onRemove(blockState, level, blockPos, blockState2, bl) + } } \ No newline at end of file diff --git a/src/main/kotlin/org/neoflock/neocomputers/block/Generators.kt b/src/main/kotlin/org/neoflock/neocomputers/block/Generators.kt index 77406a9..891e635 100644 --- a/src/main/kotlin/org/neoflock/neocomputers/block/Generators.kt +++ b/src/main/kotlin/org/neoflock/neocomputers/block/Generators.kt @@ -13,6 +13,7 @@ import net.minecraft.world.entity.player.Player import net.minecraft.world.level.Level import net.minecraft.world.level.block.Block import net.minecraft.world.level.block.EntityBlock +import net.minecraft.world.level.block.FurnaceBlock import net.minecraft.world.level.block.SoundType import net.minecraft.world.level.block.entity.BlockEntity import net.minecraft.world.level.block.state.BlockState @@ -30,15 +31,15 @@ class SolarGeneratorBlock : NodeBlock(), EntityBlock { // TODO: make it glow when burning class CombustionGeneratorBlock : NodeBlock, EntityBlock { companion object { - val ACTIVE = BooleanProperty.create("active") + val COMBUSTGEN_ACTIVE = BooleanProperty.create("active") fun getLuminance(blockState: BlockState): Int { - return if(blockState.getValue(ACTIVE)) 5 else 0 + return if(blockState.getValue(COMBUSTGEN_ACTIVE)) 5 else 0 } } constructor(): super(Properties.of().sound(SoundType.STONE).lightLevel(CombustionGeneratorBlock::getLuminance)) { - registerDefaultState(defaultBlockState().setValue(ACTIVE, false)) + registerDefaultState(defaultBlockState().setValue(COMBUSTGEN_ACTIVE, false)) } override fun newBlockEntity(blockPos: BlockPos, blockState: BlockState): BlockEntity = CombustionGeneratorBlockEntity(blockPos, blockState).initNetworking() @@ -60,12 +61,12 @@ class CombustionGeneratorBlock : NodeBlock, EntityBlock { } override fun createBlockStateDefinition(builder: StateDefinition.Builder) { - builder.add(ACTIVE) + builder.add(COMBUSTGEN_ACTIVE) } override fun animateTick(blockState: BlockState, level: Level, blockPos: BlockPos, randomSource: RandomSource) { - if(blockState.getValue(ACTIVE)) { - if(randomSource.nextDouble() < 0.1) level.playSound(null, blockPos, SoundEvents.FURNACE_FIRE_CRACKLE, SoundSource.AMBIENT) + if(blockState.getValue(COMBUSTGEN_ACTIVE)) { + if(randomSource.nextDouble() < 0.1) level.playLocalSound(blockPos, SoundEvents.FURNACE_FIRE_CRACKLE, SoundSource.AMBIENT, 1F, 1F, false) val x = blockPos.x.toDouble() val y = blockPos.y.toDouble() diff --git a/src/main/kotlin/org/neoflock/neocomputers/block/NodeBlock.kt b/src/main/kotlin/org/neoflock/neocomputers/block/NodeBlock.kt index b657400..fea5ac0 100644 --- a/src/main/kotlin/org/neoflock/neocomputers/block/NodeBlock.kt +++ b/src/main/kotlin/org/neoflock/neocomputers/block/NodeBlock.kt @@ -87,6 +87,10 @@ object NodeSynchronizer { NetworkManager.sendToPlayer(player, ScreenPayload(nodeTypeToWireID(ent.type), buf)) } } + + fun sendScreenInteraction(friendlyByteBuf: FriendlyByteBuf) { + NetworkManager.sendToServer(ScreenPayload("", friendlyByteBuf)) + } } abstract class NodeBlockEntity(blockEntityType: BlockEntityType<*>, blockPos: BlockPos, blockState: BlockState) : BlockEntity(blockEntityType, blockPos, blockState) { @@ -119,6 +123,8 @@ abstract class NodeBlockEntity(blockEntityType: BlockEntityType<*>, blockPos: Bl // Encodes data meant for the associated screen of a player open fun encodeScreenData(player: ServerPlayer, packet: FriendlyByteBuf) {} + open fun processScreenInteraction(player: ServerPlayer, packet: FriendlyByteBuf) {} + private var stateIsDirty = true open fun getNeighbourEntities(): List { diff --git a/src/main/kotlin/org/neoflock/neocomputers/entity/BlockEntities.kt b/src/main/kotlin/org/neoflock/neocomputers/entity/BlockEntities.kt index 2ea740f..c3b3255 100644 --- a/src/main/kotlin/org/neoflock/neocomputers/entity/BlockEntities.kt +++ b/src/main/kotlin/org/neoflock/neocomputers/entity/BlockEntities.kt @@ -75,6 +75,11 @@ object BlockEntities { ::CombustionGeneratorBlockEntity, mutableSetOf(Blocks.REDSTONEIO_BLOCK.get()), BullshitFix() ) } + val CASE_ENTITY: RegistrySupplier> = BLOCKENTITIES.register("case") { + BlockEntityType( + ::CaseBlockEntity, mutableSetOf(Blocks.CASE_BLOCK.get()), BullshitFix() + ) + } fun registerPowerBlocks() { PowerManager.registerPowerBlockEntity(CAPACITOR_ENTITY.get()) diff --git a/src/main/kotlin/org/neoflock/neocomputers/entity/CaseBlockEntity.kt b/src/main/kotlin/org/neoflock/neocomputers/entity/CaseBlockEntity.kt new file mode 100644 index 0000000..6da9eed --- /dev/null +++ b/src/main/kotlin/org/neoflock/neocomputers/entity/CaseBlockEntity.kt @@ -0,0 +1,217 @@ +package org.neoflock.neocomputers.entity + +import net.minecraft.client.Minecraft +import net.minecraft.client.resources.sounds.BiomeAmbientSoundsHandler +import net.minecraft.client.resources.sounds.EntityBoundSoundInstance +import net.minecraft.client.resources.sounds.SoundInstance +import net.minecraft.client.sounds.LoopingAudioStream +import net.minecraft.core.BlockPos +import net.minecraft.core.Direction +import net.minecraft.core.HolderLookup +import net.minecraft.core.NonNullList +import net.minecraft.nbt.CompoundTag +import net.minecraft.network.FriendlyByteBuf +import net.minecraft.network.chat.Component +import net.minecraft.server.level.ServerPlayer +import net.minecraft.sounds.SoundSource +import net.minecraft.world.Container +import net.minecraft.world.ContainerHelper +import net.minecraft.world.MenuProvider +import net.minecraft.world.entity.player.Inventory +import net.minecraft.world.entity.player.Player +import net.minecraft.world.item.ItemStack +import net.minecraft.world.level.block.state.BlockState +import org.neoflock.neocomputers.NeoComputers +import org.neoflock.neocomputers.block.CaseBlock +import org.neoflock.neocomputers.block.NodeBlockEntity +import org.neoflock.neocomputers.block.dirToIdx +import org.neoflock.neocomputers.gui.menu.CaseMenu +import org.neoflock.neocomputers.item.ComponentItem +import org.neoflock.neocomputers.network.Networking +import org.neoflock.neocomputers.network.PowerRole +import org.neoflock.neocomputers.sounds.ComputerRunningSoundInstance +import org.neoflock.neocomputers.sounds.Sounds +import org.neoflock.neocomputers.utils.GenericContainer +import java.time.Duration +import kotlin.math.min + +class CaseBlockEntity(blockPos: BlockPos, blockState: BlockState): NodeBlockEntity(BlockEntities.CASE_ENTITY.get(), blockPos, blockState), MachineEntity, GenericContainer, MenuProvider { + val stacks: NonNullList = NonNullList.withSize(7, ItemStack.EMPTY) + + var isOn = false + var soundInstance: SoundInstance? = null + + override val node = object : Networking.Node() { + override var powerRole = PowerRole.STORAGE + override var energyCapacity: Long = 500 + } + + override fun encodeDownstreamData(packet: FriendlyByteBuf) { + super.encodeDownstreamData(packet) + packet.writeBoolean(isOn) + } + + override fun syncWithUpstream(packet: FriendlyByteBuf) { + super.syncWithUpstream(packet) + setRunning(packet.readBoolean()) + } + + override fun processScreenInteraction(player: ServerPlayer, packet: FriendlyByteBuf) { + val c = packet.readByte().toInt() + if(c == 0x01) { + start() + } + if(c == 0x02) { + stop() + } + } + + override fun encodeScreenData(player: ServerPlayer, packet: FriendlyByteBuf) { + packet.writeBoolean(isOn) + packet.writeLong(node.energy) + packet.writeLong(node.energyCapacity) + packet.writeLong(getMachineMemoryUsed()) + packet.writeLong(getMachineMemoryTotal()) + packet.writeLong(getMachineComponentsUsed()) + packet.writeLong(getMachineMemoryTotal()) + } + + val redstoneIn = Array(Direction.entries.size) {0} + val redstoneOut = Array(Direction.entries.size) {0} + + fun refetchRedstone(dir: Direction) { + val src = blockPos.offset(dir.stepX, dir.stepY, dir.stepZ) + val cur = level?.getSignal(src, dir) ?: 0 + val idx = dirToIdx(dir) + if(redstoneIn[idx] != cur) { + onRedstoneSignalChanged(dir, redstoneIn[idx], cur) + } + redstoneIn[idx] = cur + } + + fun refetchAllRedstone() { + Direction.entries.forEach { refetchRedstone(it) } + } + + fun sendMachineEvent(event: MachineEvent) { + stacks.forEach { + val item = it.item + if(item is ComponentItem) { + item.onMachineEvent(it, this, event) + } + } + } + + fun onRedstoneSignalChanged(dir: Direction, oldValue: Int, newValue: Int) { + sendMachineEvent(MachineRedstoneEvent(this, dir, oldValue, newValue)) + Networking.emitMessage(node, Networking.ComputerUncheckedSignal(node, "redstone_changed", arrayOf(node.address.toString(), dirToIdx(dir), oldValue, newValue))) + NeoComputers.LOGGER.info("redstone in direction ${dir.name} changed from $oldValue to $newValue") + if(oldValue == 0) { + // Rising edge + start() + } + if(newValue == 0) { + // Not accurate but whatevs + stop() + } + setChanged() + } + + override fun getBlockPosition(): BlockPos = blockPos + + override fun isRunning(): Boolean = isOn + + fun setRunning(value: Boolean) { + if(isOn == value) return + NeoComputers.LOGGER.info("[${node.address}] Going from $isOn to $value") + isOn = value + val world = level ?: return + blockState?.setValue(CaseBlock.COMPUTER_RUNNING, isOn) + if(world.isClientSide) { + if(value) { + soundInstance = ComputerRunningSoundInstance(this, Sounds.COMPUTER_RUNNING.get(), SoundSource.AMBIENT) + Minecraft.getInstance().soundManager.play(soundInstance!!) + } else { + Minecraft.getInstance().soundManager.stop(soundInstance!!) + soundInstance = null + } + return + } + // Server-side stuff!! + world.onBlockStateChange(blockPos, blockState, blockState) + sendMachineEvent(MachinePowerEvent(this, isOn)) + } + + override fun start(): Boolean { + setRunning(true) + return isOn + } + + override fun stop(): Boolean { + setRunning(false) + return isOn + } + + override fun crash(error: String): Boolean { + NeoComputers.LOGGER.warn("Crashing cases is not implemented yet lol") + return false + } + + override fun getLastError(): String? = null + + override fun getMachineNode(): Networking.Node = node + + override fun getRedstoneInput(direction: Direction): Int = redstoneIn[dirToIdx(direction)] + + override fun getRedstoneOutput(direction: Direction): Int = redstoneOut[dirToIdx(direction)] + + override fun setRedstoneOutput(direction: Direction, newValue: Int): Int { + val idx = dirToIdx(direction) + val old = redstoneOut[idx] + redstoneOut[idx] = newValue + return old + } + + override fun beepAsync(frequency: Int, duration: Duration, volume: Double): Boolean { + NeoComputers.LOGGER.warn("beep not yet implemented") + return true + } + + override fun getMachineMemoryTotal(): Long = stacks.mapNotNull { (it.item as? ComponentItem)?.getMemoryCapacity(it) }.sum().toLong() + override fun getMachineMemoryUsed(): Long = 0 + override fun getMachineComponentsUsed(): Long = node.connections.size.toLong() + override fun getMachineComponentsTotal(): Long = stacks.mapNotNull { (it.item as? ComponentItem)?.getComponentCapacity(it) }.sum().toLong() + + override fun getItems(): NonNullList = stacks + + override fun stillValid(player: Player): Boolean = true + + override fun loadAdditional(compoundTag: CompoundTag, provider: HolderLookup.Provider) { + super.loadAdditional(compoundTag, provider) + node.energy = min(node.energyCapacity, compoundTag.getLong("energy")) + //isOn = compoundTag.getBoolean("powerOn") + ContainerHelper.loadAllItems(compoundTag, getItems(), provider) + } + + override fun saveAdditional(compoundTag: CompoundTag, provider: HolderLookup.Provider) { + super.saveAdditional(compoundTag, provider) + compoundTag.putLong("energy", node.energy) + //compoundTag.putBoolean("powerOn", isOn) + ContainerHelper.saveAllItems(compoundTag, getItems(), provider) + } + + override fun getDisplayName(): Component? = Component.literal("Computer") + override fun createMenu(i: Int, inventory: Inventory, player: Player) = CaseMenu(i, inventory, this) + + override fun canPlaceItem(i: Int, itemStack: ItemStack): Boolean = false + override fun canTakeItem(container: Container, i: Int, itemStack: ItemStack): Boolean = false + + override fun setChanged() { + super.setChanged() + } + + override fun setRemoved() { + setRunning(false) + super.setRemoved() + } +} \ No newline at end of file diff --git a/src/main/kotlin/org/neoflock/neocomputers/entity/CombustionGeneratorBlockEntity.kt b/src/main/kotlin/org/neoflock/neocomputers/entity/CombustionGeneratorBlockEntity.kt index 0e6db01..43969ec 100644 --- a/src/main/kotlin/org/neoflock/neocomputers/entity/CombustionGeneratorBlockEntity.kt +++ b/src/main/kotlin/org/neoflock/neocomputers/entity/CombustionGeneratorBlockEntity.kt @@ -5,20 +5,14 @@ import net.minecraft.core.HolderLookup import net.minecraft.core.NonNullList import net.minecraft.nbt.CompoundTag import net.minecraft.network.FriendlyByteBuf -import net.minecraft.network.RegistryFriendlyByteBuf import net.minecraft.network.chat.Component import net.minecraft.server.level.ServerPlayer -import net.minecraft.sounds.SoundEvents -import net.minecraft.sounds.SoundSource import net.minecraft.world.ContainerHelper import net.minecraft.world.MenuProvider import net.minecraft.world.entity.player.Inventory import net.minecraft.world.entity.player.Player -import net.minecraft.world.inventory.AbstractContainerMenu import net.minecraft.world.item.ItemStack import net.minecraft.world.level.Level -import net.minecraft.world.level.block.ChestBlock -import net.minecraft.world.level.block.FurnaceBlock import net.minecraft.world.level.block.state.BlockState import org.neoflock.neocomputers.block.CombustionGeneratorBlock import org.neoflock.neocomputers.block.NodeBlockEntity @@ -81,7 +75,7 @@ class CombustionGeneratorBlockEntity(blockPos: BlockPos, blockState: BlockState) override fun setChanged() { super.setChanged() - level?.setBlockAndUpdate(blockPos, blockState.setValue(CombustionGeneratorBlock.ACTIVE, burningTimeRemaining > 0)) + level?.setBlockAndUpdate(blockPos, blockState.setValue(CombustionGeneratorBlock.COMBUSTGEN_ACTIVE, burningTimeRemaining > 0)) } override fun encodeScreenData(player: ServerPlayer, packet: FriendlyByteBuf) { diff --git a/src/main/kotlin/org/neoflock/neocomputers/entity/MachineEntity.kt b/src/main/kotlin/org/neoflock/neocomputers/entity/MachineEntity.kt index fc9d8bf..740b403 100644 --- a/src/main/kotlin/org/neoflock/neocomputers/entity/MachineEntity.kt +++ b/src/main/kotlin/org/neoflock/neocomputers/entity/MachineEntity.kt @@ -4,24 +4,35 @@ import net.minecraft.core.BlockPos import net.minecraft.core.Direction import org.neoflock.neocomputers.item.ComponentItem import org.neoflock.neocomputers.network.Networking +import java.time.Duration abstract class MachineEvent { abstract val machine: MachineEntity } -data class MachineRedstoneEvent(override val machine: MachineEntity, val side: Direction): MachineEvent() +data class MachineRedstoneEvent(override val machine: MachineEntity, val side: Direction, val oldValue: Int, val newValue: Int): MachineEvent() +data class MachinePowerEvent(override val machine: MachineEntity, val nowRunning: Boolean): MachineEvent() interface MachineEntity { // Block position of machine, for wireless tech fun getBlockPosition(): BlockPos + fun beepAsync(frequency: Int, duration: Duration, volume: Double): Boolean + fun isRunning(): Boolean fun start(): Boolean fun stop(): Boolean fun crash(error: String): Boolean + fun getLastError(): String? fun getMachineNode(): Networking.Node + // Some metadata + fun getMachineMemoryTotal(): Long + fun getMachineMemoryUsed(): Long + fun getMachineComponentsUsed(): Long + fun getMachineComponentsTotal(): Long + // Redstone signals fun getRedstoneInput(direction: Direction): Int fun getRedstoneOutput(direction: Direction): Int diff --git a/src/main/kotlin/org/neoflock/neocomputers/gui/menu/CaseMenu.kt b/src/main/kotlin/org/neoflock/neocomputers/gui/menu/CaseMenu.kt index 4ad9d29..8e7a674 100644 --- a/src/main/kotlin/org/neoflock/neocomputers/gui/menu/CaseMenu.kt +++ b/src/main/kotlin/org/neoflock/neocomputers/gui/menu/CaseMenu.kt @@ -1,49 +1,15 @@ package org.neoflock.neocomputers.gui.menu; -import net.minecraft.core.BlockPos -import net.minecraft.core.Direction import net.minecraft.world.Container import net.minecraft.world.SimpleContainer import net.minecraft.world.entity.player.Inventory -import org.neoflock.neocomputers.gui.menu.Menus; -import net.minecraft.world.entity.player.Player -import net.minecraft.world.inventory.AbstractContainerMenu -import net.minecraft.world.inventory.MenuType -import net.minecraft.world.item.ItemStack -import org.neoflock.neocomputers.NeoComputers -import org.neoflock.neocomputers.entity.MachineEntity +import org.neoflock.neocomputers.entity.CaseBlockEntity import org.neoflock.neocomputers.gui.widget.ComponentRoles import org.neoflock.neocomputers.gui.widget.ComponentSlot import org.neoflock.neocomputers.gui.widget.ComponentSlotRequirement -import org.neoflock.neocomputers.gui.widget.DynamicSlot -import org.neoflock.neocomputers.item.ComponentItem -import org.neoflock.neocomputers.network.Networking import org.neoflock.neocomputers.utils.GenericContainerMenu -// lowest IQ machine to exist -class DumbMachine: MachineEntity { - override fun getBlockPosition() = BlockPos.ZERO!! - - override fun isRunning() = false - - override fun start() = false - - override fun stop() = false - - override fun crash(error: String) = false - - override fun getMachineNode() = Networking.Node() - - override fun getRedstoneInput(direction: Direction): Int = 0 - - override fun getRedstoneOutput(direction: Direction): Int = 0 - - override fun setRedstoneOutput(direction: Direction, newValue: Int): Int = 0 -} - -class CaseMenu : GenericContainerMenu { - constructor(i: Int, inv: Inventory) : this(i, inv, SimpleContainer(7)) - +open class CaseMenu : GenericContainerMenu { open val eepromRequirement = ComponentSlotRequirement(1, ComponentRoles.FIRMWARE) open val slotRequirements = listOf( listOf(ComponentSlotRequirement(1, ComponentRoles.CARD), ComponentSlotRequirement(1, ComponentRoles.CARD)), @@ -51,18 +17,23 @@ class CaseMenu : GenericContainerMenu { listOf(ComponentSlotRequirement(1, ComponentRoles.STORAGE)), ) + constructor(i: Int, inv: Inventory) : this(i, inv, SimpleContainer(7)) + constructor(i: Int, inv: Inventory, container: Container) : super(Menus.CASE_MENU.get(), i, container) { this.addInventorySlots(inv, 8, 84) - this.addSlot(ComponentSlot(this.container!!, 0, 20, 34, DumbMachine(), eepromRequirement)) + val machine = container as? CaseBlockEntity + + this.addSlot(ComponentSlot(this.container, 0, 20, 34, machine, eepromRequirement)) var i = 1 for ((col, slotCol) in slotRequirements.withIndex()) { for ((row, slotReq) in slotCol.withIndex()) { - this.addSlot(ComponentSlot(this.container!!, i, 98+(col*22), 18*(row+1)-2, DumbMachine(), slotReq)) + this.addSlot(ComponentSlot(this.container, i, 98+(col*22), 18*(row+1)-2, machine, slotReq)) i++ } } + // for (int col=1; col<4; col++) { // for (int row=1; row<4; row++) { // int i = (row-1)*3+(col-1); diff --git a/src/main/kotlin/org/neoflock/neocomputers/gui/menu/ScreenMenu.kt b/src/main/kotlin/org/neoflock/neocomputers/gui/menu/ScreenMenu.kt index c90bb1a..b0427d2 100644 --- a/src/main/kotlin/org/neoflock/neocomputers/gui/menu/ScreenMenu.kt +++ b/src/main/kotlin/org/neoflock/neocomputers/gui/menu/ScreenMenu.kt @@ -1,14 +1,13 @@ package org.neoflock.neocomputers.gui.menu; +import net.minecraft.world.SimpleContainer import net.minecraft.world.entity.player.Inventory import org.neoflock.neocomputers.gui.menu.Menus; import net.minecraft.world.entity.player.Player import net.minecraft.world.inventory.AbstractContainerMenu import net.minecraft.world.inventory.MenuType import net.minecraft.world.item.ItemStack +import org.neoflock.neocomputers.utils.GenericContainerMenu -class ScreenMenu(i: Int, inv: Inventory) : AbstractContainerMenu(Menus.SCREEN_MENU.get(), i) { - - override fun stillValid(player: Player) = true // TODO: implement this properly - override fun quickMoveStack(player: Player, i: Int): ItemStack = ItemStack.EMPTY // there's no container here anyways +class ScreenMenu(i: Int, inv: Inventory) : GenericContainerMenu(Menus.SCREEN_MENU.get(), i, SimpleContainer(0)) { } \ No newline at end of file diff --git a/src/main/kotlin/org/neoflock/neocomputers/gui/render/ProgressBar.kt b/src/main/kotlin/org/neoflock/neocomputers/gui/render/ProgressBar.kt index ac999f6..49c381a 100644 --- a/src/main/kotlin/org/neoflock/neocomputers/gui/render/ProgressBar.kt +++ b/src/main/kotlin/org/neoflock/neocomputers/gui/render/ProgressBar.kt @@ -34,7 +34,7 @@ object ProgressBar { // TODO: variable length guiGraphics.blit(BAR, x+1, y, width-2, height, 1F, 0F, 1, 14, 3, 14) guiGraphics.blit(BAR, x+width-1, y, 1, height, 2F, 0F, 1, 14, 3, 14) - val frac = value.toFloat() / max.toFloat() + val frac = if(max == 0L) 0.0f else value.toFloat() / max.toFloat() val linew = ceil(frac*(width-2).toFloat()) guiGraphics.fill( RenderType.gui(), diff --git a/src/main/kotlin/org/neoflock/neocomputers/gui/screen/CaseScreen.kt b/src/main/kotlin/org/neoflock/neocomputers/gui/screen/CaseScreen.kt index e4bb314..ff6cc98 100644 --- a/src/main/kotlin/org/neoflock/neocomputers/gui/screen/CaseScreen.kt +++ b/src/main/kotlin/org/neoflock/neocomputers/gui/screen/CaseScreen.kt @@ -7,6 +7,7 @@ import com.mojang.blaze3d.vertex.VertexFormat import net.minecraft.client.gui.GuiGraphics import net.minecraft.client.gui.components.ImageButton import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen +import net.minecraft.network.FriendlyByteBuf import net.minecraft.network.chat.Component import net.minecraft.resources.ResourceLocation import net.minecraft.world.entity.player.Inventory @@ -18,8 +19,28 @@ import org.neoflock.neocomputers.utils.GenericContainerScreen class CaseScreen : GenericContainerScreen { private val PCB: ResourceLocation = ResourceLocation.fromNamespaceAndPath(NeoComputers.MODID, "textures/gui/computer.png") + private val POWER_ATLAS: ResourceLocation = ResourceLocation.fromNamespaceAndPath(NeoComputers.MODID, "textures/gui/button_power.png") + private val BTN_SIZE = 18 override fun shouldCenterTitle(): Boolean = false + + var isOn = false + var energy = 0L + var energyTotal = 0L + var memUsed = 0L + var memTotal = 0L + var compUsed = 0L + var compTotal = 0L + + override fun processScreenStatePacket(buf: FriendlyByteBuf) { + isOn = buf.readBoolean() + energy = buf.readLong() + energyTotal = buf.readLong() + memUsed = buf.readLong() + memTotal = buf.readLong() + compUsed = buf.readLong() + compTotal = buf.readLong() + } constructor(abstractContainerMenu: CaseMenu, inventory: Inventory, component: Component) : super(abstractContainerMenu, inventory, component) override fun renderBg(guiGraphics: GuiGraphics, f: Float, i: Int, j: Int) { @@ -33,6 +54,14 @@ class CaseScreen : GenericContainerScreen { } + override fun renderCustomOverlay(graphics: GuiGraphics, mouseX: Int, mouseY: Int, blend: Float) { + super.renderCustomOverlay(graphics, mouseX, mouseY, blend) + val relX = (this.width - this.imageWidth) / 2 + val relY = (this.height - this.imageHeight) / 2 + + graphics.blit(POWER_ATLAS, relX, relY, BTN_SIZE, BTN_SIZE, 0.5f, 0.5f, BTN_SIZE, BTN_SIZE, BTN_SIZE*2, BTN_SIZE*2) + } + // private fun renderSlots(relX: Int, relY: Int) { // TODO: put this in some generic screen class // for (slot in menu.slots) { // if (slot is DynamicSlot) { diff --git a/src/main/kotlin/org/neoflock/neocomputers/gui/widget/ComponentSlot.kt b/src/main/kotlin/org/neoflock/neocomputers/gui/widget/ComponentSlot.kt index 05db6b8..0d2276f 100644 --- a/src/main/kotlin/org/neoflock/neocomputers/gui/widget/ComponentSlot.kt +++ b/src/main/kotlin/org/neoflock/neocomputers/gui/widget/ComponentSlot.kt @@ -85,7 +85,7 @@ data class ComponentSlotRequirement(val tier: Int, val role: String) { // Tier 0 allows ALL tiers, making it completely untiered. // Role determines what the role is. -class ComponentSlot(container: Container, slot: Int, x: Int, y: Int, val machine: MachineEntity, val requirement: ComponentSlotRequirement): DynamicSlot(container, slot, x, y) { +class ComponentSlot(container: Container, slot: Int, x: Int, y: Int, val machine: MachineEntity?, val requirement: ComponentSlotRequirement): DynamicSlot(container, slot, x, y) { override fun draw(graphics: GuiGraphics, relX: Int, relY: Int, mouseX: Int, mouseY: Int) { super.draw(graphics, relX, relY, mouseX, mouseY) if(!hasItem()) { @@ -115,16 +115,20 @@ class ComponentSlot(container: Container, slot: Int, x: Int, y: Int, val machine override fun set(itemStack: ItemStack) { super.set(itemStack) - val item = itemStack.item - if(item is ComponentItem) { - item.whenComponentPlaced(itemStack, machine, requirement.role) + if(machine != null) { + val item = itemStack.item + if (item is ComponentItem) { + item.whenComponentPlaced(itemStack, machine, requirement.role) + } } } override fun onTake(player: Player, itemStack: ItemStack) { - val item = itemStack.item - if(item is ComponentItem) { - item.whenComponentTaken(itemStack, machine, requirement.role) + if(machine != null) { + val item = itemStack.item + if (item is ComponentItem) { + item.whenComponentTaken(itemStack, machine, requirement.role) + } } super.onTake(player, itemStack) } diff --git a/src/main/kotlin/org/neoflock/neocomputers/item/ComponentItem.kt b/src/main/kotlin/org/neoflock/neocomputers/item/ComponentItem.kt index 56da218..b90bcc5 100644 --- a/src/main/kotlin/org/neoflock/neocomputers/item/ComponentItem.kt +++ b/src/main/kotlin/org/neoflock/neocomputers/item/ComponentItem.kt @@ -21,11 +21,13 @@ interface ComponentItem { if(oldNode != null) Networking.removeNode(oldNode) // did a mod forget to call whenComponentTaken? val node = toComponentNode(itemStack, machine) ?: return Networking.addNode(node) + machine.getMachineNode().connectTo(node) } // Component taken, and thus removed fun whenComponentTaken(itemStack: ItemStack, machine: MachineEntity, previousRole: String) { val node = getComponentNode(itemStack) ?: return + node.disconnectFrom(machine.getMachineNode()) Networking.removeNode(node) } diff --git a/src/main/kotlin/org/neoflock/neocomputers/item/DataComponents.kt b/src/main/kotlin/org/neoflock/neocomputers/item/DataComponents.kt index b389d52..0672974 100644 --- a/src/main/kotlin/org/neoflock/neocomputers/item/DataComponents.kt +++ b/src/main/kotlin/org/neoflock/neocomputers/item/DataComponents.kt @@ -6,6 +6,7 @@ import net.minecraft.core.component.DataComponentType import net.minecraft.core.registries.BuiltInRegistries import net.minecraft.resources.ResourceLocation import org.neoflock.neocomputers.NeoComputers +import java.nio.ByteBuffer object DataComponents { val ADDRESS = Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, ResourceLocation.fromNamespaceAndPath(NeoComputers.MODID, "address"), @@ -15,7 +16,7 @@ object DataComponents { val READONLY = Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, ResourceLocation.fromNamespaceAndPath(NeoComputers.MODID, "readonly"), DataComponentType.builder().persistent(Codec.BOOL).build()) val EEPROM_CODE = Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, ResourceLocation.fromNamespaceAndPath(NeoComputers.MODID, "eeprom_code"), - DataComponentType.builder().persistent(Codec.STRING).build()) + DataComponentType.builder().persistent(Codec.BYTE_BUFFER).build()) val EEPROM_DATA = Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, ResourceLocation.fromNamespaceAndPath(NeoComputers.MODID, "eeprom_data"), - DataComponentType.builder().persistent(Codec.STRING).build()) + DataComponentType.builder().persistent(Codec.BYTE_BUFFER).build()) } \ No newline at end of file diff --git a/src/main/kotlin/org/neoflock/neocomputers/item/EEPROMItem.kt b/src/main/kotlin/org/neoflock/neocomputers/item/EEPROMItem.kt index 66612c0..f925967 100644 --- a/src/main/kotlin/org/neoflock/neocomputers/item/EEPROMItem.kt +++ b/src/main/kotlin/org/neoflock/neocomputers/item/EEPROMItem.kt @@ -8,15 +8,15 @@ import org.neoflock.neocomputers.entity.MachineEntity import org.neoflock.neocomputers.gui.widget.ComponentRoles import org.neoflock.neocomputers.network.Networking import org.neoflock.neocomputers.utils.Formatting -import java.util.UUID +import java.nio.ByteBuffer -fun getEEPROMProperties(): Item.Properties = Item.Properties() - .component(DataComponents.EEPROM_CODE, "") - .component(DataComponents.EEPROM_DATA, "") +fun getEEPROMProperties(codeCap: Int, dataCap: Int): Item.Properties = Item.Properties() + .component(DataComponents.EEPROM_CODE, ByteBuffer.allocate(codeCap)) + .component(DataComponents.EEPROM_DATA, ByteBuffer.allocate(dataCap)) .component(DataComponents.LABEL, "") .component(DataComponents.READONLY, false) -open class EEPROMItem(val tier: Int, val codeCapacity: Int, val dataCapacity: Int): Item(getEEPROMProperties()), ComponentItem { +open class EEPROMItem(val tier: Int, val codeCapacity: Int, val dataCapacity: Int): Item(getEEPROMProperties(codeCapacity, dataCapacity)), ComponentItem { override fun getComponentRoles(itemStack: ItemStack): Set = setOf(ComponentRoles.FIRMWARE) override fun getComponentTier(itemStack: ItemStack): Int = tier @@ -39,12 +39,10 @@ open class EEPROMItem(val tier: Int, val codeCapacity: Int, val dataCapacity: In tooltipFlag: TooltipFlag ) { if(tooltipFlag.isAdvanced) { - val code = itemStack.get(DataComponents.EEPROM_CODE) ?: "" - val data = itemStack.get(DataComponents.EEPROM_DATA) ?: "" + val codeSize = itemStack.get(DataComponents.EEPROM_CODE)?.position() ?: 0 + val dataSize = itemStack.get(DataComponents.EEPROM_DATA)?.position() ?: 0 val addr = itemStack.get(DataComponents.ADDRESS) val readonly = itemStack.get(DataComponents.READONLY) ?: false - val codeSize = code.encodeToByteArray().size - val dataSize = data.encodeToByteArray().size val addrComp = if(addr == null) Component.translatable("neocomputers.noaddr") else Component.literal(addr) list.addLast(addrComp) list.addLast(Component.translatable("neocomputers.eeprom.codeused", Formatting.formatMemory(codeSize.toLong()), diff --git a/src/main/kotlin/org/neoflock/neocomputers/item/GPUCard.kt b/src/main/kotlin/org/neoflock/neocomputers/item/GPUCard.kt index b5541e4..3f10eee 100644 --- a/src/main/kotlin/org/neoflock/neocomputers/item/GPUCard.kt +++ b/src/main/kotlin/org/neoflock/neocomputers/item/GPUCard.kt @@ -20,7 +20,7 @@ open class GPUCard(val tier: Int, val vram: Long): Item(Properties()), Component super.whenComponentPlaced(itemStack, machine, newRole) } - // TODO: Modem Component + // TODO: GPU Component override fun toComponentNode(itemStack: ItemStack, machine: MachineEntity): Networking.Node? = null override fun appendHoverText( diff --git a/src/main/kotlin/org/neoflock/neocomputers/item/Tabs.kt b/src/main/kotlin/org/neoflock/neocomputers/item/Tabs.kt index d777947..1273835 100644 --- a/src/main/kotlin/org/neoflock/neocomputers/item/Tabs.kt +++ b/src/main/kotlin/org/neoflock/neocomputers/item/Tabs.kt @@ -2,11 +2,14 @@ package org.neoflock.neocomputers.item import dev.architectury.registry.CreativeTabRegistry import dev.architectury.registry.registries.DeferredRegister +import net.minecraft.client.Minecraft import net.minecraft.core.registries.Registries import net.minecraft.network.chat.Component +import net.minecraft.resources.ResourceLocation import net.minecraft.world.item.CreativeModeTab import net.minecraft.world.item.ItemStack import org.neoflock.neocomputers.NeoComputers +import java.nio.ByteBuffer object Tabs { val TABS: DeferredRegister = @@ -53,11 +56,24 @@ object Tabs { output.accept(ItemStack(Items.EE0.get())) - val luaBios = ItemStack(Items.EE0.get()) - luaBios.set(DataComponents.LABEL, "Lua BIOS") - luaBios.set(DataComponents.EEPROM_CODE, "error('hi')") - luaBios.set(DataComponents.EEPROM_DATA, "random garbage") - output.accept(luaBios) + // Criminal black magic to put LuaBIOS EEPROM in the tabs + do { + val luaBios = ItemStack(Items.EE0.get()) + val res = Minecraft.getInstance().resourceManager.getResourceOrThrow( + ResourceLocation.fromNamespaceAndPath( + NeoComputers.MODID, + "lua/oc_bios.lua" + ) + ) + val stream = res.openAsReader() + val code = stream.readText().encodeToByteArray() + stream.close() + val codeBuf = ByteBuffer.allocate(code.size) + codeBuf.put(code) + luaBios.set(DataComponents.LABEL, "Lua BIOS") + luaBios.set(DataComponents.EEPROM_CODE, codeBuf) + output.accept(luaBios) + } while(false) } } } diff --git a/src/main/kotlin/org/neoflock/neocomputers/sounds/LoopingSoundInstance.kt b/src/main/kotlin/org/neoflock/neocomputers/sounds/LoopingSoundInstance.kt new file mode 100644 index 0000000..77d6fb1 --- /dev/null +++ b/src/main/kotlin/org/neoflock/neocomputers/sounds/LoopingSoundInstance.kt @@ -0,0 +1,35 @@ +package org.neoflock.neocomputers.sounds + +import net.minecraft.client.resources.sounds.AbstractTickableSoundInstance +import net.minecraft.client.resources.sounds.SoundInstance +import net.minecraft.sounds.SoundEvent +import net.minecraft.sounds.SoundSource +import org.neoflock.neocomputers.entity.MachineEntity + +class ComputerRunningSoundInstance: AbstractTickableSoundInstance { + val machine: MachineEntity + + fun updatePosition() { + val pos = machine.getBlockPosition() + this.x = pos.x.toDouble() + 0.5 + this.y = pos.y.toDouble() + 0.5 + this.z = pos.z.toDouble() + 0.5 + } + + constructor(machine: MachineEntity, soundEvent: SoundEvent, soundSource: SoundSource): super(soundEvent, soundSource, SoundInstance.createUnseededRandom()) { + this.machine = machine + this.looping = true + this.delay = 0 + this.volume = 1.0F + this.relative = true + updatePosition() + } + + override fun tick() { + if(!machine.isRunning()) { + this.stop() + } else { + updatePosition() + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/org/neoflock/neocomputers/sounds/Sounds.kt b/src/main/kotlin/org/neoflock/neocomputers/sounds/Sounds.kt new file mode 100644 index 0000000..9cfedb5 --- /dev/null +++ b/src/main/kotlin/org/neoflock/neocomputers/sounds/Sounds.kt @@ -0,0 +1,17 @@ +package org.neoflock.neocomputers.sounds + +import dev.architectury.registry.registries.DeferredRegister +import net.minecraft.core.registries.Registries +import net.minecraft.resources.ResourceLocation +import net.minecraft.sounds.SoundEvent +import org.neoflock.neocomputers.NeoComputers + +object Sounds { + val SOUNDS = DeferredRegister.create(NeoComputers.MODID, Registries.SOUND_EVENT)!! + + val COMPUTER_RUNNING = registerSound("computer_running") + + fun registerSound(name: String) = SOUNDS.register(name) { + SoundEvent.createVariableRangeEvent(ResourceLocation.fromNamespaceAndPath(NeoComputers.MODID, name)) + }!! +} \ No newline at end of file diff --git a/src/main/kotlin/org/neoflock/neocomputers/utils/GenericContainer.kt b/src/main/kotlin/org/neoflock/neocomputers/utils/GenericContainer.kt index 7112ad8..ef16e28 100644 --- a/src/main/kotlin/org/neoflock/neocomputers/utils/GenericContainer.kt +++ b/src/main/kotlin/org/neoflock/neocomputers/utils/GenericContainer.kt @@ -62,7 +62,7 @@ interface GenericContainer : Container { } } -abstract class GenericContainerMenu(menuType: MenuType<*>, id: Int, var container: Container?): AbstractContainerMenu(menuType, id) { +abstract class GenericContainerMenu(menuType: MenuType<*>, id: Int, var container: Container): AbstractContainerMenu(menuType, id) { fun addInventorySlots(inventory: Inventory, x: Int, y: Int) { // Based off the code in ChestMenu for (i in 0..2) { @@ -88,7 +88,7 @@ abstract class GenericContainerMenu(menuType: MenuType<*>, id: Int, var containe val stack = slot.item val copied = stack.copy() - val contSize = container!!.containerSize + val contSize = container.containerSize if(i < contSize) { if(!this.moveItemStackTo(stack, contSize, slots.size, true)) { @@ -108,7 +108,7 @@ abstract class GenericContainerMenu(menuType: MenuType<*>, id: Int, var containe } override fun stillValid(player: Player): Boolean { - return container!!.stillValid(player) + return container.stillValid(player) } } @@ -148,9 +148,13 @@ abstract class GenericContainerScreen(menu: T, inventor } } + open fun renderCustomOverlay(graphics: GuiGraphics, mouseX: Int, mouseY: Int, blend: Float) { + + } + override fun render(graphics: GuiGraphics, mouseX: Int, mouseY: Int, something: Float) { super.render(graphics, mouseX, mouseY, something) - + renderCustomOverlay(graphics, mouseX, mouseY, something) if(shouldRenderTooltip()) super.renderTooltip(graphics, mouseX, mouseY) } } \ No newline at end of file diff --git a/src/main/resources/assets/neocomputers/lua/oc_bios.lua b/src/main/resources/assets/neocomputers/lua/oc_bios.lua new file mode 100644 index 0000000..ec6060a --- /dev/null +++ b/src/main/resources/assets/neocomputers/lua/oc_bios.lua @@ -0,0 +1,64 @@ +local init +do + local component_invoke = component.invoke + local function boot_invoke(address, method, ...) + local result = table.pack(pcall(component_invoke, address, method, ...)) + if not result[1] then + return nil, result[2] + else + return table.unpack(result, 2, result.n) + end + end + + -- backwards compatibility, may remove later + local eeprom = component.list("eeprom")() + computer.getBootAddress = function() + return boot_invoke(eeprom, "getData") + end + computer.setBootAddress = function(address) + return boot_invoke(eeprom, "setData", address) + end + + do + local screen = component.list("screen")() + local gpu = component.list("gpu")() + if gpu and screen then + boot_invoke(gpu, "bind", screen) + end + end + local function tryLoadFrom(address) + local handle, reason = boot_invoke(address, "open", "/init.lua") + if not handle then + return nil, reason + end + local buffer = "" + repeat + local data, reason = boot_invoke(address, "read", handle, math.maxinteger or math.huge) + if not data and reason then + return nil, reason + end + buffer = buffer .. (data or "") + until not data + boot_invoke(address, "close", handle) + return load(buffer, "=init") + end + local reason + if computer.getBootAddress() then + init, reason = tryLoadFrom(computer.getBootAddress()) + end + if not init then + computer.setBootAddress() + for address in component.list("filesystem") do + init, reason = tryLoadFrom(address) + if init then + computer.setBootAddress(address) + break + end + end + end + if not init then + error("no bootable medium found" .. (reason and (": " .. tostring(reason)) or ""), 0) + end + computer.beep(1000, 0.2) +end +return init() diff --git a/src/main/resources/assets/neocomputers/sounds.json b/src/main/resources/assets/neocomputers/sounds.json new file mode 100644 index 0000000..6acef02 --- /dev/null +++ b/src/main/resources/assets/neocomputers/sounds.json @@ -0,0 +1,9 @@ +{ + "computer_running": { + "subtitle": "sounds.neocomputers.computer_running", + "category": "ambient", + "sounds": [ + {"name": "neocomputers:computer_running", "stream": true} + ] + } +} \ No newline at end of file diff --git a/src/main/resources/assets/neocomputers/sounds/computer_running.ogg b/src/main/resources/assets/neocomputers/sounds/computer_running.ogg new file mode 100644 index 0000000..c9404f9 Binary files /dev/null and b/src/main/resources/assets/neocomputers/sounds/computer_running.ogg differ