Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 11 additions & 11 deletions src/main/kotlin/com/lambda/event/events/RenderEvent.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,22 @@

package com.lambda.event.events

import com.lambda.context.SafeContext
import com.lambda.event.Event
import com.lambda.event.callback.Cancellable
import com.lambda.event.callback.ICancellable
import com.lambda.graphics.renderer.esp.global.DynamicESP
import com.lambda.graphics.renderer.esp.global.StaticESP
import com.lambda.event.listener.SafeListener.Companion.listen
import com.lambda.graphics.renderer.esp.ShapeBuilder
import com.lambda.graphics.renderer.esp.Treed

sealed class RenderEvent {
class World : Event

class StaticESP : Event {
val renderer = StaticESP
}
fun Any.onStaticRender(block: SafeContext.(ShapeBuilder) -> Unit) =
listen<RenderEvent.Upload> { block(ShapeBuilder(Treed.Static.faceBuilder, Treed.Static.edgeBuilder)) }
fun Any.onDynamicRender(block: SafeContext.(ShapeBuilder) -> Unit) =
listen<RenderEvent.Upload> { block(ShapeBuilder(Treed.Dynamic.faceBuilder, Treed.Dynamic.edgeBuilder)) }

class DynamicESP : Event {
val renderer = DynamicESP
}
sealed class RenderEvent {
object Upload : Event
object Render : Event

class UpdateTarget : ICancellable by Cancellable()
}
22 changes: 11 additions & 11 deletions src/main/kotlin/com/lambda/graphics/RenderMain.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@ import com.lambda.event.listener.SafeListener.Companion.listen
import com.lambda.graphics.gl.GlStateUtils.setupGL
import com.lambda.graphics.gl.Matrices
import com.lambda.graphics.gl.Matrices.resetMatrices
import com.lambda.graphics.renderer.esp.global.DynamicESP
import com.lambda.graphics.renderer.esp.global.StaticESP
import com.lambda.graphics.renderer.esp.Treed
import com.lambda.util.math.Vec2d
import com.mojang.blaze3d.opengl.GlStateManager
import com.mojang.blaze3d.systems.RenderSystem
Expand Down Expand Up @@ -56,21 +55,22 @@ object RenderMain {

GlStateManager._glBindFramebuffer(GL_FRAMEBUFFER, prevFramebuffer)

RenderEvent.World().post()
StaticESP.render()
DynamicESP.render()
Treed.Static.render()
Treed.Dynamic.render()

RenderEvent.Render.post()
}
}

