Skip to content

Commit 9cc047f

Browse files
committed
Merge remote-tracking branch 'origin/feature/packetmine-rewrite' into feature/packetmine-rewrite
2 parents cc0493f + 5ce3483 commit 9cc047f

File tree

156 files changed

+5548
-4123
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

156 files changed

+5548
-4123
lines changed

.coderabbit.yaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
language: "en-US"
2+
early_access: false
3+
reviews:
4+
profile: "chill"
5+
high_level_summary: false
6+
poem: false
7+
review_status: false
8+
auto_review:
9+
enabled: false
10+
chat:
11+
auto_reply: false

common/src/main/java/com/lambda/mixin/network/ClientPlayNetworkHandlerMixin.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,14 @@
1919

2020
import com.lambda.event.EventFlow;
2121
import com.lambda.event.events.InventoryEvent;
22+
import com.lambda.module.modules.render.NoRender;
2223
import net.minecraft.client.network.ClientPlayNetworkHandler;
2324
import net.minecraft.network.packet.s2c.play.ScreenHandlerSlotUpdateS2CPacket;
2425
import net.minecraft.network.packet.s2c.play.UpdateSelectedSlotS2CPacket;
2526
import org.spongepowered.asm.mixin.Mixin;
2627
import org.spongepowered.asm.mixin.injection.At;
2728
import org.spongepowered.asm.mixin.injection.Inject;
29+
import org.spongepowered.asm.mixin.injection.Redirect;
2830
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
2931

