le screen is le synchronized

This commit is contained in:
2026-04-26 06:20:02 +00:00
parent 83749bf3ba
commit ed6ddddf98
8 changed files with 153 additions and 52 deletions

View File

@@ -65,15 +65,6 @@ object NeoComputers {
} }
ClientLifecycleEvent.CLIENT_STARTED.register { ClientLifecycleEvent.CLIENT_STARTED.register {
FontProvider.load(ResourceLocation.fromNamespaceAndPath(MODID, "font/unscii.hex")) FontProvider.load(ResourceLocation.fromNamespaceAndPath(MODID, "font/unscii.hex"))
ScreenRenderer.genUnboundTex();
var buffer: MutableList<BufferRenderer.GPUChar> = mutableListOf(BufferRenderer.GPUChar('h'), BufferRenderer.GPUChar('i'))
for (i in 0..398) {
buffer.add(BufferRenderer.GPUChar(' '))
}
var renderer: BufferRenderer = BufferRenderer(20, 20, ResourceLocation.fromNamespaceAndPath(NeoComputers.MODID, "screen/test"), buffer)
renderer.drawBuffer()
} }
ClientLifecycleEvent.CLIENT_STOPPING.register { ClientLifecycleEvent.CLIENT_STOPPING.register {

View File

@@ -112,6 +112,7 @@ class CaseBlockEntity(blockPos: BlockPos, blockState: BlockState): NodeBlockEnti
item.onMachineEvent(it, this, event) item.onMachineEvent(it, this, event)
} }
} }
Networking.emitMessage(node, Networking.ComputerEvent(node, event))
} }
fun onRedstoneSignalChanged(dir: Direction, oldValue: Int, newValue: Int) { fun onRedstoneSignalChanged(dir: Direction, oldValue: Int, newValue: Int) {
@@ -147,7 +148,6 @@ class CaseBlockEntity(blockPos: BlockPos, blockState: BlockState): NodeBlockEnti
return return
} }
// Server-side stuff!! // Server-side stuff!!
world.onBlockStateChange(blockPos, blockState, blockState)
sendMachineEvent(MachinePowerEvent(this, isOn)) sendMachineEvent(MachinePowerEvent(this, isOn))
} }

View File

