Skip to content

Commit

Permalink
Added a duplicate message counter
Browse files Browse the repository at this point in the history
Quick changelog:
- added a dupe counter that shows up behind messages after 2 or more somewhat identical messages are recieved
- string formatter now functions properly when text is before the first formatting token
- implemented all counter options and features
- bumped the version number up to 1.4.6
  • Loading branch information
mrbuilder1961 committed May 28, 2022
1 parent 14544db commit 3e53ccf
Show file tree
Hide file tree
Showing 13 changed files with 132 additions and 93 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[![Fabric Mod](https://img.shields.io/badge/modloader-fabric-informational)](https://fabricmc.net/use/)
[![Latest Version](https://img.shields.io/badge/version-1.4.5-brightgreen)](https://github.com/Giggitybyte/ServerChatHistory/releases)
[![Latest Version](https://img.shields.io/badge/version-1.4.6-brightgreen)](https://github.com/Giggitybyte/ServerChatHistory/releases)
[![Curseforge Download](https://bit.ly/33eX25e)](https://www.curseforge.com/minecraft/mc-mods/wmch)
# Where's My Chat History

Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17

archivesBaseName = 'wmch'
version = '1.4.5'
version = '1.4.6'
group = 'obro1961.wmch'
project.ext.set('minecraft_version', '1.18.2')
project.ext.set('loader_version', '0.13.3')
Expand Down
14 changes: 10 additions & 4 deletions src/main/java/obro1961/wmch/Util.java
Original file line number Diff line number Diff line change
Expand Up @@ -101,18 +101,24 @@ public static Text getStrTextF(String dirty) {
Matcher results = finder.matcher(dirty);

if (dirty.matches(".*"+finder.pattern()+".*")) {
// if there is text before a formatter then add it alone
if( dirty.split(finder.pattern())[0].length() > 0 ) {
String prfx = dirty.split(finder.pattern())[0];
out.append(prfx);
dirty = dirty.replace(prfx, "");
};

List<String> texts = new ArrayList<>( Arrays.asList(dirty.split(finder.pattern())) ); texts.removeIf(s -> s.equals(""));
int i = 0;
// &8(&7x&r$&8) -> _&8(&7x&r#&8) -> [_,(,x,#,)] -> [r,8,7,r,8] -> Text

while(results.find()) {
Formatting[] style = new Formatting[results.group().length() / 2];
char[] codes = delAll(results.group(), "&").toCharArray();
for (int j = 0; j < codes.length; ++j) style[j] = Formatting.byCode(codes[j]);

out.append( new LiteralText(texts.get(i)).formatted(style) );
++i;
out.append( new LiteralText(texts.get(i++)).formatted(style) );
}
System.out.println(results.results());

return out;
} else
return Text.of(dirty);
Expand Down
49 changes: 17 additions & 32 deletions src/main/java/obro1961/wmch/config/ClothConfig.java
Original file line number Diff line number Diff line change
@@ -1,21 +1,5 @@
package obro1961.wmch.config;

import static obro1961.wmch.config.Option.BOUNDARY;
import static obro1961.wmch.config.Option.BOUNDARYCOLOR;
import static obro1961.wmch.config.Option.BOUNDARYSTR;
import static obro1961.wmch.config.Option.COUNTER;
import static obro1961.wmch.config.Option.COUNTERCOLOR;
import static obro1961.wmch.config.Option.COUNTERSTR;
import static obro1961.wmch.config.Option.HOVER;
import static obro1961.wmch.config.Option.HOVERSTR;
import static obro1961.wmch.config.Option.LENIANTEQUALS;
import static obro1961.wmch.config.Option.MAXMSGS;
import static obro1961.wmch.config.Option.NAMESTR;
import static obro1961.wmch.config.Option.TIME;
import static obro1961.wmch.config.Option.TIMECOLOR;
import static obro1961.wmch.config.Option.TIMEFORMAT;
import static obro1961.wmch.config.Option.TIMESTR;

import me.shedaniel.clothconfig2.api.ConfigBuilder;
import me.shedaniel.clothconfig2.api.ConfigCategory;
import me.shedaniel.clothconfig2.api.ConfigEntryBuilder;
Expand Down Expand Up @@ -43,29 +27,30 @@ public Screen getWMCHConfigScreen(Screen prevScreen) {

ConfigCategory time = bldr.getOrCreateCategory(new TranslatableText("text.wmch.time_category"));
ConfigCategory hover = bldr.getOrCreateCategory(new TranslatableText("text.wmch.hover_category"));
//ConfigCategory counter = bldr.getOrCreateCategory(new TranslatableText("text.wmch.counter_category"));
ConfigCategory counter = bldr.getOrCreateCategory(new TranslatableText("text.wmch.counter_category"));
ConfigCategory boundary = bldr.getOrCreateCategory(new TranslatableText("text.wmch.boundary_category"));
ConfigCategory other = bldr.getOrCreateCategory(new TranslatableText("text.wmch.other_category"));

eBldr = TIME.updateEntryBuilder(eBldr, time, TIME);
eBldr = TIMESTR.updateEntryBuilder(eBldr, time, TIMESTR);
eBldr = TIMEFORMAT.updateEntryBuilder(eBldr, time, TIMEFORMAT);
eBldr = TIMECOLOR.updateEntryBuilder(eBldr, time, TIMECOLOR);
eBldr = Option.TIME.updateEntryBuilder(eBldr, time, Option.TIME);
eBldr = Option.TIMESTR.updateEntryBuilder(eBldr, time, Option.TIMESTR);
eBldr = Option.TIMEFORMAT.updateEntryBuilder(eBldr, time, Option.TIMEFORMAT);
eBldr = Option.TIMECOLOR.updateEntryBuilder(eBldr, time, Option.TIMECOLOR);

eBldr = HOVER.updateEntryBuilder(eBldr, hover, HOVER);
eBldr = HOVERSTR.updateEntryBuilder(eBldr, hover, HOVERSTR);
eBldr = Option.HOVER.updateEntryBuilder(eBldr, hover, Option.HOVER);
eBldr = Option.HOVERSTR.updateEntryBuilder(eBldr, hover, Option.HOVERSTR);

/* eBldr = COUNTER.updateEntryBuilder(eBldr, counter, COUNTER);
eBldr = COUNTERSTR.updateEntryBuilder(eBldr, counter, COUNTERSTR);
eBldr = COUNTERCOLOR.updateEntryBuilder(eBldr, counter, COUNTERCOLOR);
eBldr = LENIANTEQUALS.updateEntryBuilder(eBldr, counter, LENIANTEQUALS); */
eBldr = Option.COUNTER.updateEntryBuilder(eBldr, counter, Option.COUNTER);
eBldr = Option.COUNTERSTR.updateEntryBuilder(eBldr, counter, Option.COUNTERSTR);
eBldr = Option.COUNTERCOLOR.updateEntryBuilder(eBldr, counter, Option.COUNTERCOLOR);
//eBldr = Option.DUPETHRESHOLD.updateEntryBuilder(eBldr, counter, Option.DUPETHRESHOLD);
eBldr = Option.LENIANTEQUALS.updateEntryBuilder(eBldr, counter, Option.LENIANTEQUALS);

eBldr = BOUNDARY.updateEntryBuilder(eBldr, boundary, BOUNDARY);
eBldr = BOUNDARYSTR.updateEntryBuilder(eBldr, boundary, BOUNDARYSTR);
eBldr = BOUNDARYCOLOR.updateEntryBuilder(eBldr, boundary, BOUNDARYCOLOR);
eBldr = Option.BOUNDARY.updateEntryBuilder(eBldr, boundary, Option.BOUNDARY);
eBldr = Option.BOUNDARYSTR.updateEntryBuilder(eBldr, boundary, Option.BOUNDARYSTR);
eBldr = Option.BOUNDARYCOLOR.updateEntryBuilder(eBldr, boundary, Option.BOUNDARYCOLOR);

eBldr = NAMESTR.updateEntryBuilder(eBldr, other, NAMESTR);
eBldr = MAXMSGS.updateEntryBuilder(eBldr, other, MAXMSGS);
eBldr = Option.NAMESTR.updateEntryBuilder(eBldr, other, Option.NAMESTR);
eBldr = Option.MAXMSGS.updateEntryBuilder(eBldr, other, Option.MAXMSGS);


bldr.setSavingRunnable(() -> {
Expand Down
30 changes: 15 additions & 15 deletions src/main/java/obro1961/wmch/config/Config.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.text.LiteralText;
import net.minecraft.text.Style;
import net.minecraft.text.Text;
import obro1961.wmch.Util;
import obro1961.wmch.WMCH;
Expand All @@ -37,6 +38,7 @@ public class Config {
public boolean counter;
public String counterStr;
public int counterColor;
public int dupeThreshold;
public boolean leniantEquals;
public boolean boundary;
public String boundaryStr;
Expand All @@ -55,12 +57,13 @@ public Config() {
this.counter = Option.COUNTER.getDefault();
this.counterStr = Option.COUNTERSTR.getDefault();
this.counterColor = Option.COUNTERCOLOR.getDefault();
this.dupeThreshold = Option.DUPETHRESHOLD.getDefault();
this.leniantEquals = Option.LENIANTEQUALS.getDefault();
this.boundary = Option.BOUNDARY.getDefault();
this.boundaryStr = Option.BOUNDARYSTR.getDefault();
this.boundaryColor = Option.BOUNDARYCOLOR.getDefault();
this.nameStr = Option.NAMESTR.getDefault();
this.maxMsgs = Option.MAXMSGS.getDefault();
this.leniantEquals = Option.LENIANTEQUALS.getDefault();
}

/**
Expand All @@ -82,10 +85,11 @@ public static void validate() {
Option.BOUNDARYSTR.onSave(cfg.boundaryStr, Option.BOUNDARYSTR);
Option.BOUNDARYCOLOR.onSave(cfg.boundaryColor, Option.BOUNDARYCOLOR);

/* Option.COUNTER.onSave(cfg.counter, Option.COUNTER);
Option.COUNTER.onSave(cfg.counter, Option.COUNTER);
Option.COUNTERSTR.onSave(cfg.counterStr, Option.COUNTERSTR);
Option.COUNTERCOLOR.onSave(cfg.counterColor, Option.COUNTERCOLOR);
Option.LENIANTEQUALS.onSave(cfg.leniantEquals, Option.LENIANTEQUALS); */
//Option.DUPETHRESHOLD.onSave(cfg.dupeThreshold, Option.DUPETHRESHOLD);
Option.LENIANTEQUALS.onSave(cfg.leniantEquals, Option.LENIANTEQUALS);

Option.NAMESTR.onSave(cfg.nameStr, Option.NAMESTR);
Option.MAXMSGS.onSave(cfg.maxMsgs, Option.MAXMSGS);
Expand All @@ -98,7 +102,7 @@ public static void validate() {
/** Formats timeStr, then uses that to format timeFormat, adds a space, then finally colors it */
public Text getTimeF(Date when) {
return ((LiteralText)Util.getStrTextF(Option.TIMEFORMAT.get() + (new SimpleDateFormat(cfg.timeStr).format(when)) + " "))
.fillStyle(net.minecraft.text.Style.EMPTY.withColor(Option.TIMECOLOR.get()));
.fillStyle(Style.EMPTY.withColor(Option.TIMECOLOR.get()));
}
public String getHoverF(Date when) {
return new SimpleDateFormat(Option.HOVERSTR.get()).format(when);
Expand All @@ -107,23 +111,19 @@ public String getNameF(String name) {
return Option.NAMESTR.get().replaceAll("\\$", name);
}
public Text getDupeF(int dupes) {
return Util.getStrTextF(" " + Option.COUNTERSTR.get().replaceAll("\\$", Integer.toString(dupes)));
return ((LiteralText)Util.getStrTextF(" " + Option.COUNTERSTR.get().replaceAll("\\$", Integer.toString(dupes))))
.fillStyle(Style.EMPTY.withColor(Option.COUNTERCOLOR.get()));
}

/** Prints any changes between altering Options. */
/** Prints any changes between altering of Options */
protected static void logDiffs() {
// only log if changes were made
if (Option.diff == "Changes made:") {
Option.diff = "No changes made!";
} else {
Option.diff.lines().forEach(ln -> {});
}

lg.info(Option.diff);
if (Option.diff == "Changes made:") lg.info("No changes made!");
else lg.info(Option.diff);
Option.diff = "Changes made:";
}

/** Sets the {@code cfg} field in {@link Config} to the file at {@code ./config/wmch.json}. */
/** Sets the {@code cfg} field in {@link Config} to the file at {@code ./config/wmch.json} */
public static void read() {
File cfgFile = new File( FabricLoader.getInstance().getConfigDir().toFile().getAbsolutePath() + File.separator + "wmch.json" );
Gson gson = new Gson();
Expand All @@ -150,7 +150,7 @@ public static void read() {
}

/**
* Saves a Config to {@code ./config/wmch.json}.
* Saves a Config to {@code ./config/wmch.json}
* @param c The Config to save
*/
public static void write(Config c) {
Expand Down
16 changes: 9 additions & 7 deletions src/main/java/obro1961/wmch/config/Option.java
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ public ConfigEntryBuilder updateEntryBuilder(ConfigEntryBuilder builder, ConfigC
break;
}
case "java.lang.Integer": {
category.addEntry( me.getKey() == "maxMsgs"
category.addEntry( me.getKey() == "maxMsgs" || me.getKey() == "dupeThreshold"
? builder.startIntField(getName(), (int)value)
.setDefaultValue((int)def)
.setTooltip(getTooltip())
Expand Down Expand Up @@ -169,31 +169,33 @@ public static void printTableEntries() {
public static final Option<Boolean> COUNTER = new Option<>(true, "counter", TIME.getSaveConsumer());
public static final Option<String> COUNTERSTR = new Option<>("&8(&7x&e$&8)", "counterStr", (inc, me) -> {
if(inc.contains("$")) {
String out = Util.delAll(inc, "\s{3,}");
String out = Util.delAll(inc, "\s{2,}");
Util.getStrTextF(out);
me.setInDefConfig(out);
}
});
public static final Option<Integer> COUNTERCOLOR = new Option<>(Formatting.YELLOW.getColorValue(), "counterColor", TIMECOLOR.getSaveConsumer());
public static final Option<Integer> DUPETHRESHOLD = new Option<>(3, "dupeThreshold", (inc, me) -> {
if(inc > 1 && inc < Option.MAXMSGS.get()) me.setInDefConfig(inc);
});
public static final Option<Boolean> LENIANTEQUALS = new Option<>(false, "leniantEquals", TIME.getSaveConsumer());
public static final Option<Boolean> BOUNDARY = new Option<>(true, "boundary", TIME.getSaveConsumer());
public static final Option<String> BOUNDARYSTR = new Option<>("&b[==============]", "boundaryStr", (inc, me) -> {
if(inc.length() > 0) {
String out = Util.delAll(inc, "\s{2,}").trim();
Util.getStrTextF(out);
me.setInDefConfig(inc);
Util.getStrTextF(inc.strip());
me.setInDefConfig(inc.strip());
}
});
public static final Option<Integer> BOUNDARYCOLOR = new Option<>(Formatting.DARK_AQUA.getColorValue(), "boundaryColor", TIMECOLOR.getSaveConsumer());
public static final Option<String> NAMESTR = new Option<>("<$>", "nameStr", (inc, me) -> {if(inc.contains("$")) me.setInDefConfig(inc);});
public static final Option<Integer> MAXMSGS = new Option<>(1024, "maxMsgs", (inc, me) -> {
if(4097 > inc && inc > 99) me.setInDefConfig(inc);
});
public static final Option<Boolean> LENIANTEQUALS = new Option<>(false, "leniantEquals", TIME.getSaveConsumer());

public static final List<Option<?>> OPTIONS = new ArrayList<>(Arrays.asList(
TIME, TIMESTR, TIMECOLOR, TIMEFORMAT,
HOVER, HOVERSTR,
COUNTER, COUNTERSTR, COUNTERCOLOR, LENIANTEQUALS,
COUNTER, COUNTERSTR, COUNTERCOLOR, DUPETHRESHOLD, LENIANTEQUALS,
BOUNDARY, BOUNDARYSTR, BOUNDARYCOLOR,
NAMESTR, MAXMSGS
));
Expand Down
50 changes: 43 additions & 7 deletions src/main/java/obro1961/wmch/mixins/ChatHudMixin.java
Original file line number Diff line number Diff line change
Expand Up @@ -128,23 +128,59 @@ public OrderedText transform(OrderedText old) {
client.keyboard.setClipboard(raw);
client.inGameHud.addChatMessage(
MessageType.GAME_INFO,
new LiteralText( "'%s' copied!".formatted(raw.trim()) ).formatted(Formatting.GREEN),
new LiteralText( "'%s' copied!".formatted(raw.strip()) ).formatted(Formatting.GREEN),
net.minecraft.util.Util.NIL_UUID
);
}

return old;
}

@Inject(
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/client/font/TextHandler;getStyleAt(Lnet/minecraft/text/OrderedText;I)Lnet/minecraft/text/Style;"
),
at = @At(value="INVOKE", target="Lnet/minecraft/client/font/TextHandler;getStyleAt(Lnet/minecraft/text/OrderedText;I)Lnet/minecraft/text/Style;"),
method = "getText",
locals = LocalCapture.CAPTURE_FAILEXCEPTION
locals = LocalCapture.CAPTURE_FAILSOFT
)
private void grabText(double x,double y,CallbackInfoReturnable<Style> ci,double d,double e,int i,int j,ChatHudLine<OrderedText> chatHudLine) {
hovered = chatHudLine.getText();
}

/** Decides which messages need dupe counters and which don't */
@Inject(method = "addMessage(Lnet/minecraft/text/Text;IIZ)V", at = @At("HEAD"), cancellable = true)
public void injectCounter(Text m, int time, int id, boolean rfrs, CallbackInfo ci) {
//* index 0 is the message before this one (current message hasnt been added yet)
if( Option.COUNTER.get() && !m.getString().equals( Util.delAll(Option.BOUNDARYSTR.get(), "(?:&[0-9a-fA-Fk-orK-OR])+") ) && messages.size() > 0 ) {
ChatHudLine<Text> last = messages.get(0);
final List<Text> sibs = m.getSiblings(); final List<Text> lSibs = last.getText().getSiblings();

Short dupes = sibs.size() > 2
? Short.valueOf( Util.delAll(sibs.get(2).getString(), "\\D") )
: lSibs.size() > 2
? Short.valueOf( Util.delAll(lSibs.get(2).getString(), "\\D") )
: 1
;

// if the current or last message have a counter or the messages are equal, continue
if( dupes > 1 || Option.LENIANTEQUALS.get()
? sibs.get(1).getString().equalsIgnoreCase(lSibs.get(1).getString())
: sibs.get(1).getString().equals(lSibs.get(1).getString())
) {
++dupes;
// adds the updated counter and timestamp
if(lSibs.size() > 2) last.getText().getSiblings().set(2, WMCH.config.getDupeF(dupes));
else last.getText().getSiblings().add(2, WMCH.config.getDupeF(dupes));
if(lSibs.get(0).getString().length() > 0) last.getText().getSiblings().set(0, sibs.get(0));
// modifies the message to have a counter
messages.set(0, new ChatHudLine<Text>(last.getCreationTick(), last.getText(), last.getId()));

if(messages.size() > 0) visibleMessages.remove(0);
net.minecraft.client.util.ChatMessages.breakRenderedChatMessageLines(
last.getText(),
net.minecraft.util.math.MathHelper.floor((double)ChatHud.getWidth(client.options.chatWidth) / client.options.chatScale),
client.textRenderer
).forEach(vt -> visibleMessages.add(0, new ChatHudLine<>(last.getCreationTick(), vt, last.getId())));

ci.cancel(); //? might screw up logs or something, maybe add a warning that says a message was removed for duping
}
}
}
}
12 changes: 7 additions & 5 deletions src/main/resources/assets/wmch/lang/en_US.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,20 @@
"text.wmch.counter": "Message counter toggle",
"text.wmch.counterStr": "Message counter text",
"text.wmch.counterColor": "Message counter color",
"text.wmch.dupeThreshold": "Message threshold",
"text.wmch.leniantEquals": "Leniant counter toggle",
"text.wmch.counter_desc": "Should a message counter show after messages to indicate multiple were sent?",
"text.wmch.counterStr_desc": "The text that's added to the end of messages to indicate multiple duplicates were sent. Must include a $ for the number of duplicates.",
"text.wmch.counterColor_desc": "The color that's 'filled in' where applicable in the counter text.",
"text.wmch.leniantEquals_desc": "When enabled, the dupe counter will mark a message as 'duped' even if the style or text is slightly different.",
"text.wmch.counter_desc": "Should a message counter show after a message to indicate multiple were sent?",
"text.wmch.counterStr_desc": "The text that's added to the end of a message to indicate multiple duplicates were sent. Must include a $ for the number of duplicates.",
"text.wmch.counterColor_desc": "The color that's 'filled in' where applicable in the counter text, for example '&r' will be replaced with this color.",
"text.wmch.dupeThreshold_desc": "How many of the same message need to be recieved before they start being grouped together?",
"text.wmch.leniantEquals_desc": "When enabled, the dupe counter will mark a message as 'duped' even if the text's case is slightly different.",

"text.wmch.boundary": "Boundary toggle",
"text.wmch.boundaryStr": "Boundary text",
"text.wmch.boundaryColor": "Boundary color",
"text.wmch.boundary_desc": "Should a boundary line show after using chat, leaving, and then joining again later?",
"text.wmch.boundaryStr_desc": "The text that is shown when a boundary line is inserted into the chat, add ampersands (&) followed by a formatting code to prettify it.",
"text.wmch.boundaryColor_desc": "The color that's 'filled in' where applicable in the boundary text.",
"text.wmch.boundaryColor_desc": "The color that's 'filled in' where applicable in the boundary text, for example '&r' will be replaced with this color.",

"text.wmch.nameStr": "Playername text",
"text.wmch.maxMsgs": "Maximum chat messages",
Expand Down
Loading

0 comments on commit 3e53ccf

Please sign in to comment.