3032
@Mixin(ClientPlayNetworkHandler.class)
@@ -38,4 +40,9 @@ private void onUpdateSelectedSlot(UpdateSelectedSlotS2CPacket packet, CallbackIn
3840
private void onScreenHandlerSlotUpdate(ScreenHandlerSlotUpdateS2CPacket packet, CallbackInfo ci) {
3941
EventFlow.post(new InventoryEvent.SlotUpdate(packet.getSyncId(), packet.getRevision(), packet.getSlot(), packet.getStack()));
4042
}
43+
44+
@Redirect(method = "onServerMetadata", at = @At(value = "FIELD", target = "Lnet/minecraft/client/network/ClientPlayNetworkHandler;displayedUnsecureChatWarning:Z", ordinal = 0))
45+
public boolean onServerMetadata(ClientPlayNetworkHandler clientPlayNetworkHandler) {
46+
return NoRender.getNoChatVerificationToast();
47+
}
4148
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* Copyright 2025 Lambda
3+
*
4+
* This program is free software: you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation, either version 3 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
18+
package com.lambda.mixin.render;
19+
20+
import com.lambda.module.modules.client.LambdaMoji;
21+
import net.minecraft.client.font.TextRenderer;
22+
import net.minecraft.client.gui.DrawContext;
23+
import net.minecraft.client.gui.hud.ChatHud;
24+
import net.minecraft.text.OrderedText;
25+
import org.spongepowered.asm.mixin.Mixin;
26+
import org.spongepowered.asm.mixin.injection.At;
27+
import org.spongepowered.asm.mixin.injection.Redirect;
28+
29+
@Mixin(ChatHud.class)
30+
public class ChatHudMixin {
31+
@Redirect(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;drawTextWithShadow(Lnet/minecraft/client/font/TextRenderer;Lnet/minecraft/text/OrderedText;III)I"))
32+
int redirectRenderCall(DrawContext instance, TextRenderer textRenderer, OrderedText text, int x, int y, int color) {
33+
return instance.drawTextWithShadow(textRenderer, LambdaMoji.INSTANCE.parse(text, x, y, color), 0, y, 16777215 + (color << 24));
34+
}
35+
}

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

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,26 +17,47 @@
1717

1818
package com.lambda.mixin.render;
1919

20+
import com.google.common.base.Strings;
2021
import com.lambda.command.CommandManager;
22+
import com.lambda.graphics.renderer.gui.font.core.LambdaAtlas;
23+
import com.lambda.module.modules.client.LambdaMoji;
24+
import com.lambda.module.modules.client.RenderSettings;
2125
import com.mojang.brigadier.CommandDispatcher;
26+
import com.mojang.brigadier.suggestion.Suggestions;
27+
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
2228
import net.minecraft.client.gui.screen.ChatInputSuggestor;
2329
import net.minecraft.client.gui.widget.TextFieldWidget;
2430
import net.minecraft.client.network.ClientPlayNetworkHandler;
2531
import net.minecraft.command.CommandSource;
32+
import org.jetbrains.annotations.Nullable;
2633
import org.spongepowered.asm.mixin.Final;
2734
import org.spongepowered.asm.mixin.Mixin;
2835
import org.spongepowered.asm.mixin.Shadow;
36+
import org.spongepowered.asm.mixin.Unique;
2937
import org.spongepowered.asm.mixin.injection.At;
38+
import org.spongepowered.asm.mixin.injection.Inject;
3039
import org.spongepowered.asm.mixin.injection.ModifyVariable;
3140
import org.spongepowered.asm.mixin.injection.Redirect;
41+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
42+
43+
import java.util.concurrent.CompletableFuture;
44+
import java.util.regex.Matcher;
45+
import java.util.regex.Pattern;
46+
import java.util.stream.Stream;
3247

3348
@Mixin(ChatInputSuggestor.class)
34-
public class ChatInputSuggestorMixin {
49+
public abstract class ChatInputSuggestorMixin {
3550

3651
@Shadow
3752
@Final
3853
TextFieldWidget textField;
3954

55+
@Shadow
56+
private @Nullable CompletableFuture<Suggestions> pendingSuggestions;
57+
58+
@Shadow
59+
public abstract void show(boolean narrateFirstSuggestion);
60+
4061
@ModifyVariable(method = "refresh", at = @At(value = "STORE"), index = 3)
4162
private boolean refreshModify(boolean showCompletions) {
4263
return CommandManager.INSTANCE.isCommand(textField.getText());
@@ -46,4 +67,55 @@ private boolean refreshModify(boolean showCompletions) {
4667
private CommandDispatcher<CommandSource> refreshRedirect(ClientPlayNetworkHandler instance) {
4768
return CommandManager.INSTANCE.currentDispatcher(textField.getText());
4869
}
70+
71+
@Inject(method = "refresh", at = @At("TAIL"))
72+
private void refreshEmojiSuggestion(CallbackInfo ci) {
73+
if (!LambdaMoji.INSTANCE.isEnabled() ||
74+
!LambdaMoji.INSTANCE.getSuggestions()) return;
75+
76+
String typing = textField.getText();
77+
78+
// Don't suggest emojis in commands
79+
if (CommandManager.INSTANCE.isCommand(typing) ||
80+
CommandManager.INSTANCE.isLambdaCommand(typing)) return;
81+
82+
int cursor = textField.getCursor();
83+
String textToCursor = typing.substring(0, cursor);
84+
if (textToCursor.isEmpty()) return;
85+
86+
// Most right index at the left of the regex expression
87+
int start = neoLambda$getLastColon(textToCursor);
88+
if (start == -1) return;
89+
90+
String emojiString = typing.substring(start + 1);
91+
92+
Stream<String> results = LambdaAtlas.INSTANCE.getKeys(RenderSettings.INSTANCE.getEmojiFont())
93+
.keySet().stream()
94+
.filter(s -> s.startsWith(emojiString))
95+
.map(s -> s + ":");
96+
97+
pendingSuggestions = CommandSource.suggestMatching(results, new SuggestionsBuilder(textToCursor, start + 1));
98+
pendingSuggestions.thenRun(() -> {
99+
if (!pendingSuggestions.isDone()) return;
100+
101+
show(false);
102+
});
103+
}
104+
105+
@Unique
106+
private static final Pattern COLON_PATTERN = Pattern.compile("(:[a-zA-Z0-9_]+)");
107+
108+
@Unique
109+
private int neoLambda$getLastColon(String input) {
110+
if (Strings.isNullOrEmpty(input)) return -1;
111+
112+
int i = -1;
113+
Matcher matcher = COLON_PATTERN.matcher(input);
114+
115+
while (matcher.find()) {
116+
i = matcher.start();
117+
}
118+
119+
return i;
120+
}
49121
}

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

Lines changed: 0 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -17,65 +17,15 @@
1717

1818
package com.lambda.mixin.render;
1919

20-
import com.lambda.Lambda;
2120
import com.lambda.command.CommandManager;
22-
import com.lambda.graphics.renderer.gui.font.FontRenderer;
23-
import com.lambda.graphics.renderer.gui.font.LambdaEmoji;
24-
import com.lambda.graphics.renderer.gui.font.glyph.GlyphInfo;
25-
import com.lambda.module.modules.client.LambdaMoji;
26-
import com.lambda.util.math.Vec2d;
27-
import kotlin.Pair;
28-
import kotlin.ranges.IntRange;
2921
import net.minecraft.client.gui.screen.ChatScreen;
3022
import org.spongepowered.asm.mixin.Mixin;
3123
import org.spongepowered.asm.mixin.injection.At;
3224
import org.spongepowered.asm.mixin.injection.Inject;
33-
import org.spongepowered.asm.mixin.injection.ModifyArg;
3425
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
3526

36-
import java.util.ArrayList;
37-
import java.util.Collections;
38-
import java.util.List;
39-
4027
@Mixin(ChatScreen.class)
4128
public abstract class ChatScreenMixin {
42-
@ModifyArg(method = "sendMessage", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayNetworkHandler;sendChatMessage(Ljava/lang/String;)V"), index = 0)
43-
private String modifyChatText(String chatText) {
44-
if (LambdaMoji.INSTANCE.isDisabled()) return chatText;
45-
46-
List<Pair<GlyphInfo, IntRange>> emojis = FontRenderer.Companion.parseEmojis(chatText, LambdaEmoji.Twemoji);
47-
Collections.reverse(emojis);
48-
49-
List<String> pushEmojis = new ArrayList<>();
50-
List<Vec2d> pushPositions = new ArrayList<>();
51-
52-
for (Pair<GlyphInfo, IntRange> emoji : emojis) {
53-
String emojiString = chatText.substring(emoji.getSecond().getStart() + 1, emoji.getSecond().getEndInclusive());
54-
if (LambdaEmoji.Twemoji.get(emojiString) == null)
55-
continue;
56-
57-
// Because the width of a char is bigger than an emoji
58-
// we can simply replace the matches string by a space
59-
// and render it after the text
60-
chatText = chatText.substring(0, emoji.getSecond().getStart()) + " " + chatText.substring(emoji.getSecond().getEndInclusive() + 1);
61-
62-
// We cannot retain the position in the future, but we can
63-
// assume that every time you send a message the height of
64-
// the position will change by the height of the glyph
65-
// The positions are from the top left corner of the screen
66-
int x = Lambda.getMc().textRenderer.getWidth(chatText.substring(0, emoji.getSecond().getStart()));
67-
int y = Lambda.getMc().textRenderer.fontHeight;
68-
69-
pushEmojis.add(String.format(":%s:", emojiString));
70-
pushPositions.add(new Vec2d(x, y));
71-
}
72-
73-
// Not optimal because it has to parse the emoji again but who cares
74-
LambdaMoji.INSTANCE.add(pushEmojis, pushPositions);
75-
76-
return chatText;
77-
}
78-
7929
@Inject(method = "sendMessage", at = @At("HEAD"), cancellable = true)
8030
void sendMessageInject(String chatText, boolean addToHistory, CallbackInfoReturnable<Boolean> cir) {
8131
if (!CommandManager.INSTANCE.isLambdaCommand(chatText)) return;
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* Copyright 2025 Lambda
3+
*
4+
* This program is free software: you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation, either version 3 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
18+
package com.lambda.mixin.render;
19+
20+
import com.lambda.Lambda;
21+
import com.lambda.module.modules.render.MapPreview;
22+
import net.minecraft.client.MinecraftClient;
23+
import net.minecraft.client.font.TextRenderer;
24+
import net.minecraft.client.gui.DrawContext;
25+
import net.minecraft.client.gui.screen.Screen;
26+
import net.minecraft.client.gui.screen.ingame.HandledScreen;
27+
import net.minecraft.client.gui.tooltip.HoveredTooltipPositioner;
28+
import net.minecraft.client.gui.tooltip.TooltipBackgroundRenderer;
29+
import net.minecraft.client.gui.tooltip.TooltipComponent;
30+
import net.minecraft.client.gui.tooltip.TooltipPositioner;
31+
import net.minecraft.client.item.TooltipData;
32+
import net.minecraft.item.ItemStack;
33+
import net.minecraft.item.Items;
34+
import net.minecraft.text.Text;
35+
import org.spongepowered.asm.mixin.Final;
36+
import org.spongepowered.asm.mixin.Mixin;
37+
import org.spongepowered.asm.mixin.Shadow;
38+
import org.spongepowered.asm.mixin.injection.At;
39+
import org.spongepowered.asm.mixin.injection.Inject;
40+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
41+
42+
import java.util.List;
43+
import java.util.Optional;
44+
import java.util.stream.Collectors;
45+
46+
@Mixin(DrawContext.class)
47+
public abstract class DrawContextMixin {
48+
@Shadow protected abstract void drawTooltip(TextRenderer textRenderer, List<TooltipComponent> components, int x, int y, TooltipPositioner positioner);
49+
50+
@Inject(method = "drawTooltip(Lnet/minecraft/client/font/TextRenderer;Ljava/util/List;Ljava/util/Optional;II)V", at = @At("HEAD"), cancellable = true)
51+
void drawItemTooltip(TextRenderer textRenderer, List<Text> text, Optional<TooltipData> data, int x, int y, CallbackInfo ci) {
52+
List<TooltipComponent> list = text.stream().map(Text::asOrderedText).map(TooltipComponent::of).collect(Collectors.toList());
53+
data.ifPresent(datax -> list.add(1, TooltipComponent.of(datax)));
54+
55+
var screen = (HandledScreen) Lambda.getMc().currentScreen;
56+
if (screen.focusedSlot != null) {
57+
var stack = screen.focusedSlot.getStack();
58+
if (stack.isOf(Items.FILLED_MAP)) list.add(1, new MapPreview.MapComponent(stack));
59+
}
60+
61+
drawTooltip(textRenderer, list, x, y, HoveredTooltipPositioner.INSTANCE);
62+
ci.cancel();
63+
}
64+
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
package com.lambda.mixin.render;
1919

20-
import com.lambda.util.LambdaResource;
20+
import com.lambda.util.LambdaResourceKt;
2121
import net.minecraft.client.gui.screen.SplashOverlay;
2222
import net.minecraft.client.texture.ResourceTexture;
2323
import net.minecraft.resource.DefaultResourcePack;
@@ -62,7 +62,7 @@ public LogoTextureMixin(Identifier location) {
6262

6363
@Redirect(method = "loadTextureData", at = @At(value = "INVOKE", target = "Lnet/minecraft/resource/DefaultResourcePack;open(Lnet/minecraft/resource/ResourceType;Lnet/minecraft/util/Identifier;)Lnet/minecraft/resource/InputSupplier;"))
6464
InputSupplier<InputStream> loadTextureData(DefaultResourcePack instance, ResourceType type, Identifier id) {
65-
return () -> new LambdaResource("textures/lambda_banner.png").getStream();
65+
return () -> LambdaResourceKt.getStream("textures/lambda_banner.png");
6666
}
6767
}
6868
}

common/src/main/kotlin/com/lambda/Lambda.kt

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,7 @@ package com.lambda
2020
import com.google.gson.Gson
2121
import com.google.gson.GsonBuilder
2222
import com.lambda.config.serializer.*
23-
import com.lambda.config.serializer.gui.CustomModuleWindowSerializer
24-
import com.lambda.config.serializer.gui.ModuleTagSerializer
25-
import com.lambda.config.serializer.gui.TagWindowSerializer
2623
import com.lambda.core.Loader
27-
import com.lambda.gui.impl.clickgui.windows.tag.CustomModuleWindow
28-
import com.lambda.gui.impl.clickgui.windows.tag.TagWindow
2924
import com.lambda.module.tag.ModuleTag
3025
import com.lambda.util.KeyCode
3126
import com.mojang.authlib.GameProfile
@@ -54,9 +49,6 @@ object Lambda {
5449

5550
val gson: Gson = GsonBuilder()
5651
.setPrettyPrinting()
57-
.registerTypeAdapter(ModuleTag::class.java, ModuleTagSerializer)
58-
.registerTypeAdapter(CustomModuleWindow::class.java, CustomModuleWindowSerializer)
59-
.registerTypeAdapter(TagWindow::class.java, TagWindowSerializer)
6052
.registerTypeAdapter(KeyCode::class.java, KeyCodeSerializer)
6153
.registerTypeAdapter(Color::class.java, ColorSerializer)
6254
.registerTypeAdapter(BlockPos::class.java, BlockPosSerializer)

common/src/main/kotlin/com/lambda/command/CommandRegistry.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ object CommandRegistry : Configurable(LambdaConfig), Loadable {
3232
override val name = "command"
3333
val prefix by setting("prefix", ';')
3434

35-
val commands = getInstances<LambdaCommand> { forPackages("com.lambda.command.commands") }.toMutableList()
35+
val commands = getInstances<LambdaCommand>().toMutableList()
3636

3737
override fun load() = "Loaded ${commands.size} commands with ${dispatcher.root.children()} possible command paths."
3838

0 commit comments

Comments
 (0)