Skip to content
This repository has been archived by the owner on Sep 2, 2024. It is now read-only.

Commit

Permalink
mixin cleanup, improve message stacking performance
Browse files Browse the repository at this point in the history
  • Loading branch information
homchom committed Dec 25, 2023
1 parent df10182 commit 4b1c23d
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 87 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,30 +8,19 @@ import io.github.homchom.recode.ui.text.literalText
import io.github.homchom.recode.ui.text.style
import io.github.homchom.recode.ui.text.toVanilla
import io.github.homchom.recode.ui.text.translatedText
import io.github.homchom.recode.util.regex.regex
import net.minecraft.client.GuiMessageTag

private val stackTagPrefix get() = "$MOD_NAME stacked x"
object MessageStacks {
private const val STACK_TAG_PREFIX = "$MOD_NAME stacked x"

private val stackRegex = regex {
str(stackTagPrefix)
val amount by digit.oneOrMore()
}

fun stackedMessageTag(amount: Int) = GuiMessageTag(
ColorPalette.AQUA.hex,
GuiMessageTag.Icon.CHAT_MODIFIED,
translatedText(
"chat.tag.recode.stacked",
style().aqua(),
arrayOf(literalText(amount))
).toVanilla(),
"$stackTagPrefix$amount"
)

val GuiMessageTag.stackAmount: Int
get() {
val description = logTag ?: return 1
val match = stackRegex.find(description) ?: return 1
return match.groupValues[1].toInt()
}
fun tag(amount: Int) = GuiMessageTag(
ColorPalette.AQUA.hex,
GuiMessageTag.Icon.CHAT_MODIFIED,
translatedText(
"chat.tag.recode.stacked",
style().aqua(),
arrayOf(literalText(amount))
).toVanilla(),
"$STACK_TAG_PREFIX$amount"
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ import io.github.homchom.recode.id
import io.github.homchom.recode.render.IntegralColor
import io.github.homchom.recode.render.toColor
import io.github.homchom.recode.ui.text.VanillaComponent
import io.github.homchom.recode.ui.text.VanillaStyle
import net.fabricmc.fabric.api.resource.ResourceManagerHelper
import net.fabricmc.fabric.api.resource.ResourcePackActivationType
import net.minecraft.network.chat.Style

val FBuiltInResourcePacks = feature("Built-in Resource Packs") {
registerBuiltInResourcePack("better_unicode", 0x6770ff.toColor())
Expand All @@ -23,7 +23,7 @@ private fun registerBuiltInResourcePack(
// https://github.com/KyoriPowered/adventure-platform-fabric/issues/122
val packDescription = VanillaComponent.literal("[$MOD_ID] ")
.append(VanillaComponent.translatable("resourcePack.recode.$id")
.withStyle(Style.EMPTY.withColor(displayColor.toInt()))
.withStyle(VanillaStyle.EMPTY.withColor(displayColor.toInt()))
)

ResourceManagerHelper.registerBuiltinResourcePack(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import me.jellysquid.mods.sodium.client.render.SodiumWorldRenderer;
import me.jellysquid.mods.sodium.client.render.chunk.RenderSection;
import net.minecraft.client.Minecraft;
import net.minecraft.core.SectionPos;
import net.minecraft.world.level.block.entity.BlockEntity;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin;
Expand All @@ -33,9 +32,8 @@ public abstract class MSodiumWorldRenderer {
if (blockEntities == null || blockEntities.length == 0) return blockEntities;

var blockEntityList = List.of(blockEntities);
var chunkPos = SectionPos.of(blockEntityList.get(0).getBlockPos());
var levelRenderer = (DRecodeLevelRenderer) Minecraft.getInstance().levelRenderer;
return levelRenderer.recode$runBlockEntityEvents(blockEntityList, chunkPos)
return levelRenderer.recode$runBlockEntityEvents(blockEntityList, section.getPosition())
.toArray(new BlockEntity[0]);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
package io.github.homchom.recode.mixin.render;

import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import io.github.homchom.recode.event.SimpleValidated;
import io.github.homchom.recode.render.BlockEntityOutlineContext;
import io.github.homchom.recode.render.RGBAColor;
import io.github.homchom.recode.render.DRecodeLevelRenderer;
import io.github.homchom.recode.render.RGBAColor;
import io.github.homchom.recode.render.RenderEvents;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.LevelRenderer;
import net.minecraft.client.renderer.PostChain;
import net.minecraft.client.renderer.chunk.SectionRenderDispatcher;
import net.minecraft.core.BlockPos;
import net.minecraft.core.SectionPos;
import net.minecraft.world.level.block.entity.BlockEntity;
Expand Down Expand Up @@ -50,14 +50,10 @@ private Set<BlockEntity> interceptGlobalBlockEntities(
return Set.copyOf(recode$runBlockEntityEvents(blockEntities, null));
}

@WrapOperation(method = "renderLevel", at = @At(value = "INVOKE",
@ModifyExpressionValue(method = "renderLevel", at = @At(value = "INVOKE",
target = "Lnet/minecraft/client/renderer/chunk/SectionRenderDispatcher$CompiledSection;getRenderableBlockEntities()Ljava/util/List;"
))
private List<BlockEntity> interceptSectionBlockEntities(
SectionRenderDispatcher.CompiledSection section,
Operation<List<BlockEntity>> operation
) {
var blockEntities = operation.call(section);
private List<BlockEntity> interceptSectionBlockEntities(List<BlockEntity> blockEntities) {
if (blockEntities.isEmpty()) return blockEntities;

var chunkPos = SectionPos.of(blockEntities.get(0).getBlockPos());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package io.github.homchom.recode.mixin.render.chat;

import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import com.llamalad7.mixinextras.sugar.Share;
import com.llamalad7.mixinextras.sugar.ref.LocalBooleanRef;
import io.github.homchom.recode.feature.social.DGuiWithSideChat;
import io.github.homchom.recode.feature.social.MessageStacking;
import io.github.homchom.recode.feature.social.MessageStacks;
import io.github.homchom.recode.feature.social.SideChat;
import io.github.homchom.recode.mod.config.Config;
import io.github.homchom.recode.ui.ChatUI;
Expand All @@ -12,9 +13,9 @@
import net.minecraft.client.GuiMessageTag;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.components.ChatComponent;
import net.minecraft.client.multiplayer.chat.ChatListener;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.MessageSignature;
import net.minecraft.util.FormattedCharSequence;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
Expand All @@ -25,8 +26,8 @@
import org.spongepowered.asm.mixin.injection.ModifyVariable;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;

import java.util.Collections;
import java.util.List;
import java.util.Objects;

@Mixin(ChatComponent.class)
public abstract class MChatComponent {
Expand All @@ -44,11 +45,11 @@ private double overrideScreenToChatX(double screenX) {
// side chat redirects

// TODO: improve handling of chat queue (partition it?)
@WrapOperation(method = "render", at = @At(value = "INVOKE",
@ModifyExpressionValue(method = "render", at = @At(value = "INVOKE",
target = "Lnet/minecraft/client/multiplayer/chat/ChatListener;queueSize()J"
))
private long wrapMessageQueueSize(ChatListener listener, Operation<Long> operation) {
return isSideChat() ? 0 : operation.call(listener);
private long wrapMessageQueueSize(long size) {
return isSideChat() ? 0 : size;
}

// actions synced between main chat and side chat
Expand Down Expand Up @@ -97,53 +98,46 @@ private boolean isSideChat() {
// message stacking

@Unique
private int trimmedMessageCount = 0;
private int messageStackAmount = 1;

@Inject(
@ModifyExpressionValue(
method = "addMessage(Lnet/minecraft/network/chat/Component;Lnet/minecraft/network/chat/MessageSignature;ILnet/minecraft/client/GuiMessageTag;Z)V",
at = @At("HEAD")
at = @At(value = "INVOKE",
target = "Lnet/minecraft/client/gui/components/ComponentRenderUtils;wrapComponents(Lnet/minecraft/network/chat/FormattedText;ILnet/minecraft/client/gui/Font;)Ljava/util/List;"
)
)
private void countTrimmedMessagesBeforeMessageStacking(CallbackInfo ci) {
trimmedMessageCount = trimmedMessages.size();
}

@Inject(
method = "addMessage(Lnet/minecraft/network/chat/Component;Lnet/minecraft/network/chat/MessageSignature;ILnet/minecraft/client/GuiMessageTag;Z)V",
at = @At("TAIL")
)
private void stackMessages(
Component message,
private List<FormattedCharSequence> stackMessages(
List<FormattedCharSequence> lineMessages,
Component fullMessage,
MessageSignature signature,
int tickDelta,
GuiMessageTag tag,
boolean refresh,
CallbackInfo ci
@Share("cancel") LocalBooleanRef cancel
) {
if (!Config.getBoolean("stackDuplicateMsgs")) return;
if (trimmedMessageCount == 0) return;
cancel.set(false);
if (!Config.getBoolean("stackDuplicateMsgs")) return lineMessages;

// trimmedMessages[0] is the most recent message
var lineCount = trimmedMessages.size() - trimmedMessageCount;
if (trimmedMessageCount < lineCount) return;
if (trimmedMessageCount > lineCount) {
if (!trimmedMessages.get(lineCount * 2).endOfEntry()) return;
var lineCount = lineMessages.size();
if (trimmedMessages.size() < lineCount) return lineMessages;
if (trimmedMessages.size() > lineCount) {
if (!trimmedMessages.get(lineCount).endOfEntry()) return lineMessages;
}

// return if messages aren't equal
for (var index = lineCount; index < lineCount * 2; index++) {
var firstLine = trimmedMessages.get(index);
var secondLine = trimmedMessages.get(index - lineCount);
if (!TextFunctions.looksLike(firstLine.content(), secondLine.content())) return;
if (firstLine.endOfEntry() != secondLine.endOfEntry()) return;
// reset and return if messages aren't equal
for (var index = 0; index < lineCount; index++) {
var line1 = trimmedMessages.get(index);
var line2 = lineMessages.get(lineCount - 1 - index);
var endsEarly = index != 0 && line1.endOfEntry();
if (!TextFunctions.looksLike(line1.content(), line2) || endsEarly) {
messageStackAmount = 1;
return lineMessages;
}
}

// remove new message and update tags
var oldTag = Objects.requireNonNull(trimmedMessages.get(lineCount).tag());
var stackAmount = MessageStacking.getStackAmount(oldTag) + 1;

trimmedMessages.subList(0, lineCount).clear();

var newTag = ChatUI.plus(tag, MessageStacking.stackedMessageTag(stackAmount));
// replace old message, with updated tags
var newTag = ChatUI.plus(tag, MessageStacks.INSTANCE.tag(++messageStackAmount));
for (var index = 0; index < lineCount; index++) {
var oldLine = trimmedMessages.get(index);
var newLine = new GuiMessage.Line(
Expand All @@ -154,5 +148,20 @@ private void stackMessages(
);
trimmedMessages.set(index, newLine);
}

// cancel in the next handler and return a dummy value
cancel.set(true);
return Collections.emptyList();
}

@Inject(method = "addMessage(Lnet/minecraft/network/chat/Component;Lnet/minecraft/network/chat/MessageSignature;ILnet/minecraft/client/GuiMessageTag;Z)V",
at = @At(value = "INVOKE",
target = "Lnet/minecraft/client/gui/components/ComponentRenderUtils;wrapComponents(Lnet/minecraft/network/chat/FormattedText;ILnet/minecraft/client/gui/Font;)Ljava/util/List;",
shift = At.Shift.AFTER
),
cancellable = true
)
private void cancelAfterMessageStacking(CallbackInfo ci, @Share("cancel") LocalBooleanRef cancel) {
if (cancel.get()) ci.cancel();
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.github.homchom.recode.mixin.render.chat;

import com.llamalad7.mixinextras.injector.ModifyReturnValue;
import io.github.homchom.recode.feature.visual.EditBoxExpressionFormatter;
import io.github.homchom.recode.hypercube.DFValueMeta;
import io.github.homchom.recode.hypercube.DFValues;
Expand All @@ -20,7 +21,6 @@
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

import java.util.Objects;

Expand All @@ -43,23 +43,24 @@ public abstract class MCommandSuggestions {
@Shadow @Final EditBox input;

// expression highlighting and preview
@Inject(method = "formatChat", at = @At("RETURN"), cancellable = true)
private void highlightAndPreview(
@ModifyReturnValue(method = "formatChat", at = @At("RETURN"))
private FormattedCharSequence highlightAndPreview(
FormattedCharSequence returnValue,
String partialInput,
int position,
CallbackInfoReturnable<FormattedCharSequence> cir
int position
) {
if (!Config.getBoolean("highlightVarSyntax")) return;
if (!DF.isInMode(DF.getCurrentDFState(), PlotMode.Dev.ID)) return;
if (!Config.getBoolean("highlightVarSyntax")) return returnValue;
if (!DF.isInMode(DF.getCurrentDFState(), PlotMode.Dev.ID)) return returnValue;
var formatted = highlighter.format(
input.getValue(),
cir.getReturnValue(),
returnValue,
new IntRange(position, position + partialInput.length() - 1)
);
if (formatted != null) {
cir.setReturnValue(formatted.getText());
preview = formatted.getPreview();
return formatted.getText();
}
return returnValue;
}

@Inject(method = "render", at = @At("HEAD"))
Expand Down

0 comments on commit 4b1c23d

Please sign in to comment.