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 {
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 {

View File

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

View File

@@ -1,6 +1,8 @@
package org.neoflock.neocomputers.entity;
import net.minecraft.core.BlockPos
import net.minecraft.core.HolderLookup
import net.minecraft.nbt.CompoundTag
import net.minecraft.network.FriendlyByteBuf
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer
@@ -11,30 +13,56 @@ import org.neoflock.neocomputers.block.NodeBlockEntity
import org.neoflock.neocomputers.gui.buffer.BufferRenderer
import org.neoflock.neocomputers.network.Networking
import org.neoflock.neocomputers.network.PowerRole
import org.neoflock.neocomputers.utils.GPUChar
import org.neoflock.neocomputers.utils.TextBuffer
class ScreenEntity(blockPos: BlockPos, blockState: 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"
val scrwidth: Short = 50
val scrheight: Short = 16
val textBuf = TextBuffer(50, 16)
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) {
super.encodeScreenData(player, packet)
packet.writeShort(scrwidth.toInt())
packet.writeShort(scrheight.toInt())
textBuf.encodeContents(packet)
}
override fun tickNode(level: Level) {
super.tickNode(level)
if (bound == "screen/unbound") { // am i epstein or am i just retarded?
cleanrenderer()
createscreenstuffs()
}
}
override fun setRemoved() {
super.setRemoved()
@@ -46,15 +74,7 @@ class ScreenEntity(blockPos: BlockPos, blockState: BlockState) :
bound = "screen/"+node.address.toString().replace("-", "_")
NeoComputers.LOGGER.info(bound)
if (level!!.isClientSide) {
var buffer: MutableList<BufferRenderer.GPUChar> = mutableListOf()
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)
var renderer = BufferRenderer(ResourceLocation.fromNamespaceAndPath(NeoComputers.MODID, bound), textBuf)
renderer.drawBuffer()
cleanrenderer = { renderer.clean() }
}

View File

@@ -7,16 +7,18 @@ import net.minecraft.client.renderer.texture.TextureManager
import net.minecraft.resources.ResourceLocation
import org.neoflock.neocomputers.NeoComputers
import org.neoflock.neocomputers.utils.FontProvider
import org.neoflock.neocomputers.utils.GPUChar
import org.neoflock.neocomputers.utils.TextBuffer
import java.io.File
import kotlin.experimental.and
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 CHARH = 16
private var texwidth: Int = width*CHARW;
private var texheight: Int = height*CHARH;
private var texwidth: Int = buffer.width*CHARW;
private var texheight: Int = buffer.height*CHARH;
private var image: NativeImage = NativeImage(texwidth, texheight, true); // idk what the boolean is
private var tex: DynamicTexture = DynamicTexture(image)
@@ -46,9 +48,9 @@ class BufferRenderer(private var width: Int, private var height: Int, private va
}
fun drawBuffer() {
for (i in 0..<width) {
for (j in 0..<height) {
var char: GPUChar = get(i, j)
for (i in 0..<buffer.width) {
for (j in 0..<buffer.height) {
var char: GPUChar = buffer.get(i, j)
var x = i*CHARW
var y = j*CHARH
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()
}
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() {
Minecraft.getInstance().textureManager.release(this.id)
image.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.render.ScreenRenderer
import org.neoflock.neocomputers.utils.GenericContainerScreen
import org.neoflock.neocomputers.utils.TextBuffer
import kotlin.math.min
class ScreenScreen : GenericContainerScreen<ScreenMenu>{
private var renderer: ScreenRenderer = ScreenRenderer();
var scrWidth: Short = 0
var scrHeight: Short = 0
var textBuf = TextBuffer(0, 0)
override fun processScreenStatePacket(buf: FriendlyByteBuf) {
super.processScreenStatePacket(buf)
scrWidth = buf.readShort()
scrHeight = buf.readShort()
textBuf.decodeContents(buf)
}
constructor(abstractContainerMenu: ScreenMenu, inventory: Inventory, component: Component) : super(abstractContainerMenu, inventory, component) {
@@ -38,9 +37,9 @@ class ScreenScreen : GenericContainerScreen<ScreenMenu>{
this.inventoryLabelX = Int.MAX_VALUE
}
override fun renderBg(guiGraphics: GuiGraphics, f: Float, i: Int, j: Int) {
if(scrWidth > 0) {
imageWidth = scrWidth * 4
imageHeight = scrHeight * 8
if(textBuf.width > 0) {
imageWidth = textBuf.width * 4
imageHeight = textBuf.height * 8
renderer.render(guiGraphics, imageX, imageY, imageWidth, imageHeight)
}
}

View File

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

View File

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