@@ -1,6 +1,8 @@
package org.neoflock.neocomputers.entity; package org.neoflock.neocomputers.entity;
import net.minecraft.core.BlockPos import net.minecraft.core.BlockPos
import net.minecraft.core.HolderLookup
import net.minecraft.nbt.CompoundTag
import net.minecraft.network.FriendlyByteBuf import net.minecraft.network.FriendlyByteBuf
import net.minecraft.resources.ResourceLocation import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer import net.minecraft.server.level.ServerPlayer
@@ -11,29 +13,55 @@ import org.neoflock.neocomputers.block.NodeBlockEntity
import org.neoflock.neocomputers.gui.buffer.BufferRenderer import org.neoflock.neocomputers.gui.buffer.BufferRenderer
import org.neoflock.neocomputers.network.Networking import org.neoflock.neocomputers.network.Networking
import org.neoflock.neocomputers.network.PowerRole import org.neoflock.neocomputers.network.PowerRole
import org.neoflock.neocomputers.utils.GPUChar
import org.neoflock.neocomputers.utils.TextBuffer
class ScreenEntity(blockPos: BlockPos, blockState: BlockState) : class ScreenEntity(blockPos: BlockPos, blockState: BlockState) :
NodeBlockEntity(BlockEntities.SCREEN_ENTITY.get(), blockPos, blockState) { NodeBlockEntity(BlockEntities.SCREEN_ENTITY.get(), blockPos, blockState) {
override val node = Networking.Node() override val node = object : Networking.Node() {
override fun received(message: Networking.Message) {
super.received(message)
if(message is Networking.ComputerEvent) {
// return if not directly connected
if(message.sender !in this.connections) return
val mEnv = message.machineEvent
NeoComputers.LOGGER.info("Got message $mEnv!")
if(mEnv is MachinePowerEvent) {
if(mEnv.nowRunning) {
textBuf.set(0, 0, address.toString())
} else {
textBuf.fill(0, 0, textBuf.width, textBuf.height, GPUChar(' '))
}
}
}
}
}
var bound = "screen/unbound" var bound = "screen/unbound"
val scrwidth: Short = 50 val textBuf = TextBuffer(50, 16)
val scrheight: Short = 16
private var cleanrenderer: () -> Unit = { }; // TODO: THIS SUCKS, FIND A BETTER WAY private var cleanrenderer: () -> Unit = { }; // TODO: THIS SUCKS, FIND A BETTER WAY
override fun encodeDownstreamData(packet: FriendlyByteBuf) {
super.encodeDownstreamData(packet)
textBuf.encodeContents(packet)
}
override fun syncWithUpstream(packet: FriendlyByteBuf) {
super.syncWithUpstream(packet)
textBuf.decodeContents(packet)
}
override fun encodeScreenData(player: ServerPlayer, packet: FriendlyByteBuf) { override fun encodeScreenData(player: ServerPlayer, packet: FriendlyByteBuf) {
super.encodeScreenData(player, packet) super.encodeScreenData(player, packet)
packet.writeShort(scrwidth.toInt()) textBuf.encodeContents(packet)
packet.writeShort(scrheight.toInt())
} }
override fun tickNode(level: Level) { override fun tickNode(level: Level) {
super.tickNode(level) super.tickNode(level)
if (bound == "screen/unbound") { // am i epstein or am i just retarded? cleanrenderer()
createscreenstuffs() createscreenstuffs()
}
} }
override fun setRemoved() { override fun setRemoved() {
@@ -46,15 +74,7 @@ class ScreenEntity(blockPos: BlockPos, blockState: BlockState) :
bound = "screen/"+node.address.toString().replace("-", "_") bound = "screen/"+node.address.toString().replace("-", "_")
NeoComputers.LOGGER.info(bound) NeoComputers.LOGGER.info(bound)
if (level!!.isClientSide) { if (level!!.isClientSide) {
var buffer: MutableList<BufferRenderer.GPUChar> = mutableListOf() var renderer = BufferRenderer(ResourceLocation.fromNamespaceAndPath(NeoComputers.MODID, bound), textBuf)
for(char in node.address.toString()) {
buffer.add(BufferRenderer.GPUChar(char))
}
for (i in 0..((scrwidth*scrheight)-36)) {
buffer.add(BufferRenderer.GPUChar(' '))
}
var renderer: BufferRenderer = BufferRenderer(scrwidth.toInt(), scrheight.toInt(), ResourceLocation.fromNamespaceAndPath(NeoComputers.MODID, bound), buffer)
renderer.drawBuffer() renderer.drawBuffer()
cleanrenderer = { renderer.clean() } cleanrenderer = { renderer.clean() }
} }

View File

@@ -7,16 +7,18 @@ import net.minecraft.client.renderer.texture.TextureManager
import net.minecraft.resources.ResourceLocation import net.minecraft.resources.ResourceLocation
import org.neoflock.neocomputers.NeoComputers import org.neoflock.neocomputers.NeoComputers
import org.neoflock.neocomputers.utils.FontProvider import org.neoflock.neocomputers.utils.FontProvider
import org.neoflock.neocomputers.utils.GPUChar
import org.neoflock.neocomputers.utils.TextBuffer
import java.io.File import java.io.File
import kotlin.experimental.and import kotlin.experimental.and
import kotlin.experimental.xor import kotlin.experimental.xor
class BufferRenderer(private var width: Int, private var height: Int, private var id: ResourceLocation, private var buffer: MutableList<GPUChar>) { // TODO: NN buffer class BufferRenderer(private var id: ResourceLocation, private var buffer: TextBuffer) { // TODO: NN buffer
val CHARW = 8 val CHARW = 8
val CHARH = 16 val CHARH = 16
private var texwidth: Int = width*CHARW; private var texwidth: Int = buffer.width*CHARW;
private var texheight: Int = height*CHARH; private var texheight: Int = buffer.height*CHARH;
private var image: NativeImage = NativeImage(texwidth, texheight, true); // idk what the boolean is private var image: NativeImage = NativeImage(texwidth, texheight, true); // idk what the boolean is
private var tex: DynamicTexture = DynamicTexture(image) private var tex: DynamicTexture = DynamicTexture(image)
@@ -46,9 +48,9 @@ class BufferRenderer(private var width: Int, private var height: Int, private va
} }
fun drawBuffer() { fun drawBuffer() {
for (i in 0..<width) { for (i in 0..<buffer.width) {
for (j in 0..<height) { for (j in 0..<buffer.height) {
var char: GPUChar = get(i, j) var char: GPUChar = buffer.get(i, j)
var x = i*CHARW var x = i*CHARW
var y = j*CHARH var y = j*CHARH
image.fillRect(x, y, CHARW, CHARH, (0xFF000000+char.bg).toInt()) image.fillRect(x, y, CHARW, CHARH, (0xFF000000+char.bg).toInt())
@@ -58,16 +60,9 @@ class BufferRenderer(private var width: Int, private var height: Int, private va
tex.upload() tex.upload()
} }
fun get(x: Int, y: Int) = buffer[y*width+x]
fun set(x: Int, y: Int, c: GPUChar) {
buffer[y*width+x] = c
}
fun clean() { fun clean() {
Minecraft.getInstance().textureManager.release(this.id) Minecraft.getInstance().textureManager.release(this.id)
image.close() image.close()
tex.close() tex.close()
} }
data class GPUChar(val c: Char, val fg: Int =0xFFFFFF, val bg: Int = 0) // all is bgr
} }

View File

@@ -16,18 +16,17 @@ import org.neoflock.neocomputers.gui.buffer.BufferRenderer
import org.neoflock.neocomputers.gui.menu.ScreenMenu import org.neoflock.neocomputers.gui.menu.ScreenMenu
import org.neoflock.neocomputers.gui.render.ScreenRenderer import org.neoflock.neocomputers.gui.render.ScreenRenderer
import org.neoflock.neocomputers.utils.GenericContainerScreen import org.neoflock.neocomputers.utils.GenericContainerScreen
import org.neoflock.neocomputers.utils.TextBuffer
import kotlin.math.min import kotlin.math.min
class ScreenScreen : GenericContainerScreen<ScreenMenu>{ class ScreenScreen : GenericContainerScreen<ScreenMenu>{
private var renderer: ScreenRenderer = ScreenRenderer(); private var renderer: ScreenRenderer = ScreenRenderer();
var scrWidth: Short = 0 var textBuf = TextBuffer(0, 0)
var scrHeight: Short = 0
override fun processScreenStatePacket(buf: FriendlyByteBuf) { override fun processScreenStatePacket(buf: FriendlyByteBuf) {
super.processScreenStatePacket(buf) super.processScreenStatePacket(buf)
scrWidth = buf.readShort() textBuf.decodeContents(buf)
scrHeight = buf.readShort()
} }
constructor(abstractContainerMenu: ScreenMenu, inventory: Inventory, component: Component) : super(abstractContainerMenu, inventory, component) { constructor(abstractContainerMenu: ScreenMenu, inventory: Inventory, component: Component) : super(abstractContainerMenu, inventory, component) {
@@ -38,9 +37,9 @@ class ScreenScreen : GenericContainerScreen<ScreenMenu>{
this.inventoryLabelX = Int.MAX_VALUE this.inventoryLabelX = Int.MAX_VALUE
} }
override fun renderBg(guiGraphics: GuiGraphics, f: Float, i: Int, j: Int) { override fun renderBg(guiGraphics: GuiGraphics, f: Float, i: Int, j: Int) {
if(scrWidth > 0) { if(textBuf.width > 0) {
imageWidth = scrWidth * 4 imageWidth = textBuf.width * 4
imageHeight = scrHeight * 8 imageHeight = textBuf.height * 8
renderer.render(guiGraphics, imageX, imageY, imageWidth, imageHeight) renderer.render(guiGraphics, imageX, imageY, imageWidth, imageHeight)
} }
} }

View File

@@ -2,6 +2,7 @@ package org.neoflock.neocomputers.network
import net.minecraft.core.BlockPos import net.minecraft.core.BlockPos
import org.neoflock.neocomputers.NeoComputers import org.neoflock.neocomputers.NeoComputers
import org.neoflock.neocomputers.entity.MachineEvent
import java.util.UUID import java.util.UUID
import kotlin.math.min import kotlin.math.min
import kotlin.math.pow import kotlin.math.pow
@@ -43,6 +44,7 @@ object Networking {
// for plugins and shi // for plugins and shi
class ComputerCheckedSignal(sender: Node, val player: String?, val name: String, val data: Array<Any>): Message(sender) class ComputerCheckedSignal(sender: Node, val player: String?, val name: String, val data: Array<Any>): Message(sender)
class ComputerUncheckedSignal(sender: Node, val name: String, val data: Array<Any>): Message(sender) class ComputerUncheckedSignal(sender: Node, val name: String, val data: Array<Any>): Message(sender)
class ComputerEvent(sender: Node, val machineEvent: MachineEvent): Message(sender)
open class Node(_address: UUID? = null) { open class Node(_address: UUID? = null) {
val connections = mutableSetOf<Node>() val connections = mutableSetOf<Node>()

View File

@@ -99,7 +99,6 @@ object Sounds {
fun checkDone(): Boolean { fun checkDone(): Boolean {
if(dead) return true if(dead) return true
if(AL10.alGetSourcei(source, AL10.AL_SOURCE_STATE) == AL10.AL_PLAYING) return false if(AL10.alGetSourcei(source, AL10.AL_SOURCE_STATE) == AL10.AL_PLAYING) return false
NeoComputers.LOGGER.info("sound buffer stopped")
dead = true dead = true
AL10.alDeleteSources(source) AL10.alDeleteSources(source)
AL10.alDeleteBuffers(buffer) AL10.alDeleteBuffers(buffer)
@@ -146,10 +145,6 @@ object Sounds {
} }
} }
finalBuf.rewind() finalBuf.rewind()
val l = mutableListOf<Int>()
while(finalBuf.hasRemaining()) l.addLast(finalBuf.get().toInt())
finalBuf.rewind()
NeoComputers.LOGGER.info("$l")
val sound = CustomSoundBuffer() val sound = CustomSoundBuffer()
val soundErr = sound.start(pos.x.toFloat(), pos.y.toFloat(), pos.z.toFloat(), finalBuf, gain.toFloat()) val soundErr = sound.start(pos.x.toFloat(), pos.y.toFloat(), pos.z.toFloat(), finalBuf, gain.toFloat())

View File

@@ -0,0 +1,99 @@
package org.neoflock.neocomputers.utils
import net.minecraft.network.FriendlyByteBuf
import kotlin.math.min
data class GPUChar(val c: Char, val fg: Int =0xFFFFFF, val bg: Int = 0) // all is bgr
// TODO: wrapper over NN buffer
class TextBuffer(var width: Int, var height: Int) {
val blank = GPUChar(' ')
var buf = Array(width*height) { blank }
fun encodeContents(buf: FriendlyByteBuf) {
// 0x01 means set fg, 0x02 means set bg,
// 0x03 means set char+count
var lastFg = 0xFFFFFF
var lastBg = 0x000000
buf.writeVarInt(width)
buf.writeVarInt(height)
var i = 0
while(i < this.buf.size) {
val px = this.buf[i]
if(px.fg != lastFg) {
buf.writeByte(0x01)
buf.writeVarInt(px.fg)
lastFg = px.fg
}
if(px.bg != lastBg) {
buf.writeByte(0x02)
buf.writeVarInt(px.bg)
lastBg = px.bg
}
var charWritten = 1
while((i+charWritten) < this.buf.size && this.buf[i+charWritten].c == px.c) charWritten++
buf.writeByte(0x03)
buf.writeVarInt(px.c.code)
buf.writeVarInt(charWritten)
i += charWritten
}
}
fun decodeContents(buf: FriendlyByteBuf) {
var lastFg = 0xFFFFFF
var lastBg = 0x000000
width = buf.readVarInt()
height = buf.readVarInt()
if(width*height != this.buf.size) {
this.buf = Array(width * height) { blank }
}
var i = 0
while(i < width*height) {
val op = buf.readByte().toInt()
if(op == 0x01) {
lastFg = buf.readVarInt()
}
if(op == 0x02) {
lastBg = buf.readVarInt()
}
if(op == 0x03) {
val c = buf.readVarInt().toChar()
val n = buf.readVarInt()
for(o in 0..<n) {
this.buf[i+o] = GPUChar(c, lastFg, lastBg)
}
i += n
}
}
}
fun inBounds(x: Int, y: Int) = x >= 0 && y >= 0 && x < width && y < height
fun get(x: Int, y: Int) = if(inBounds(x, y)) buf[x+y*width] else blank
fun set(x: Int, y: Int, pixel: GPUChar) {
if(!inBounds(x, y)) return
buf[x+y*width] = pixel
}
fun set(x: Int, y: Int, text: String, fg: Int = 0xFFFFFF, bg: Int = 0x000000, vertical: Boolean = false) {
for ((i, c) in text.toCharArray().withIndex()) {
val cx = if(vertical) x else x + i
val cy = if(vertical) y + i else y
set(cx, cy, GPUChar(c, fg, bg))
}
}
fun fill(x: Int, y: Int, w: Int, h: Int, pixel: GPUChar = blank) {
// turn it into values we can fw
val fw = min(w, width)
val fh = min(h, height)
for(py in y..<y+fh) {
for (px in x..<x + fw) {
set(px, py, pixel)
}
}
}
}