Skip to content

Commit

Permalink
Group mod credits by role instead of bunching them together (#706)
Browse files Browse the repository at this point in the history
* Display credits by role instead of bunching them together

* Add newlines between credit groups, allow translating role names

* Fix minor code style issues

* Improve translation key generation and fallback role names

* Sort contributors within roles

* Fix Fabric authors being credited wrong

- Group mod credits together by role
  • Loading branch information
LostLuma authored Apr 22, 2024
1 parent 5eba246 commit cf58ff0
Show file tree
Hide file tree
Showing 6 changed files with 109 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import net.minecraft.client.gui.widget.ElementListWidget;
import net.minecraft.client.gui.widget.EntryListWidget;
import net.minecraft.client.render.*;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.text.OrderedText;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
Expand Down Expand Up @@ -207,20 +206,40 @@ public void renderList(DrawContext DrawContext, int mouseX, int mouseY, float de
children().add(new MojangCreditsEntry(line));
}
} else if (!"java".equals(mod.getId())) {
List<String> credits = mod.getCredits();
var credits = mod.getCredits();

if (!credits.isEmpty()) {
children().add(emptyEntry);

for (OrderedText line : textRenderer.wrapLines(CREDITS_TEXT, wrapWidth)) {
children().add(new DescriptionEntry(line));
}

for (String credit : credits) {
var iterator = credits.entrySet().iterator();

while (iterator.hasNext()) {
int indent = 8;
for (OrderedText line : textRenderer.wrapLines(Text.literal(credit), wrapWidth - 16)) {

var role = iterator.next();
var roleName = role.getKey();

for (var line : textRenderer.wrapLines(this.creditsRoleText(roleName), wrapWidth - 16)) {
children().add(new DescriptionEntry(line, indent));
indent = 16;
}

for (var contributor : role.getValue()) {
indent = 16;

for (var line : textRenderer.wrapLines(Text.literal(contributor), wrapWidth - 24)) {
children().add(new DescriptionEntry(line, indent));
indent = 24;
}
}

if (iterator.hasNext()) {
children().add(emptyEntry);
}
}
}
}
Expand Down Expand Up @@ -331,6 +350,18 @@ public void renderScrollBar(BufferBuilder bufferBuilder, Tessellator tessellator
}
}

private Text creditsRoleText(String roleName) {
// Replace spaces and dashes in role names with underscores if they exist
// Notably Quilted Fabric API does this with FabricMC as "Upstream Owner"
var translationKey = roleName.replaceAll("[\s-]", "_");

// Add an s to the default untranslated string if it ends in r since this
// Fixes common role names people use in English (e.g. Author -> Authors)
var fallback = roleName.endsWith("r") ? roleName + "s" : roleName;

return Text.translatableWithFallback("modmenu.credits.role." + translationKey, fallback).append(Text.literal(":"));
}

protected class DescriptionEntry extends ElementListWidget.Entry<DescriptionEntry> {
protected OrderedText text;
protected int indent;
Expand Down
10 changes: 8 additions & 2 deletions src/main/java/com/terraformersmc/modmenu/util/mod/Mod.java
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,17 @@ default String getTranslatedDescription() {
@NotNull
List<String> getAuthors();

/**
* @return a mapping of contributors to their roles.
*/
@NotNull
List<String> getContributors();
Map<String, Collection<String>> getContributors();

/**
* @return a mapping of roles to each contributor with that role.
*/
@NotNull
List<String> getCredits();
SortedMap<String, SortedSet<String>> getCredits();

@NotNull
Set<Badge> getBadges();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,13 +89,13 @@ public FabricDummyParentMod(FabricMod host, String id) {
}

@Override
public @NotNull List<String> getContributors() {
return new ArrayList<>();
public @NotNull Map<String, Collection<String>> getContributors() {
return Map.of();
}

@Override
public @NotNull List<String> getCredits() {
return new ArrayList<>();
public @NotNull SortedMap<String, SortedSet<String>> getCredits() {
return new TreeMap<>();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -211,20 +211,35 @@ public FabricMod(ModContainer modContainer, Set<String> modpackMods) {
}

@Override
public @NotNull List<String> getContributors() {
List<String> authors = metadata.getContributors().stream().map(Person::getName).collect(Collectors.toList());
if ("minecraft".equals(getId()) && authors.isEmpty()) {
return Lists.newArrayList();
public @NotNull Map<String, Collection<String>> getContributors() {
Map<String, Collection<String>> contributors = new HashMap<>();

for (var contributor : this.metadata.getContributors()) {
contributors.put(contributor.getName(), List.of("Contributor"));
}
return authors;

return contributors;
}

@NotNull
public List<String> getCredits() {
List<String> list = new ArrayList<>();
list.addAll(getAuthors());
list.addAll(getContributors());
return list;
@Override
public @NotNull SortedMap<String, SortedSet<String>> getCredits() {
SortedMap<String, SortedSet<String>> credits = new TreeMap<>();

var authors = this.getAuthors();
var contributors = this.getContributors();

for (var author : authors) {
contributors.put(author, List.of("Author"));
}

for (var contributor : contributors.entrySet()) {
for (var role : contributor.getValue()) {
credits.computeIfAbsent(role, key -> new TreeSet<>(String.CASE_INSENSITIVE_ORDER));
credits.get(role).add(contributor.getKey());
}
}

return credits;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,17 @@
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.stream.Collectors;

public class QuiltMod extends FabricMod {
Expand Down Expand Up @@ -51,17 +59,30 @@ public QuiltMod(net.fabricmc.loader.api.ModContainer fabricModContainer, Set<Str
}

@Override
public @NotNull List<String> getContributors() {
List<String> authors = metadata.contributors().stream().map(modContributor -> modContributor.name() + " (" + modContributor.role() + ")").collect(Collectors.toList());
if ("minecraft".equals(getId()) && authors.isEmpty()) {
return Lists.newArrayList();
public @NotNull Map<String, Collection<String>> getContributors() {
Map<String, Collection<String>> contributors = new HashMap<>();

for (var contributor : this.metadata.contributors()) {
contributors.put(contributor.name(), contributor.roles());
}
return authors;

return contributors;
}

@Override
public @NotNull List<String> getCredits() {
return this.getContributors();
public @NotNull SortedMap<String, SortedSet<String>> getCredits() {
SortedMap<String, SortedSet<String>> credits = new TreeMap<>();

var contributors = this.getContributors();

for (var contributor : contributors.entrySet()) {
for (var role : contributor.getValue()) {
credits.computeIfAbsent(role, key -> new TreeSet<>(String.CASE_INSENSITIVE_ORDER));
credits.get(role).add(contributor.getKey());
}
}

return credits;
}


Expand Down
8 changes: 8 additions & 0 deletions src/main/resources/assets/modmenu/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,14 @@
"modmenu.wiki": "Wiki",
"modmenu.youtube": "YouTube",

"modmenu.credits.role.author": "Authors",
"modmenu.credits.role.contributor": "Contributors",
"modmenu.credits.role.translator": "Translators",
"modmenu.credits.role.maintainer": "Maintainers",
"modmenu.credits.role.playtester": "Playtesters",
"modmenu.credits.role.illustrator": "Illustrators",
"modmenu.credits.role.owner": "Owners",

"modmenu.modsFolder": "Open Mods Folder",
"modmenu.configsFolder": "Open Configs Folder",

Expand Down

0 comments on commit cf58ff0

Please sign in to comment.