Skip to content

Commit dbcdb86

Browse files
committed
Merge remote-tracking branch 'origin/refactor/ui' into refactor/ui
2 parents 9c21ca1 + 113f96a commit dbcdb86

File tree

6 files changed

+98
-67
lines changed

6 files changed

+98
-67
lines changed

common/src/main/java/com/lambda/mixin/render/ChatInputSuggestorMixin.java

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import org.spongepowered.asm.mixin.injection.Redirect;
4141
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
4242

43+
import java.util.Map;
4344
import java.util.concurrent.CompletableFuture;
4445
import java.util.regex.Matcher;
4546
import java.util.regex.Pattern;
@@ -87,10 +88,22 @@ private void refreshEmojiSuggestion(CallbackInfo ci) {
8788
int start = neoLambda$getLastColon(textToCursor);
8889
if (start == -1) return;
8990

90-
String emojiString = typing.substring(start + 1);
91+
Matcher emojiMatcher = EMOJI_PATTERN.matcher(textToCursor);
92+
Map<String, ?> emojiKeys = LambdaAtlas.INSTANCE.getKeys(RenderSettings.INSTANCE.getEmojiFont());
93+
while (emojiMatcher.find()) {
94+
int openingColon = emojiMatcher.start(1);
95+
String key = emojiMatcher.group(2);
96+
int closingColon = emojiMatcher.end(3);
97+
98+
if (emojiKeys.containsKey(key) && start >= openingColon && start < closingColon) {
99+
// If the colon is part of a previous valid emoji, return
100+
return;
101+
}
102+
}
103+
104+
String emojiString = textToCursor.substring(start + 1);
91105

92-
Stream<String> results = LambdaAtlas.INSTANCE.getKeys(RenderSettings.INSTANCE.getEmojiFont())
93-
.keySet().stream()
106+
Stream<String> results = emojiKeys.keySet().stream()
94107
.filter(s -> s.startsWith(emojiString))
95108
.map(s -> s + ":");
96109

@@ -105,6 +118,9 @@ private void refreshEmojiSuggestion(CallbackInfo ci) {
105118
@Unique
106119
private static final Pattern COLON_PATTERN = Pattern.compile("(:[a-zA-Z0-9_]+)");
107120

121+
@Unique
122+
private static final Pattern EMOJI_PATTERN = Pattern.compile("(:)([a-zA-Z0-9_]+)(:)");
123+
108124
@Unique
109125
private int neoLambda$getLastColon(String input) {
110126
if (Strings.isNullOrEmpty(input)) return -1;

common/src/main/kotlin/com/lambda/graphics/buffer/Buffer.kt

Lines changed: 46 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -40,17 +40,17 @@ abstract class Buffer(
4040
/**
4141
* Specifies how the buffers are used
4242
*
43-
* | Buffer Usage | Description |
44-
* |--------------------------------|-----------------------------------------------------------------|
45-
* | GL_STREAM_DRAW | Data is set once and used a few times for drawing. |
46-
* | GL_STREAM_READ | Data is set once and used a few times for reading. |
47-
* | GL_STREAM_COPY | Data is set once and used a few times for copying. |
48-
* | GL_STATIC_DRAW | Data is set once and used many times for drawing. |
49-
* | GL_STATIC_READ | Data is set once and used many times for reading. |
50-
* | GL_STATIC_COPY | Data is set once and used many times for copying. |
51-
* | GL_DYNAMIC_DRAW | Data is modified repeatedly and used many times for drawing. |
52-
* | GL_DYNAMIC_READ | Data is modified repeatedly and used many times for reading. |
53-
* | GL_DYNAMIC_COPY | Data is modified repeatedly and used many times for copying. |
43+
* | Buffer Usage | Description |
44+
* |----------------------------------|-----------------------------------------------------------------|
45+
* | [GL_STREAM_DRAW] | Data is set once and used a few times for drawing. |
46+
* | [GL_STREAM_READ] | Data is set once and used a few times for reading. |
47+
* | [GL_STREAM_COPY] | Data is set once and used a few times for copying. |
48+
* | [GL_STATIC_DRAW] | Data is set once and used many times for drawing. |
49+
* | [GL_STATIC_READ] | Data is set once and used many times for reading. |
50+
* | [GL_STATIC_COPY] | Data is set once and used many times for copying. |
51+
* | [GL_DYNAMIC_DRAW] | Data is modified repeatedly and used many times for drawing. |
52+
* | [GL_DYNAMIC_READ] | Data is modified repeatedly and used many times for reading. |
53+
* | [GL_DYNAMIC_COPY] | Data is modified repeatedly and used many times for copying. |
5454
*
5555
* @see <a href="https://www.khronos.org/opengl/wiki/Buffer_Object">Buffer object</a>
5656
*/
@@ -60,22 +60,22 @@ abstract class Buffer(
6060
* Specifies the target to which the buffer object is bound which must be one
6161
* of the following:
6262
*
63-
* | Buffer Binding Target | Purpose |
64-
* |-------------------------------|--------------------------------------|
65-
* | GL_ARRAY_BUFFER | Vertex attributes |
66-
* | GL_ATOMIC_COUNTER_BUFFER | Atomic counter storage |
67-
* | GL_COPY_READ_BUFFER | Buffer copy source |
68-
* | GL_COPY_WRITE_BUFFER | Buffer copy destination |
69-
* | GL_DISPATCH_INDIRECT_BUFFER | Indirect compute dispatch commands |
70-
* | GL_DRAW_INDIRECT_BUFFER | Indirect command arguments |
71-
* | GL_ELEMENT_ARRAY_BUFFER | Vertex array indices |
72-
* | GL_PIXEL_PACK_BUFFER | Pixel read target |
73-
* | GL_PIXEL_UNPACK_BUFFER | Texture data source |
74-
* | GL_QUERY_BUFFER | Query result buffer |
75-
* | GL_SHADER_STORAGE_BUFFER | Read-write storage for shaders |
76-
* | GL_TEXTURE_BUFFER | Texture data buffer |
77-
* | GL_TRANSFORM_FEEDBACK_BUFFER | Transform feedback buffer |
78-
* | GL_UNIFORM_BUFFER | Uniform block storage |
63+
* | Buffer Binding Target | Purpose |
64+
* |---------------------------------|--------------------------------------|
65+
* | [GL_ARRAY_BUFFER] | Vertex attributes |
66+
* | [GL_ATOMIC_COUNTER_BUFFER] | Atomic counter storage |
67+
* | [GL_COPY_READ_BUFFER] | Buffer copy source |
68+
* | [GL_COPY_WRITE_BUFFER] | Buffer copy destination |
69+
* | [GL_DISPATCH_INDIRECT_BUFFER] | Indirect compute dispatch commands |
70+
* | [GL_DRAW_INDIRECT_BUFFER] | Indirect command arguments |
71+
* | [GL_ELEMENT_ARRAY_BUFFER] | Vertex array indices |
72+
* | [GL_PIXEL_PACK_BUFFER] | Pixel read target |
73+
* | [GL_PIXEL_UNPACK_BUFFER] | Texture data source |
74+
* | [GL_QUERY_BUFFER] | Query result buffer |
75+
* | [GL_SHADER_STORAGE_BUFFER] | Read-write storage for shaders |
76+
* | [GL_TEXTURE_BUFFER] | Texture data buffer |
77+
* | [GL_TRANSFORM_FEEDBACK_BUFFER] | Transform feedback buffer |
78+
* | [GL_UNIFORM_BUFFER] | Uniform block storage |
7979
*
8080
* @see <a href="https://www.khronos.org/opengl/wiki/Buffer_Object">Buffer object</a>
8181
*/
@@ -85,16 +85,18 @@ abstract class Buffer(
8585
* Specifies a combination of access flags indicating the desired
8686
* access to the mapping range and must contain one or more of the following:
8787
*
88-
* | Flag | Description | Disclaimer |
89-
* |-------------------------------|-----------------------------------------------------|---------------------------------------------------------------|
90-
* | GL_MAP_READ_BIT | Allows reading buffer data. | Undefined if used without this flag. |
91-
* | GL_MAP_WRITE_BIT | Allows modifying buffer data. | Undefined if used without this flag. |
92-
* | GL_MAP_PERSISTENT_BIT | Enables persistent mapping during GL operations. | Requires proper allocation with GL_MAP_PERSISTENT_BIT. |
93-
* | GL_MAP_COHERENT_BIT | Ensures changes are visible without extra steps. | Without this, explicit sync is needed. |
94-
* | GL_MAP_INVALIDATE_RANGE_BIT | Discards previous contents of the mapped range. | Cannot be used with GL_MAP_READ_BIT. |
95-
* | GL_MAP_INVALIDATE_BUFFER_BIT | Discards previous contents of the entire buffer. | Cannot be used with GL_MAP_READ_BIT. |
96-
* | GL_MAP_FLUSH_EXPLICIT_BIT | Requires explicit flushing of modified sub-ranges. | Only with GL_MAP_WRITE_BIT. Data may be undefined if skipped. |
97-
* | GL_MAP_UNSYNCHRONIZED_BIT | Skips synchronization before mapping. | May cause data corruption if regions overlap. |
88+
* | Flag | Description | Information |
89+
* |--------------------------------|-----------------------------------------------------|-------------------------------------------------------------------------------------------|
90+
* | [GL_MAP_READ_BIT] | Allows reading buffer data. | Buffer must be created with this flag. Undefined if not included in access. |
91+
* | [GL_MAP_WRITE_BIT] | Allows modifying buffer data. | Buffer must be created with this flag. Undefined if not included in access. |
92+
* | [GL_MAP_PERSISTENT_BIT] | Enables persistent mapping during GL operations. | Requires buffer to be created with [GL_MAP_PERSISTENT_BIT]. |
93+
* | [GL_MAP_COHERENT_BIT] | Ensures changes are visible to the GPU. | Requires buffer creation with [GL_MAP_PERSISTENT_BIT] or explicit sync. |
94+
* | [GL_MAP_INVALIDATE_RANGE_BIT] | Discards previous contents of the mapped range. | Cannot be used with [GL_MAP_READ_BIT]. |
95+
* | [GL_MAP_INVALIDATE_BUFFER_BIT] | Discards previous contents of the entire buffer. | Cannot be used with [GL_MAP_READ_BIT]. |
96+
* | [GL_MAP_FLUSH_EXPLICIT_BIT] | Requires explicit flushing of modified sub-ranges. | Only valid with [GL_MAP_WRITE_BIT]. Data may be undefined if flushing is skipped. |
97+
* | [GL_MAP_UNSYNCHRONIZED_BIT] | Skips synchronization before mapping. | May cause data corruption if buffer is accessed concurrently. |
98+
* | [GL_DYNAMIC_STORAGE_BIT] | Allows updates via [glBufferSubData]. | If omitted, [glBufferSubData] will fail. |
99+
* | [GL_CLIENT_STORAGE_BIT] | Hints that the buffer should prefer client storage. | Implementation-dependent optimization. |
98100
*
99101
* @see <a href="https://www.khronos.org/opengl/wiki/Buffer_Object">Buffer object</a>
100102
*/
@@ -257,8 +259,6 @@ abstract class Buffer(
257259
/**
258260
* Maps a specified region of the buffer's data store into client memory, processes it using the provided lambda, and then unmaps the buffer.
259261
*
260-
* This function does not handle the binding.
261-
*
262262
* If [access] contains the `GL_MAP_PERSISTENT_BIT` flag, the buffer will not be unmapped.
263263
*
264264
* @param size Specifies the length of the range to be mapped.
@@ -269,26 +269,25 @@ abstract class Buffer(
269269
*/
270270
open fun map(size: Long, offset: Long, block: (ByteBuffer) -> Unit = {}): ByteBuffer {
271271
validate()
272+
bind()
272273

273274
check(offset >= 0 || size >= 0)
274275
{ "Invalid offset or size parameter offset: $offset size: $size." }
275276

276277
check(offset + size <= glGetBufferParameteri(target, GL_BUFFER_SIZE))
277278
{ "Out of bound (is the buffer initialized?) $size + $offset > ${glGetBufferParameteri(target, GL_BUFFER_SIZE)}." }
278279

279-
check(glGetInteger(bindingCheckMappings.getValue(target)) == GL_TRUE)
280-
{ "Target is zero bound." }
281-
282280
check(glGetBufferParameteri(target, GL_BUFFER_MAPPED) == GL_FALSE)
283281
{ "Buffer is already mapped." }
284282

285-
check(access and GL_MAP_WRITE_BIT != 0 && access and GL_MAP_READ_BIT != 0)
283+
check(access and GL_MAP_WRITE_BIT != 0 || access and GL_MAP_READ_BIT != 0)
286284
{ "Neither GL_MAP_READ_BIT nor GL_MAP_WRITE_BIT is set." }
287285

288-
check(access and GL_MAP_READ_BIT != 0 &&
286+
check((access and GL_MAP_READ_BIT != 0 &&
289287
(access and GL_MAP_INVALIDATE_RANGE_BIT != 0 ||
290288
access and GL_MAP_INVALIDATE_BUFFER_BIT != 0 ||
291-
access and GL_MAP_UNSYNCHRONIZED_BIT != 0)
289+
access and GL_MAP_UNSYNCHRONIZED_BIT != 0)) ||
290+
access and GL_MAP_WRITE_BIT != 0
292291
)
293292
{ "GL_MAP_READ_BIT is set and any of GL_MAP_INVALIDATE_RANGE_BIT, GL_MAP_INVALIDATE_BUFFER_BIT or GL_MAP_UNSYNCHRONIZED_BIT is set." }
294293

@@ -302,6 +301,8 @@ abstract class Buffer(
302301
throw IllegalStateException("An unknown error occurred due to GPU memory availability of buffer corruption.")
303302
}
304303

304+
bind(0)
305+
305306
return sharedRegion
306307
}
307308

common/src/main/kotlin/com/lambda/graphics/buffer/pixel/PixelBuffer.kt

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ package com.lambda.graphics.buffer.pixel
2020
import com.lambda.graphics.buffer.Buffer
2121
import com.lambda.graphics.gl.putTo
2222
import com.lambda.graphics.texture.Texture
23+
import com.lambda.threading.runSafeGameScheduled
2324
import com.lambda.util.math.MathUtils.toInt
2425
import org.lwjgl.opengl.GL45C.*
2526
import java.nio.ByteBuffer
@@ -31,25 +32,38 @@ import java.nio.ByteBuffer
3132
* Functions that perform an upload operation, a pixel unpack, will use the buffer object bound to the target GL_PIXEL_UNPACK_BUFFER.
3233
* If a buffer is bound, then the pointer value that those functions take is not a pointer, but an offset from the beginning of that buffer.
3334
*
35+
* Asynchronous should only be used for medium-size blocks of data being updated one time or less per frame
36+
* Persistent should only be used for streaming operations with large blocks of data updated once or more per frame
37+
*
3438
* @property texture The [Texture] instance to use
3539
* @property asynchronous Whether to use 2 buffers or not
36-
* @property bufferMapping Whether to map a block in memory to upload or not
40+
* @property persistent Whether to map a block in memory to upload or not
3741
*
38-
* @see <a href="https://www.khronos.org/opengl/wiki/Pixel_Buffer_Object">Reference</a>
42+
* @see <a href="https://www.khronos.org/opengl/wiki/Pixel_Buffer_Object">Pixel buffer object</a>
3943
*/
4044
class PixelBuffer(
4145
private val texture: Texture,
4246
private val asynchronous: Boolean = false,
43-
private val bufferMapping: Boolean = false,
47+
private val persistent: Boolean = false,
4448
) : Buffer(buffers = asynchronous.toInt() + 1) {
4549
override val usage = GL_STATIC_DRAW
4650
override val target = GL_PIXEL_UNPACK_BUFFER
47-
override val access = GL_MAP_WRITE_BIT or GL_DYNAMIC_STORAGE_BIT or GL_MAP_PERSISTENT_BIT
51+
override val access =
52+
if (persistent) GL_MAP_WRITE_BIT or GL_DYNAMIC_STORAGE_BIT or GL_MAP_PERSISTENT_BIT or GL_MAP_COHERENT_BIT
53+
else GL_MAP_WRITE_BIT or GL_DYNAMIC_STORAGE_BIT
4854

4955
private val channels = channelMapping[texture.format] ?: throw IllegalArgumentException("Invalid image format, expected OpenGL format, got ${texture.format} instead")
5056
private val size = texture.width * texture.height * channels * 1L
57+
// private var sharedRegion: ByteBuffer? = null
5158

5259
override fun upload(data: ByteBuffer, offset: Long) {
60+
if (!asynchronous) {
61+
glBindTexture(GL_TEXTURE_2D, texture.id)
62+
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texture.width, texture.height, texture.format, GL_UNSIGNED_BYTE, data)
63+
glBindTexture(GL_TEXTURE_2D, 0)
64+
return
65+
}
66+
5367
bind()
5468
glBindTexture(GL_TEXTURE_2D, texture.id)
5569

@@ -69,8 +83,9 @@ class PixelBuffer(
6983
swap()
7084
bind()
7185

72-
if (bufferMapping) map(size, offset, data::putTo)
73-
else update(data, offset)
86+
// if (persistent) data.putTo(sharedRegion)
87+
// else update(data, offset)
88+
update(data, offset)
7489

7590
bind(0)
7691
}
@@ -87,6 +102,10 @@ class PixelBuffer(
87102
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
88103

89104
storage(size)
105+
106+
// bind()
107+
// sharedRegion = if (persistent) map(size, 0) else null
108+
// bind(0)
90109
}
91110

92111
companion object {

common/src/main/kotlin/com/lambda/graphics/gl/Memory.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,4 @@ val Long.kibibyte get() = this * 1024
3535
val Long.mebibyte get() = this * 1024 * 1024
3636
val Long.gibibyte get() = this * 1024 * 1024 * 1024
3737

38-
fun ByteBuffer.putTo(dst: ByteBuffer) { dst.put(this) }
38+
fun ByteBuffer.putTo(dst: ByteBuffer?) { dst?.put(this) }

common/src/main/kotlin/com/lambda/module/HudModule.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ abstract class HudModule(
115115

116116
listen<RenderEvent.GUI.HUD> {
117117
while (scheduled.isNotEmpty()) {
118-
scheduled.removeFirst().invoke()
118+
scheduled.removeAt(0).invoke()
119119
}
120120

121121
base.onEvent(GuiEvent.Update)

common/src/main/kotlin/com/lambda/module/modules/client/LambdaMoji.kt

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,8 @@ object LambdaMoji : Module(
3737
defaultTags = setOf(ModuleTag.CLIENT, ModuleTag.RENDER),
3838
enabledByDefault = true,
3939
) {
40-
val scale by setting("Emoji Scale", 1.0, 0.5..1.5, 0.1)
4140
val suggestions by setting("Chat Suggestions", true)
4241

43-
private val emojiWhitespace: String
44-
get() = " ".repeat(((mc.textRenderer.fontHeight / 2 / mc.textRenderer.getWidth(" ")) * scale).toInt())
45-
4642
private val renderQueue = mutableListOf<Triple<GlyphInfo, Vec2d, Color>>()
4743

4844
init {
@@ -73,7 +69,6 @@ object LambdaMoji : Module(
7369
val index = raw.indexOf(emoji)
7470
if (index == -1) return@forEach
7571

76-
val height = mc.textRenderer.fontHeight
7772
val width = mc.textRenderer.getWidth(raw.substring(0, index))
7873

7974
// Dude I'm sick of working with the shitcode that is minecraft's codebase :sob:
@@ -82,19 +77,19 @@ object LambdaMoji : Module(
8277
else -> Color(255, 255, 255, (color shr 24 and 0xFF))
8378
}
8479

85-
val glyph = RenderSettings.emojiFont[emoji]!!
86-
renderQueue.add(Triple(glyph, Vec2d(x + width, y + height / 2), trueColor))
80+
val glyph = RenderSettings.emojiFont[emoji] ?: return@forEach
81+
renderQueue.add(Triple(glyph, Vec2d(x + width, y), trueColor))
8782

8883
// Replace the emoji with whitespaces depending on the player's settings
89-
raw = raw.replaceFirst(emoji, emojiWhitespace)
84+
raw = raw.replaceFirst(emoji, " ")
9085
}
9186

9287
val constructed = mutableListOf<OrderedText>()
9388

9489
// Will not work properly if the emoji is part of the style
95-
saved.forEach { (charIndex: Int, style: Style) ->
96-
if (charIndex >= raw.length) return@forEach
97-
constructed.add(OrderedText.styledForwardsVisitedString(raw.substring(charIndex, charIndex + 1), style))
90+
saved.forEach { (index, style) ->
91+
if (index >= raw.length) return@forEach
92+
constructed.add(OrderedText.styledForwardsVisitedString(raw.substring(index, index + 1), style))
9893
}
9994

10095
return OrderedText.concat(constructed)

0 commit comments

Comments
 (0)