Render screen texture on block

This commit is contained in:
2026-04-22 22:30:23 +02:00
parent faa1be7175
commit 55f30283c3
10 changed files with 166 additions and 28 deletions

View File

@@ -0,0 +1,13 @@
package org.neoflock.neocomputers.platforms.fabric.client;
import net.fabricmc.api.ClientModInitializer;
import net.minecraft.client.renderer.blockentity.BlockEntityRenderers;
import org.neoflock.neocomputers.entity.BlockEntities;
import org.neoflock.neocomputers.gui.render.ScreenEntityRenderer;
public class NeoComputersFabricClient implements ClientModInitializer {
@Override
public void onInitializeClient() {
BlockEntityRenderers.register(BlockEntities.INSTANCE.getSCREEN_ENTITY().get(), ScreenEntityRenderer::new);
}
}

View File

@@ -1,5 +1,7 @@
package org.neoflock.neocomputers
import com.mojang.blaze3d.vertex.DefaultVertexFormat
import com.mojang.blaze3d.vertex.VertexFormat
import dev.architectury.event.events.client.ClientLifecycleEvent
import dev.architectury.event.events.common.PlayerEvent
import dev.architectury.event.events.common.TickEvent
@@ -11,11 +13,15 @@ import org.neoflock.neocomputers.gui.menu.Menus
import dev.architectury.utils.Env
import dev.architectury.utils.EnvExecutor
import net.minecraft.client.Minecraft
import net.minecraft.client.renderer.RenderStateShard
import net.minecraft.client.renderer.RenderType
import net.minecraft.server.level.ServerPlayer
import org.neoflock.neocomputers.block.NodeBlockEntity
import org.neoflock.neocomputers.block.NodeSynchronizer
import org.neoflock.neocomputers.gui.buffer.BufferRenderer
import org.neoflock.neocomputers.gui.render.ScreenRenderer
import org.neoflock.neocomputers.gui.widget.ComponentRoles
import org.neoflock.neocomputers.item.GPUCard
import org.neoflock.neocomputers.item.Items
import org.neoflock.neocomputers.item.Tabs
import org.neoflock.neocomputers.network.Networking
@@ -24,12 +30,19 @@ import org.neoflock.neocomputers.utils.FontProvider
import org.neoflock.neocomputers.utils.GenericContainerScreen
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import java.nio.Buffer
object NeoComputers {
const val MODID: String = "neocomputers"
val LOGGER: Logger = LoggerFactory.getLogger("NeoComputers")
var PLATFORM: ModPlatform? = null
val BlockEntityRenderType: RenderType = RenderType.create(
"nc_blockentities",
DefaultVertexFormat.POSITION_TEX,
VertexFormat.Mode.QUADS,
0xc000, RenderType.CompositeState.builder().setShaderState(RenderStateShard.POSITION_TEX_SHADER).createCompositeState(false)) // TODO: figure out correct buffer size and composite state
fun entrypoint(platform: ModPlatform?) {
PLATFORM = platform
@@ -51,6 +64,14 @@ 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

@@ -1,8 +1,10 @@
package org.neoflock.neocomputers.block;
import dev.architectury.registry.menu.ExtendedMenuProvider
import dev.architectury.registry.menu.MenuRegistry
import net.minecraft.core.BlockPos
import net.minecraft.core.Direction
import net.minecraft.network.FriendlyByteBuf
import net.minecraft.network.chat.Component
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.InteractionHand
@@ -35,6 +37,7 @@ import kotlin.math.max
class ScreenBlock() : NodeBlock() {
companion object {
val FACING: EnumProperty<Direction> = EnumProperty.create<Direction>("facing", Direction::class.java)
val ENERGY: Long = 5
}
init {
@@ -56,14 +59,19 @@ class ScreenBlock() : NodeBlock() {
): InteractionResult {
if(!level.isClientSide) {
val screenState = level.getBlockEntity(blockPos, BlockEntities.SCREEN_ENTITY.get()).get()
if(!screenState.node.consumeEnergy(5)) {
if(!screenState.node.consumeEnergy(ENERGY)) {
player.sendSystemMessage(Component.literal("Not enough power."))
return InteractionResult.SUCCESS
};
MenuRegistry.openMenu(player as ServerPlayer, object : MenuProvider {
MenuRegistry.openExtendedMenu(player as ServerPlayer, object : ExtendedMenuProvider {
override fun getDisplayName(): Component = Component.literal("SCREEEEEN!")
override fun createMenu(i: Int, inventory: Inventory, player: Player): AbstractContainerMenu {
return Menus.SCREEN_MENU.get().create(i, inventory);
// return Menus.SCREEN_MENU.get().create(i, inventory);
return ScreenMenu(i, inventory, level.getBlockEntity(blockPos, BlockEntities.SCREEN_ENTITY.get()).get())
}
override fun saveExtraData(buf: FriendlyByteBuf?) {
buf!!.writeBlockPos(blockPos)
}
})
}

View File

@@ -1,8 +1,12 @@
package org.neoflock.neocomputers.entity;
import net.minecraft.core.BlockPos
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.level.Level
import net.minecraft.world.level.block.state.BlockState
import org.neoflock.neocomputers.NeoComputers
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
@@ -10,4 +14,38 @@ class ScreenEntity(blockPos: BlockPos, blockState: BlockState) :
NodeBlockEntity(BlockEntities.SCREEN_ENTITY.get(), blockPos, blockState) {
override val node = Networking.Node()
var bound = "screen/unbound"
var render_on_block = false
private var cleanrenderer: () -> Unit = { }; // TODO: THIS SUCKS, FIND A BETTER WAY
override fun setChanged() {
super.setChanged()
if (bound == "screen/unbound") {
createscreenstuffs()
}
}
override fun setRemoved() {
super.setRemoved()
cleanrenderer()
}
private fun createscreenstuffs() {
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, 0xFFFF00, 0x0000FF))
}
for (i in 0..((40*20)-36)) {
buffer.add(BufferRenderer.GPUChar(' '))
}
var renderer: BufferRenderer = BufferRenderer(40, 20, ResourceLocation.fromNamespaceAndPath(NeoComputers.MODID, bound), buffer)
renderer.drawBuffer()
cleanrenderer = { renderer.clean() }
}
}
}

View File

@@ -17,7 +17,8 @@ import org.neoflock.neocomputers.gui.screen.ScreenScreen
object Menus {
val MENUS: DeferredRegister<MenuType<*>> = DeferredRegister.create(NeoComputers.MODID, Registries.MENU)
val SCREEN_MENU: RegistrySupplier<MenuType<ScreenMenu>> = MENUS.register("screen_menu") { MenuType(::ScreenMenu, FeatureFlagSet.of()) }
// val SCREEN_MENU: RegistrySupplier<MenuType<ScreenMenu>> = MENUS.register("screen_menu") { MenuType(::ScreenMenu, FeatureFlagSet.of()) }
val SCREEN_MENU: RegistrySupplier<MenuType<ScreenMenu>> = MENUS.register("screen_menu") { MenuRegistry.ofExtended<ScreenMenu>(::ScreenMenu) }
val COMBUSTGEN_MENU: RegistrySupplier<MenuType<CombustionGeneratorMenu>> = MENUS.register("combustgen_menu") { MenuType(::CombustionGeneratorMenu, FeatureFlagSet.of() ) }
val CASE_MENU: RegistrySupplier<MenuType<CaseMenu>> = MENUS.register("case_menu") { MenuType(::CaseMenu, FeatureFlagSet.of() )}

View File

@@ -1,5 +1,6 @@
package org.neoflock.neocomputers.gui.menu;
import net.minecraft.network.FriendlyByteBuf
import net.minecraft.world.SimpleContainer
import net.minecraft.world.entity.player.Inventory
import org.neoflock.neocomputers.gui.menu.Menus;
@@ -7,7 +8,16 @@ 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 net.minecraft.world.level.block.entity.BlockEntity
import org.neoflock.neocomputers.entity.ScreenEntity
import org.neoflock.neocomputers.utils.GenericContainerMenu
class ScreenMenu(i: Int, inv: Inventory) : GenericContainerMenu(Menus.SCREEN_MENU.get(), i, SimpleContainer(0)) {
class ScreenMenu : GenericContainerMenu {
var entity: ScreenEntity? = null
constructor(i: Int, inv: Inventory, buf: FriendlyByteBuf) : this(i, inv, inv.player.level().getBlockEntity(buf.readBlockPos()))
constructor(i: Int, inv: Inventory, entity: BlockEntity?) : super(Menus.SCREEN_MENU.get(), i, SimpleContainer(0)) {
this.entity = entity as ScreenEntity
}
}

View File

@@ -20,14 +20,18 @@ class BufferRenderer(private var width: Int, private var height: Int, private va
private var image: NativeImage = NativeImage(texwidth, texheight, true); // idk what the boolean is
private var tex: DynamicTexture = DynamicTexture(image)
init {
Minecraft.getInstance().textureManager.register(this.id, tex)
}
fun dump(path: String) {
image.writeToFile(File(path))
NeoComputers.LOGGER.info("DUMPED!!!")
}
fun toRGBA(color: Int): Int {
return color.shl(8).or(0xFF)
}
// fun toRGBA(color: Int): Int {
// return color.shl(8).or(0xFF)
// }
fun drawGlyph(x: Int, y: Int, c: Char, fg: Int) {
var glyph: ArrayList<Byte> = FontProvider.map[c]!!
@@ -36,7 +40,7 @@ class BufferRenderer(private var width: Int, private var height: Int, private va
for (i in 0..<CHARW) {
// var pixel = ((glyph[j] and ((1 shl (CHARW - i - 1)).toByte())).toInt()) ushr (CHARW - i - 1) // retardation
var pixel = (glyph[j] and (0b10000000 ushr i).toByte()).toInt()
if (pixel > 0) image.setPixelRGBA(x+i, y+j, toRGBA(fg))
if (pixel > 0) image.setPixelRGBA(x+i, y+j, 0xFF000000.toInt()+fg)
}
}
}
@@ -59,15 +63,11 @@ class BufferRenderer(private var width: Int, private var height: Int, private va
buffer[y*width+x] = c
}
fun register() {
Minecraft.getInstance().textureManager.register(this.id, tex) // also idk how to unregister this
}
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)
data class GPUChar(val c: Char, val fg: Int =0xFFFFFF, val bg: Int = 0) // all is bgr
}

View File

@@ -0,0 +1,51 @@
package org.neoflock.neocomputers.gui.render
import com.mojang.blaze3d.systems.RenderSystem
import com.mojang.blaze3d.vertex.PoseStack
import com.mojang.math.Axis
import net.minecraft.client.renderer.MultiBufferSource
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider
import net.minecraft.core.Direction
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.level.block.state.properties.EnumProperty
import org.neoflock.neocomputers.NeoComputers
import org.neoflock.neocomputers.NeoComputers.BlockEntityRenderType
import org.neoflock.neocomputers.block.ScreenBlock
import org.neoflock.neocomputers.entity.ScreenEntity
class ScreenEntityRenderer(val context: BlockEntityRendererProvider.Context?) : BlockEntityRenderer<ScreenEntity> {
override fun render(entity: ScreenEntity, partialTick: Float, mat: PoseStack, bufferSource: MultiBufferSource, packedLight: Int, packedOverlay: Int) {
mat.pushPose()
handleDirection(entity, mat)
mat.translate(2 / 16f, 2 / 16f, 0.0001f) // am i epstein or am i just retarded
// mat.mulPose(Axis.YP.rotationDegrees(180f))
// handleDirection(entity, mat)
// RenderSystem.setShader(GameRenderer::getPositionTexShader);
RenderSystem.setShaderTexture(0, ResourceLocation.fromNamespaceAndPath(NeoComputers.MODID, entity.bound))
val buffer = bufferSource.getBuffer(BlockEntityRenderType) // idk the correct rendertype for ts
buffer.addVertex(mat.last(), 3 / 4f, 0f, 0f).setUv(1f, 1f)
buffer.addVertex(mat.last(), 3 / 4f, 3 / 4f, 0f).setUv(1f, 0f)
buffer.addVertex(mat.last(), 0f, 3 / 4f, 0f).setUv(0f, 0f)
buffer.addVertex(mat.last(), 0f, 0f, 0f).setUv(0f, 1f)
mat.popPose()
}
private fun handleDirection(ent: ScreenEntity, mat: PoseStack) { // TODO: separate up and down from cardinal directions
when (ent.blockState.getValue(ScreenBlock.FACING)) {
Direction.SOUTH -> { mat.translate(0F, 0F, 1F) }
Direction.EAST -> { mat.mulPose(Axis.YP.rotationDegrees(90F)); mat.translate(-1F, 0F, 1F) }
Direction.WEST -> { mat.mulPose(Axis.YN.rotationDegrees(90F)); }
Direction.NORTH -> {mat.mulPose(Axis.YP.rotationDegrees(180F)); mat.translate(-1F, 0F, 0F) }
Direction.UP -> { mat.mulPose(Axis.XN.rotationDegrees(90F)); mat.mulPose(Axis.ZP.rotationDegrees(180F)); mat.translate(-1.0001F, 0F, 1F) } // idek
Direction.DOWN -> { mat.mulPose(Axis.XP.rotationDegrees(90F)); mat.mulPose(Axis.ZN.rotationDegrees(180F)); mat.translate(-1F, -1F, 0F) }
else -> return
}
}
// private fun handleDirection(ent: ScreenEntity, mat: PoseStack?) {
// `when`(ent.getBlockState().get)
// }
}

View File

@@ -10,6 +10,7 @@ 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.entity.ScreenEntity
import org.neoflock.neocomputers.gui.buffer.BufferRenderer
import org.neoflock.neocomputers.gui.menu.ScreenMenu
import org.neoflock.neocomputers.gui.render.ScreenRenderer
@@ -17,17 +18,9 @@ import org.neoflock.neocomputers.gui.render.ScreenRenderer
class ScreenScreen : AbstractContainerScreen<ScreenMenu>{
private var renderer: ScreenRenderer = ScreenRenderer();
private var bufferRenderer: BufferRenderer? = null;
constructor(abstractContainerMenu: ScreenMenu, inventory: Inventory, component: Component) : super(abstractContainerMenu, inventory, component) {
val buffer: ArrayList<BufferRenderer.GPUChar> = arrayListOf(BufferRenderer.GPUChar('h'), BufferRenderer.GPUChar('a'), BufferRenderer.GPUChar('i'))
for (i in 0..<(400-3)) {
buffer.add(BufferRenderer.GPUChar(' '))
}
bufferRenderer = BufferRenderer(20, 20, ResourceLocation.fromNamespaceAndPath(NeoComputers.MODID, "screen/test"), buffer)
bufferRenderer!!.register()
bufferRenderer!!.drawBuffer()
renderer.bind(ResourceLocation.fromNamespaceAndPath(NeoComputers.MODID, "screen/test"))
var ent: ScreenEntity = abstractContainerMenu.entity!!;
renderer.bind(ResourceLocation.fromNamespaceAndPath(NeoComputers.MODID, ent.bound))
}
override fun renderBg(guiGraphics: GuiGraphics, f: Float, i: Int, j: Int) {}
override fun render(graphics: GuiGraphics, mouseX: Int, mouseY: Int, something: Float) {
@@ -35,8 +28,8 @@ class ScreenScreen : AbstractContainerScreen<ScreenMenu>{
renderer.render(graphics, 50, 50, 100, 200)
}
override fun onClose() {
super.onClose()
bufferRenderer!!.clean()
}
// override fun onClose() {
// super.onClose()
// renderer.
// }
}

View File

@@ -21,6 +21,9 @@
],
"main": [
"org.neoflock.neocomputers.platforms.fabric.NeoComputersFabric"
],
"client": [
"org.neoflock.neocomputers.platforms.fabric.client.NeoComputersFabricClient"
]
},
"mixins": [