Fixed a few things worked on a couple things situated it so that the menu can be scrolled set color coding and made it so it actually shows the username

This commit is contained in:
minster586
2026-10-26 19:33:33 -04:00
parent 90666d0ac9
commit 5fe1ad4e19
20 changed files with 807 additions and 86 deletions
@@ -173,9 +173,11 @@ public final class ConnectionManager {
try {
JsonObject root = JsonParser.parseString(raw).getAsJsonObject();
if (socketPlatform == Platform.TWITCH && handleStreamerBotControl(root)) return;
if (config.debugLogging) LOGGER.info("Received from " + socketPlatform + ": " + raw);
StreamEvent event = socketPlatform == Platform.TIKTOK
? StreamEventParser.parseTikFinity(raw)
: StreamEventParser.parseStreamerBot(raw);
if (event.platform() == Platform.TIKTOK && "config".equals(event.type())) return;
synchronized (this) {
lastEvents.put(event.platform(), Instant.now());
statuses.put(event.platform(), "Connected");
@@ -290,7 +292,7 @@ public final class ConnectionManager {
private boolean isKnownEvent(StreamEvent event) {
if (event.platform() == Platform.TIKTOK) {
return switch (event.type()) {
case "chat", "gift", "share", "follow", "like", "roomUser", "subscribe" -> true;
case "chat", "gift", "share", "follow", "like", "join", "subscribe" -> true;
default -> false;
};
}
@@ -306,7 +308,7 @@ public final class ConnectionManager {
private void display(StreamEvent event, DisplayTarget target) {
String text = config.format(event);
Component component = Component.literal(text);
Component component = ColorText.parse(text);
switch (target) {
case CHAT -> {
if (client.gui != null) client.gui.getChat().addMessage(component);
@@ -318,7 +320,7 @@ public final class ConnectionManager {
client.getToasts(),
SystemToast.SystemToastIds.TUTORIAL_HINT,
Component.literal(event.platform() + " " + event.type()),
Component.literal(text));
component);
case HIDDEN -> {
}
}
@@ -11,6 +11,9 @@ public final class StreamChatClient implements ClientModInitializer {
private static final KeyMapping TOGGLE_CONNECTIONS = KeyBindingHelper.registerKeyBinding(
new KeyMapping("key.streamchat.toggle_connections", GLFW.GLFW_KEY_UNKNOWN, "category.streamchat"));
private static final KeyMapping RELOAD_CONFIG = KeyBindingHelper.registerKeyBinding(
new KeyMapping("key.streamchat.reload_config", GLFW.GLFW_KEY_UNKNOWN, "category.streamchat"));
public static StreamChatConfig CONFIG;
public static ConnectionManager CONNECTIONS;
@@ -23,6 +26,10 @@ public final class StreamChatClient implements ClientModInitializer {
while (TOGGLE_CONNECTIONS.consumeClick()) {
CONNECTIONS.toggleConnections();
}
while (RELOAD_CONFIG.consumeClick()) {
CONFIG.reload();
CONNECTIONS.configurationChanged();
}
});
}
}
@@ -1,11 +1,13 @@
package dev.streamchat;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.components.AbstractWidget;
import net.minecraft.client.gui.components.Button;
import net.minecraft.client.gui.components.EditBox;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.network.chat.Component;
import java.util.ArrayList;
import java.util.List;
public final class StreamChatScreen extends Screen {
@@ -14,7 +16,7 @@ public final class StreamChatScreen extends Screen {
private static final List<String> YOUTUBE_EVENTS =
List.of("Message", "SuperChat", "SuperSticker", "MemberMilestone", "NewSponsor", "GiftMembershipReceived");
private static final List<String> TIKTOK_EVENTS =
List.of("chat", "gift", "share", "follow", "like", "roomUser", "subscribe");
List.of("chat", "gift", "share", "follow", "like", "join", "subscribe");
private final Screen parent;
private final StreamChatConfig config;
@@ -25,6 +27,10 @@ public final class StreamChatScreen extends Screen {
private EditBox tikFinityUrl;
private EditBox prefix;
private EditBox template;
private final List<AbstractWidget> scrollable = new ArrayList<>();
private final List<Integer> baseY = new ArrayList<>();
private int scroll;
private int contentEnd;
public StreamChatScreen(Screen parent, StreamChatConfig config, ConnectionManager connections) {
super(Component.literal("Stream Chat Settings"));
@@ -90,17 +96,19 @@ public final class StreamChatScreen extends Screen {
prefix.setValue(config.getPrefix(selectedPlatform));
prefix.setMaxLength(128);
addRenderableWidget(prefix);
template = new EditBox(font, left, 270, rowWidth, 20, Component.literal("Message format"));
template.setValue(config.templates.getOrDefault(selectedPlatform.name(),
"{prefix}{username} > {message}"));
template = new EditBox(font, left, 270, rowWidth, 20, Component.literal("Chat message format"));
template.setValue(config.getChatFormat(selectedPlatform));
template.setMaxLength(256);
addRenderableWidget(template);
addRouteButtons(left);
captureScrollable();
addRenderableWidget(Button.builder(Component.literal("Toggle connections"), button -> connections.toggleConnections())
.bounds(left, height - 32, 180, 20).build());
.bounds(left, height - 32, 120, 20).build());
addRenderableWidget(Button.builder(Component.literal("Reload config"), button -> reloadConfig())
.bounds(left + 130, height - 32, 120, 20).build());
addRenderableWidget(Button.builder(Component.literal("Done"), button -> onClose())
.bounds(left + 200, height - 32, 180, 20).build());
.bounds(left + 260, height - 32, 120, 20).build());
}
@Override
@@ -108,22 +116,78 @@ public final class StreamChatScreen extends Screen {
renderBackground(graphics);
graphics.drawCenteredString(font, title, width / 2, 8, 0xFFFFFF);
int left = width / 2 - 190;
graphics.drawString(font, "Streamer.bot / TikFinity WebSocket settings", left, 60, 0xA0A0A0);
graphics.drawString(font, "Connection status: " + connections.status(selectedPlatform), left, 188, 0xFFFFFF);
graphics.drawString(font, "Last event: " + connections.lastEvent(selectedPlatform), left + 180, 188, 0xA0A0A0);
graphics.drawString(font, "Prefix", left, 220, 0xA0A0A0);
graphics.drawString(font, "Format: {prefix}, {platform}, {event}, {username}, {message}", left, 256, 0xA0A0A0);
graphics.drawString(font, "Event destination (click to cycle)", left, 296, 0xA0A0A0);
label(graphics, "Streamer.bot / TikFinity WebSocket settings", left, 60, 0xA0A0A0);
label(graphics, "Connection status: " + connections.status(selectedPlatform), left, 188, 0xFFFFFF);
label(graphics, "Last event: " + connections.lastEvent(selectedPlatform), left + 180, 188, 0xA0A0A0);
label(graphics, "Prefix", left, 220, 0xA0A0A0);
label(graphics, "Chat format ({prefix} {username} {message}; &c colors; other events: platform .yml)", left, 256, 0xA0A0A0);
label(graphics, "Event destination (click to cycle)", left, 296, 0xA0A0A0);
super.render(graphics, mouseX, mouseY, delta);
}
private void label(GuiGraphics graphics, String text, int x, int baseY, int color) {
int y = baseY - scroll;
if (y >= viewTop() && y + 9 <= viewBottom()) {
graphics.drawString(font, text, x, y, color);
}
}
private int viewTop() {
return 24;
}
private int viewBottom() {
return height - 40;
}
private int maxScroll() {
return Math.max(0, contentEnd + 8 - viewBottom());
}
private void captureScrollable() {
scrollable.clear();
baseY.clear();
for (var child : children()) {
if (child instanceof AbstractWidget widget) {
scrollable.add(widget);
baseY.add(widget.getY());
}
}
scroll = Math.min(scroll, maxScroll());
applyScroll();
}
private void applyScroll() {
for (int i = 0; i < scrollable.size(); i++) {
AbstractWidget widget = scrollable.get(i);
int y = baseY.get(i) - scroll;
widget.setY(y);
boolean inView = y >= viewTop() && y + widget.getHeight() <= viewBottom();
widget.visible = inView;
widget.active = inView;
}
}
private boolean scrollBy(double amount) {
int next = (int) Math.max(0, Math.min(maxScroll(), scroll - amount * 20));
if (next == scroll) return false;
scroll = next;
applyScroll();
return true;
}
@Override
public boolean mouseScrolled(double mouseX, double mouseY, double delta) {
return scrollBy(delta) || super.mouseScrolled(mouseX, mouseY, delta);
}
@Override
public void onClose() {
config.streamerBotUrl = streamerBotUrl.getValue().trim();
config.streamerBotPassword = streamerBotPassword.getValue();
config.tikFinityUrl = tikFinityUrl.getValue().trim();
config.prefixes.put(selectedPlatform.name(), prefix.getValue());
config.templates.put(selectedPlatform.name(), template.getValue());
config.setChatFormat(selectedPlatform, template.getValue());
config.save();
connections.configurationChanged();
minecraft.setScreen(parent);
@@ -134,11 +198,16 @@ public final class StreamChatScreen extends Screen {
config.streamerBotPassword = streamerBotPassword.getValue();
config.tikFinityUrl = tikFinityUrl.getValue().trim();
config.prefixes.put(selectedPlatform.name(), prefix.getValue());
config.templates.put(selectedPlatform.name(), template.getValue());
config.setChatFormat(selectedPlatform, template.getValue());
selectedPlatform = platform;
prefix.setValue(config.getPrefix(platform));
template.setValue(config.templates.getOrDefault(platform.name(),
"{prefix}{username} > {message}"));
template.setValue(config.getChatFormat(platform));
rebuildRoutes();
}
private void reloadConfig() {
config.reload();
connections.configurationChanged();
rebuildRoutes();
}
@@ -153,6 +222,7 @@ public final class StreamChatScreen extends Screen {
case YOUTUBE -> YOUTUBE_EVENTS;
case TIKTOK -> TIKTOK_EVENTS;
};
contentEnd = 320 + (events.size() + 1) / 2 * 24;
for (int i = 0; i < events.size(); i++) {
String eventType = events.get(i);
int x = left + (i % 2) * 195;