init {
listen<TickEvent.Post> {
StaticESP.clear()
RenderEvent.StaticESP().post()
StaticESP.upload()
Treed.Static.clear()
Treed.Dynamic.clear()

RenderEvent.Upload.post()

DynamicESP.clear()
RenderEvent.DynamicESP().post()
DynamicESP.upload()
Treed.Static.upload()
Treed.Dynamic.upload()
}
}
}
11 changes: 9 additions & 2 deletions src/main/kotlin/com/lambda/graphics/buffer/DynamicByteBuffer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,8 @@ class DynamicByteBuffer private constructor(initialCapacity: Int) {
val offset = position - pointer

memCopy(pointer, newPointer, offset)
data = newBuffer

data = newBuffer
pointer = newPointer
position = newPointer + offset
capacity = newCapacity
Expand All @@ -176,6 +176,13 @@ class DynamicByteBuffer private constructor(initialCapacity: Int) {
capacity = newCapacity
}

/**
* Returns the relative index of the first mismatch between this and the given buffer, otherwise -1 if no mismatch.
*
* @see [ByteBuffer.mismatch]
*/
fun mismatch(other: DynamicByteBuffer) = data.mismatch(other.data)

companion object {
/**
* Creates a new DynamicByteBuffer with specified initial capacity
Expand All @@ -184,4 +191,4 @@ class DynamicByteBuffer private constructor(initialCapacity: Int) {
fun dynamicByteBuffer(initialCapacity: Int) =
DynamicByteBuffer(initialCapacity)
}
}
}
30 changes: 1 addition & 29 deletions src/main/kotlin/com/lambda/graphics/pipeline/PersistentBuffer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,8 @@
package com.lambda.graphics.pipeline

import com.lambda.graphics.buffer.Buffer.Companion.createPipelineBuffer
import com.lambda.graphics.buffer.DynamicByteBuffer
import com.lambda.graphics.buffer.DynamicByteBuffer.Companion.dynamicByteBuffer
import com.lambda.graphics.gl.kibibyte
import org.lwjgl.system.MemoryUtil
import org.lwjgl.system.MemoryUtil.memCopy

/**
Expand Down Expand Up @@ -64,7 +62,7 @@ class PersistentBuffer(
}

if (snapshotData > 0 && snapshot.capacity >= byteBuffer.bytesPut) {
if (memcmp(snapshot, byteBuffer, uploadOffset, dataCount)) return
if (snapshot.mismatch(byteBuffer) >= 0) return
}

glBuffer.update(uploadOffset, dataCount, dataStart)
Expand All @@ -90,30 +88,4 @@ class PersistentBuffer(
}

fun use(block: () -> Unit) = glBuffer.bind { block() }

private fun memcmp(a: DynamicByteBuffer, b: DynamicByteBuffer, position: Long, size: Long): Boolean {
if (a.capacity != b.capacity) return false

val end = position + size
var head = position

// Process the aligned bytes in chunks of 8 until we've reached the end
while (head + 8 <= end) {
val first = MemoryUtil.memGetLong(a.pointer + head)
val second = MemoryUtil.memGetLong(b.pointer + head)
if (first != second) return false

head += 8
}

while (head < end) {
val first = MemoryUtil.memGetByte(a.pointer + head)
val second = MemoryUtil.memGetByte(b.pointer + head)
if (first != second) return false

head++
}

return true
}
}
7 changes: 2 additions & 5 deletions src/main/kotlin/com/lambda/graphics/pipeline/VertexBuilder.kt
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ import org.joml.Vector4d
class VertexBuilder(
private val direct: VertexPipeline? = null
) {
val vertices by lazy { mutableListOf<Attribute>() }
val indices by lazy { mutableListOf<Int>() }
val vertices by lazy(LazyThreadSafetyMode.PUBLICATION) { mutableListOf<Attribute>() }
val indices by lazy(LazyThreadSafetyMode.PUBLICATION) { mutableListOf<Int>() }

private var verticesCounter = 0

Expand Down Expand Up @@ -115,9 +115,6 @@ class VertexBuilder(
fun collect(vararg indices: Int) =
indices

fun use(block: VertexBuilder.() -> Unit) =
apply(block)

/**
* Creates a new vertex with specified attributes
* @param block Configuration lambda for defining vertex attributes
Expand Down
89 changes: 30 additions & 59 deletions src/main/kotlin/com/lambda/graphics/renderer/esp/ChunkedESP.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,13 @@ package com.lambda.graphics.renderer.esp
import com.lambda.event.events.RenderEvent
import com.lambda.event.events.TickEvent
import com.lambda.event.events.WorldEvent
import com.lambda.event.events.onStaticRender
import com.lambda.event.listener.SafeListener.Companion.listen
import com.lambda.event.listener.SafeListener.Companion.listenConcurrently
import com.lambda.graphics.renderer.esp.impl.StaticESPRenderer
import com.lambda.module.modules.client.StyleEditor
import com.lambda.threading.awaitMainThread
import com.lambda.util.world.FastVector
import com.lambda.util.world.fastVectorOf
import net.minecraft.util.math.ChunkPos
import net.minecraft.world.World
import net.minecraft.world.chunk.WorldChunk
Expand All @@ -33,13 +35,11 @@ import java.util.concurrent.ConcurrentLinkedDeque

class ChunkedESP private constructor(
owner: Any,
private val update: StaticESPRenderer.(World, Int, Int, Int) -> Unit
private val update: ShapeBuilder.(World, FastVector) -> Unit
) {
private val rendererMap = ConcurrentHashMap<Long, EspChunk>()
private val WorldChunk.renderer
get() = rendererMap.getOrPut(pos.toLong()) {
EspChunk(this, this@ChunkedESP)
}
get() = rendererMap.getOrPut(pos.toLong()) { EspChunk(this, this@ChunkedESP) }

private val uploadQueue = ConcurrentLinkedDeque<() -> Unit>()
private val rebuildQueue = ConcurrentLinkedDeque<EspChunk>()
Expand All @@ -52,92 +52,63 @@ class ChunkedESP private constructor(
}

init {
listenConcurrently<WorldEvent.BlockUpdate.Client> { event ->
world.getWorldChunk(event.pos).renderer.notifyChunks()
}
//listen<WorldEvent.BlockUpdate.Client> { rebuildQueue.add(rendererMap[ChunkPos.toLong(it.pos)] ?: return@listen) }
listen<WorldEvent.ChunkEvent.Load> { it.chunk.renderer.notifyChunks() }
listen<WorldEvent.ChunkEvent.Unload> { rendererMap.remove(it.chunk.pos.toLong())?.notifyChunks() }

listenConcurrently<WorldEvent.ChunkEvent.Load> { event ->
event.chunk.renderer.notifyChunks()
}

listenConcurrently<WorldEvent.ChunkEvent.Unload> { event ->
rendererMap.remove(event.chunk.pos.toLong())?.notifyChunks()
}

owner.listenConcurrently<TickEvent.Pre> {
listenConcurrently<TickEvent.Post> {
if (++ticks % StyleEditor.updateFrequency == 0) {
val polls = minOf(StyleEditor.rebuildsPerTick, rebuildQueue.size)

repeat(polls) {
rebuildQueue.poll()?.rebuild()
}
repeat(polls) { rebuildQueue.poll()?.rebuild() }

ticks = 0
}
}

owner.listen<TickEvent.Pre> {
if (uploadQueue.isEmpty()) return@listen
owner.onStaticRender {
if (uploadQueue.isEmpty()) return@onStaticRender

val polls = minOf(StyleEditor.uploadsPerTick, uploadQueue.size)

repeat(polls) {
uploadQueue.poll()?.invoke()
}
repeat(polls) { uploadQueue.poll()?.invoke() }
}

owner.listen<RenderEvent.World> {
rendererMap.values.forEach {
it.renderer?.render()
}
}
owner.listen<RenderEvent.Render> { rendererMap.values.forEach { it.renderer.render() } }
}

companion object {
fun Any.newChunkedESP(
update: StaticESPRenderer.(World, Int, Int, Int) -> Unit
) = ChunkedESP(this, update)
update: ShapeBuilder.(World, FastVector) -> Unit
) = ChunkedESP(this@newChunkedESP, update)
}

private class EspChunk(val chunk: WorldChunk, val owner: ChunkedESP) {
var renderer: StaticESPRenderer? = null

private val chunkOffsets = listOf(1 to 0, 0 to 1, -1 to 0, 0 to -1)
var renderer = Treed(static = true)
private val builder: ShapeBuilder
get() = ShapeBuilder(renderer.faceBuilder, renderer.edgeBuilder)

val neighbors = chunkOffsets.map {
ChunkPos(chunk.pos.x + it.first, chunk.pos.z + it.second)
}.toTypedArray()
val neighbors = listOf(1 to 0, 0 to 1, -1 to 0, 0 to -1)
.map { ChunkPos(chunk.pos.x + it.first, chunk.pos.z + it.second) }

fun notifyChunks() {
neighbors.forEach {
owner.rendererMap[it.toLong()]?.let {
owner.rebuildQueue.apply {
if (!contains(it)) add(it)
}
if (!owner.rebuildQueue.contains(it))
owner.rebuildQueue.add(it)
}
}
}

suspend fun rebuild() {
val newRenderer = awaitMainThread { StaticESPRenderer() }
renderer = awaitMainThread { Treed(static = true) }

iterateChunk { x, y, z ->
owner.update(newRenderer, chunk.world, x, y, z)
}
for (x in chunk.pos.startX..chunk.pos.endX)
for (z in chunk.pos.startZ..chunk.pos.endZ)
for (y in chunk.bottomY..chunk.height)
owner.update(builder, chunk.world, fastVectorOf(x, y, z))

owner.uploadQueue.add {
newRenderer.upload()
renderer = newRenderer
}
}

private fun iterateChunk(block: (Int, Int, Int) -> Unit) = chunk.apply {
for (x in pos.startX..pos.endX) {
for (z in pos.startZ..pos.endZ) {
for (y in bottomY..height) {
block(x, y, z)
}
}
}
owner.uploadQueue.add { renderer.upload() }
}
}
}
12 changes: 2 additions & 10 deletions src/main/kotlin/com/lambda/graphics/renderer/esp/DynamicAABB.kt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ class DynamicAABB {
private var prev: Box? = null
private var curr: Box? = null

val pair get() = prev?.let { prev -> curr?.let { curr -> prev to curr } }

fun update(box: Box): DynamicAABB {
prev = curr ?: box
curr = box
Expand All @@ -38,16 +40,6 @@ class DynamicAABB {
curr = null
}

fun getBoxPair(): Pair<Box, Box>? {
prev?.let { previous ->
curr?.let { current ->
return previous to current
}
}

return null
}

companion object {
val Entity.dynamicBox
get() = DynamicAABB().apply {
Expand Down
Loading