Merge branch 'main' of https://gitea.codersquack.nl/NeoFlock/NeoComputers
This commit is contained in:
@@ -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) {{
|
||||
@@ -70,6 +72,15 @@ object NeoComputers {
|
||||
player ->
|
||||
NodeSynchronizer.playerScreenClosed(player)
|
||||
}
|
||||
|
||||
NetworkManager.registerReceiver(NetworkManager.c2s(),NodeSynchronizer.ScreenDataPayload.TYPE, NodeSynchronizer.ScreenDataPayload.CODEC, {
|
||||
packet, ctx ->
|
||||
val player = ctx.player
|
||||
if(player is ServerPlayer) {
|
||||
NodeSynchronizer.screenMap[player]?.processScreenInteraction(player, packet.buffer)
|
||||
}
|
||||
})
|
||||
|
||||
// we have to do this because the datagen task runs in the physical server
|
||||
EnvExecutor.runInEnv(Env.CLIENT) {{
|
||||
NetworkManager.registerReceiver(NetworkManager.s2c(),NodeSynchronizer.StatePayload.TYPE, NodeSynchronizer.StatePayload.CODEC, {
|
||||
@@ -93,7 +104,6 @@ object NeoComputers {
|
||||
// https://github.com/architectury/architectury-api/issues/518
|
||||
NetworkManager.registerS2CPayloadType(NodeSynchronizer.StatePayload.TYPE, NodeSynchronizer.StatePayload.CODEC)
|
||||
NetworkManager.registerS2CPayloadType(NodeSynchronizer.ScreenPayload.TYPE, NodeSynchronizer.ScreenPayload.CODEC)
|
||||
|
||||
}}
|
||||
|
||||
LOGGER.info("Registered!")
|
||||
|
||||
@@ -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<Block?, BlockState?>) {
|
||||
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)
|
||||
}
|
||||
}
|
||||
@@ -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<Block?, BlockState?>) {
|
||||
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()
|
||||
|
||||
@@ -68,6 +68,27 @@ object NodeSynchronizer {
|
||||
override fun type() = TYPE
|
||||
}
|
||||
|
||||
class ScreenDataPayload(var entityTypeWireID: String, var buffer: FriendlyByteBuf): CustomPacketPayload {
|
||||
companion object {
|
||||
val SCREEN_SYNC_ID = ResourceLocation.fromNamespaceAndPath(NeoComputers.MODID, "screen_data")
|
||||
val TYPE = CustomPacketPayload.Type<ScreenDataPayload>(SCREEN_SYNC_ID)
|
||||
val CODEC = object : StreamCodec<RegistryFriendlyByteBuf, ScreenDataPayload> {
|
||||
override fun decode(buf: RegistryFriendlyByteBuf): ScreenDataPayload {
|
||||
val id = buf.readByteArray().decodeToString()
|
||||
val buffer = FriendlyByteBuf(buf.copy(buf.readerIndex(), buf.readableBytes()))
|
||||
return ScreenDataPayload(id, buffer)
|
||||
}
|
||||
|
||||
override fun encode(buf: RegistryFriendlyByteBuf, payload: ScreenDataPayload) {
|
||||
buf.writeByteArray(payload.entityTypeWireID.encodeToByteArray())
|
||||
buf.writeBytes(payload.buffer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun type() = TYPE
|
||||
}
|
||||
|
||||
val screenMap = mutableMapOf<ServerPlayer, NodeBlockEntity>()
|
||||
|
||||
fun playerScreenClosed(player: ServerPlayer) {
|
||||
@@ -87,6 +108,10 @@ object NodeSynchronizer {
|
||||
NetworkManager.sendToPlayer(player, ScreenPayload(nodeTypeToWireID(ent.type), buf))
|
||||
}
|
||||
}
|
||||
|
||||
fun sendScreenInteraction(friendlyByteBuf: FriendlyByteBuf) {
|
||||
NetworkManager.sendToServer(ScreenDataPayload("", friendlyByteBuf))
|
||||
}
|
||||
}
|
||||
|
||||
abstract class NodeBlockEntity(blockEntityType: BlockEntityType<*>, blockPos: BlockPos, blockState: BlockState) : BlockEntity(blockEntityType, blockPos, blockState) {
|
||||
@@ -119,6 +144,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<BlockEntity> {
|
||||
|
||||
@@ -75,6 +75,11 @@ object BlockEntities {
|
||||
::CombustionGeneratorBlockEntity, mutableSetOf(Blocks.REDSTONEIO_BLOCK.get()), BullshitFix()
|
||||
)
|
||||
}
|
||||
val CASE_ENTITY: RegistrySupplier<BlockEntityType<CaseBlockEntity>> = BLOCKENTITIES.register("case") {
|
||||
BlockEntityType(
|
||||
::CaseBlockEntity, mutableSetOf(Blocks.CASE_BLOCK.get()), BullshitFix()
|
||||
)
|
||||
}
|
||||
|
||||
fun registerPowerBlocks() {
|
||||
PowerManager.registerPowerBlockEntity(CAPACITOR_ENTITY.get())
|
||||
|
||||
@@ -0,0 +1,210 @@
|
||||
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.Level
|
||||
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<ItemStack> = NonNullList<ItemStack>.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) {
|
||||
super.encodeScreenData(player, packet)
|
||||
packet.writeBoolean(isOn)
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
setChanged()
|
||||
}
|
||||
|
||||
override fun getMachineBlockPosition(): BlockPos = blockPos
|
||||
override fun getMachineLevel(): Level = level!!
|
||||
|
||||
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<ItemStack> = 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()
|
||||
}
|
||||
}
|
||||
@@ -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) {
|
||||
|
||||
@@ -2,26 +2,39 @@ package org.neoflock.neocomputers.entity
|
||||
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.world.level.Level
|
||||
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 getMachineBlockPosition(): BlockPos
|
||||
fun getMachineLevel(): Level
|
||||
|
||||
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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)) {
|
||||
}
|
||||
@@ -38,7 +38,7 @@ object ProgressBar {
|
||||
guiGraphics.fill(x+1, y+height-1, x+width, y+height, 0xFFFFFFFF.toInt()) // bottom right corner + bottom edge
|
||||
guiGraphics.fill(x+width-1, y+height-1, x+width, y+1, 0xFFFFFFFF.toInt()) // right edge
|
||||
|
||||
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(),
|
||||
|
||||
@@ -4,16 +4,19 @@ import com.mojang.blaze3d.vertex.BufferBuilder
|
||||
import com.mojang.blaze3d.vertex.DefaultVertexFormat
|
||||
import com.mojang.blaze3d.vertex.Tesselator
|
||||
import com.mojang.blaze3d.vertex.VertexFormat
|
||||
import io.netty.buffer.Unpooled
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.gui.components.Button
|
||||
import net.minecraft.client.gui.components.ImageButton
|
||||
import net.minecraft.client.gui.components.WidgetSprites
|
||||
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
|
||||
import org.neoflock.neocomputers.NeoComputers
|
||||
import org.neoflock.neocomputers.block.NodeSynchronizer
|
||||
import org.neoflock.neocomputers.gui.menu.CaseMenu
|
||||
import org.neoflock.neocomputers.gui.widget.ButtonSprites
|
||||
import org.neoflock.neocomputers.gui.widget.ImagerButton
|
||||
@@ -27,18 +30,26 @@ class CaseScreen : GenericContainerScreen<CaseMenu> {
|
||||
// private val BTN_ENABLED_HOVER: ResourceLocation = ResourceLocation.fromNamespaceAndPath(NeoComputers.MODID, "textures/gui/button/power/enabled_hover.png")
|
||||
// private val BTN_DISABLED_HOVER: ResourceLocation = ResourceLocation.fromNamespaceAndPath(NeoComputers.MODID, "textures/gui/power/disabled_hover.png")
|
||||
|
||||
|
||||
private var btn: ImagerButton? = null;
|
||||
private var btn: ImagerButton? = null
|
||||
override fun shouldCenterTitle(): Boolean = false
|
||||
|
||||
var isOn = false
|
||||
|
||||
override fun processScreenStatePacket(buf: FriendlyByteBuf) {
|
||||
super.processScreenStatePacket(buf)
|
||||
isOn = buf.readBoolean()
|
||||
btn?.pressed = isOn
|
||||
}
|
||||
|
||||
constructor(abstractContainerMenu: CaseMenu, inventory: Inventory, component: Component) : super(abstractContainerMenu, inventory, component) {
|
||||
btn = ImagerButton(
|
||||
15, 15,
|
||||
18, 18,
|
||||
ButtonSprites(BTN, 18, 18, 36, 36)
|
||||
) {
|
||||
var btn = it as ImagerButton
|
||||
btn.pressed = !btn.pressed
|
||||
val buf = FriendlyByteBuf(Unpooled.buffer())
|
||||
buf.writeByte(if(isOn) 0x02 else 0x01)
|
||||
NodeSynchronizer.sendScreenInteraction(buf)
|
||||
}
|
||||
// addRenderableWidget(btn!!)
|
||||
}
|
||||
@@ -47,7 +58,6 @@ class CaseScreen : GenericContainerScreen<CaseMenu> {
|
||||
val relX = (this.width - this.imageWidth) / 2
|
||||
val relY = (this.height - this.imageHeight) / 2
|
||||
|
||||
|
||||
btn!!.x = relX+70
|
||||
btn!!.y = relY+33
|
||||
btn!!.render(guiGraphics, i, j, f) // minecraft SUCKSSS
|
||||
@@ -64,5 +74,4 @@ class CaseScreen : GenericContainerScreen<CaseMenu> {
|
||||
} else return false
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -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,17 +115,21 @@ class ComponentSlot(container: Container, slot: Int, x: Int, y: Int, val machine
|
||||
|
||||
override fun set(itemStack: ItemStack) {
|
||||
super.set(itemStack)
|
||||
if(machine != null) {
|
||||
val item = itemStack.item
|
||||
if (item is ComponentItem) {
|
||||
item.whenComponentPlaced(itemStack, machine, requirement.role)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onTake(player: Player, itemStack: ItemStack) {
|
||||
if(machine != null) {
|
||||
val item = itemStack.item
|
||||
if (item is ComponentItem) {
|
||||
item.whenComponentTaken(itemStack, machine, requirement.role)
|
||||
}
|
||||
}
|
||||
super.onTake(player, itemStack)
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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<Boolean>().persistent(Codec.BOOL).build())
|
||||
val EEPROM_CODE = Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, ResourceLocation.fromNamespaceAndPath(NeoComputers.MODID, "eeprom_code"),
|
||||
DataComponentType.builder<String>().persistent(Codec.STRING).build())
|
||||
DataComponentType.builder<ByteBuffer>().persistent(Codec.BYTE_BUFFER).build())
|
||||
val EEPROM_DATA = Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, ResourceLocation.fromNamespaceAndPath(NeoComputers.MODID, "eeprom_data"),
|
||||
DataComponentType.builder<String>().persistent(Codec.STRING).build())
|
||||
DataComponentType.builder<ByteBuffer>().persistent(Codec.BYTE_BUFFER).build())
|
||||
}
|
||||
@@ -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<String> = 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()),
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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<CreativeModeTab> =
|
||||
@@ -53,11 +56,24 @@ object Tabs {
|
||||
|
||||
output.accept(ItemStack(Items.EE0.get()))
|
||||
|
||||
// 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, "error('hi')")
|
||||
luaBios.set(DataComponents.EEPROM_DATA, "random garbage")
|
||||
luaBios.set(DataComponents.EEPROM_CODE, codeBuf)
|
||||
output.accept(luaBios)
|
||||
} while(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
package org.neoflock.neocomputers.sounds
|
||||
|
||||
import net.minecraft.client.resources.sounds.AbstractTickableSoundInstance
|
||||
import net.minecraft.client.resources.sounds.EntityBoundSoundInstance
|
||||
import net.minecraft.client.resources.sounds.MinecartSoundInstance
|
||||
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.getMachineBlockPosition()
|
||||
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.pitch = 1.0F
|
||||
updatePosition()
|
||||
}
|
||||
|
||||
override fun tick() {
|
||||
if(!machine.isRunning()) {
|
||||
this.stop()
|
||||
} else {
|
||||
updatePosition()
|
||||
}
|
||||
}
|
||||
}
|
||||
17
src/main/kotlin/org/neoflock/neocomputers/sounds/Sounds.kt
Normal file
17
src/main/kotlin/org/neoflock/neocomputers/sounds/Sounds.kt
Normal file
@@ -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))
|
||||
}!!
|
||||
}
|
||||
@@ -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<T: GenericContainerMenu>(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)
|
||||
}
|
||||
}
|
||||
@@ -46,5 +46,6 @@
|
||||
"neocomputers.noaddr": "No address assigned",
|
||||
"neocomputers.memory.capacity": "Capacity: %1$s",
|
||||
"neocomputers.eeprom.codeused": "Code Storage: %1$s / %2$s",
|
||||
"neocomputers.eeprom.dataused": "Data Storage: %1$s / %2$s"
|
||||
"neocomputers.eeprom.dataused": "Data Storage: %1$s / %2$s",
|
||||
"sounds.neocomputers.computer_running": "Computer Fans"
|
||||
}
|
||||
64
src/main/resources/assets/neocomputers/lua/oc_bios.lua
Normal file
64
src/main/resources/assets/neocomputers/lua/oc_bios.lua
Normal file
@@ -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()
|
||||
9
src/main/resources/assets/neocomputers/sounds.json
Normal file
9
src/main/resources/assets/neocomputers/sounds.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"computer_running": {
|
||||
"subtitle": "sounds.neocomputers.computer_running",
|
||||
"category": "ambient",
|
||||
"sounds": [
|
||||
{"name": "neocomputers:computer_running", "stream": true}
|
||||
]
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Reference in New Issue
Block a user