Skip to content

Commit 5c04268

Browse files
committed
Rework the resource pack scanner to produce compatibility reports
1 parent cf27e14 commit 5c04268

File tree

1 file changed

+132
-72
lines changed

1 file changed

+132
-72
lines changed

src/main/java/me/jellysquid/mods/sodium/client/compatibility/checks/ResourcePackScanner.java

Lines changed: 132 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -8,26 +8,30 @@
88
import net.minecraft.text.MutableText;
99
import net.minecraft.text.Text;
1010
import net.minecraft.util.Identifier;
11+
import org.jetbrains.annotations.NotNull;
1112
import org.slf4j.Logger;
1213
import org.slf4j.LoggerFactory;
1314
import java.io.IOException;
14-
import java.util.ArrayList;
15-
import java.util.Arrays;
16-
import java.util.HashMap;
17-
import java.util.List;
18-
import java.util.Map;
15+
import java.util.*;
16+
import java.util.stream.Collectors;
1917

2018
public class ResourcePackScanner {
21-
22-
private static final Logger LOGGER = LoggerFactory.getLogger("Sodium-InGameChecks");
23-
private static final List<String> VSH_FSH_BLACKLIST = Arrays.asList(
24-
"rendertype_solid.vsh", "rendertype_solid.fsh",
25-
"rendertype_cutout_mipped.vsh", "rendertype_cutout_mipped.fsh",
26-
"rendertype_cutout.vsh", "rendertype_cutout.fsh",
27-
"rendertype_translucent.vsh", "rendertype_translucent.fsh",
28-
"rendertype_tripwire.vsh", "rendertype_tripwire.fsh"
19+
private static final Logger LOGGER = LoggerFactory.getLogger("Sodium-ResourcePackScanner");
20+
21+
private static final Set<String> SHADER_PROGRAM_BLACKLIST = Set.of(
22+
"rendertype_solid.vsh",
23+
"rendertype_solid.fsh",
24+
"rendertype_cutout_mipped.vsh",
25+
"rendertype_cutout_mipped.fsh",
26+
"rendertype_cutout.vsh",
27+
"rendertype_cutout.fsh",
28+
"rendertype_translucent.vsh",
29+
"rendertype_translucent.fsh",
30+
"rendertype_tripwire.vsh",
31+
"rendertype_tripwire.fsh"
2932
);
30-
private static final List<String> GLSL_BLACKLIST = Arrays.asList(
33+
34+
private static final Set<String> SHADER_INCLUDE_BLACKLIST = Set.of(
3135
"light.glsl",
3236
"fog.glsl"
3337
);
@@ -40,85 +44,138 @@ public class ResourcePackScanner {
4044
* Detailed information on shader files replaced by resource packs is printed in the client log.
4145
*/
4246
public static void checkIfCoreShaderLoaded(ResourceManager manager) {
43-
HashMap<String, MessageLevel> detectedResourcePacks = new HashMap<>();
44-
var customResourcePacks = manager.streamResourcePacks();
45-
46-
customResourcePacks.forEach(resourcePack -> {
47-
// Omit 'vanilla' and 'fabric' resource packs
48-
if (!resourcePack.getName().equals("vanilla") && !resourcePack.getName().equals("fabric")) {
49-
var resourcePackName = resourcePack.getName();
50-
var ignoredShaders = determineIgnoredShaders(resourcePack);
47+
var outputs = manager.streamResourcePacks()
48+
.filter(pack -> !isBuiltInResourcePack(pack))
49+
.collect(Collectors.toMap(ResourcePack::getName, ResourcePackScanner::scanResources));
5150

52-
resourcePack.findResources(ResourceType.CLIENT_RESOURCES, Identifier.DEFAULT_NAMESPACE, "shaders", (path, ignored) -> {
53-
// Trim full shader file path to only contain the filename
54-
var shaderName = path.getPath().substring(path.getPath().lastIndexOf('/') + 1);
51+
printToasts(outputs);
52+
printCompatibilityReport(outputs);
53+
}
5554

56-
// Check if the pack has already acknowledged the warnings in this file,
57-
// in this case we report a different info log about the situation
58-
if (ignoredShaders.contains(shaderName)) {
59-
if (VSH_FSH_BLACKLIST.contains(shaderName)) {
60-
LOGGER.info("Resource pack '{}' replaces core shader '{}' but indicates it can be ignored", resourcePackName, shaderName);
61-
}
55+
private static void printToasts(Map<String, ScanResults> scanResults) {
56+
var incompatibleResourcePacks = new ArrayList<String>();
57+
var likelyIncompatibleResourcePacks = new ArrayList<String>();
6258

63-
if (GLSL_BLACKLIST.contains(shaderName)) {
64-
LOGGER.info("Resource pack '{}' replaces shader '{}' but indicates it can be ignored", resourcePackName, shaderName);
65-
}
66-
return;
67-
}
59+
for (var entry : scanResults.entrySet()) {
60+
var path = entry.getKey();
61+
var result = entry.getValue();
6862

69-
if (VSH_FSH_BLACKLIST.contains(shaderName)) {
63+
if (!result.shaderPrograms.isEmpty()) {
64+
incompatibleResourcePacks.add(path);
65+
} else if (!result.shaderIncludes.isEmpty()) {
66+
likelyIncompatibleResourcePacks.add(path);
67+
}
68+
}
7069

71-
if (!detectedResourcePacks.containsKey(resourcePackName)) {
72-
detectedResourcePacks.put(resourcePackName, MessageLevel.SEVERE);
73-
} else if (detectedResourcePacks.get(resourcePackName) == MessageLevel.WARN) {
74-
detectedResourcePacks.replace(resourcePackName, MessageLevel.SEVERE);
75-
}
70+
boolean shown = false;
7671

77-
LOGGER.error("Resource pack '{}' replaces core shader '{}'", resourcePackName, shaderName);
78-
}
72+
if (!incompatibleResourcePacks.isEmpty()) {
73+
showConsoleMessage(Text.translatable("sodium.console.core_shaders_error"), MessageLevel.SEVERE);
7974

80-
if (GLSL_BLACKLIST.contains(shaderName)) {
75+
for (var pack : incompatibleResourcePacks) {
76+
showConsoleMessage(Text.literal(getResourcePackName(pack)), MessageLevel.SEVERE);
77+
}
8178

82-
if (!detectedResourcePacks.containsKey(resourcePackName)) {
83-
detectedResourcePacks.put(resourcePackName, MessageLevel.WARN);
84-
}
79+
shown = true;
80+
}
8581

86-
LOGGER.error("Resource pack '{}' replaces shader '{}'", resourcePackName, shaderName);
82+
if (!likelyIncompatibleResourcePacks.isEmpty()) {
83+
showConsoleMessage(Text.translatable("sodium.console.core_shaders_warn"), MessageLevel.WARN);
8784

88-
}
89-
});
85+
for (var pack : likelyIncompatibleResourcePacks) {
86+
showConsoleMessage(Text.literal(getResourcePackName(pack)), MessageLevel.WARN);
9087
}
91-
});
9288

93-
if (detectedResourcePacks.containsValue(MessageLevel.SEVERE)) {
94-
showConsoleMessage(Text.translatable("sodium.console.core_shaders_error"), MessageLevel.SEVERE);
89+
shown = true;
90+
}
91+
92+
if (shown) {
93+
showConsoleMessage(Text.translatable("sodium.console.core_shaders_info"), MessageLevel.INFO);
94+
}
95+
}
96+
97+
private static void printCompatibilityReport(Map<String, ScanResults> scanResults) {
98+
var builder = new StringBuilder();
99+
100+
for (var entry : scanResults.entrySet()) {
101+
var path = entry.getKey();
102+
var result = entry.getValue();
95103

96-
for (Map.Entry<String, MessageLevel> entry : detectedResourcePacks.entrySet()) {
104+
builder.append("- Resource pack: ").append(getResourcePackName(path)).append("\n");
105+
106+
if (!result.shaderPrograms.isEmpty()) {
107+
emitProblem(builder,
108+
"The resource pack replaces terrain shaders, which are not supported",
109+
"https://github.com/CaffeineMC/sodium-fabric/wiki/Resource-Packs",
110+
result.shaderPrograms);
111+
}
97112

98-
if (entry.getValue() == MessageLevel.SEVERE) {
99-
// Omit 'file/' prefix for the in-game message
100-
var message = entry.getKey().startsWith("file/") ? entry.getKey().substring(5) : entry.getKey();
101-
showConsoleMessage(Text.literal(message), MessageLevel.SEVERE);
102-
}
113+
if (!result.shaderIncludes.isEmpty()) {
114+
emitProblem(builder,
115+
"The resource pack modifies shader include files, which are not fully supported",
116+
"https://github.com/CaffeineMC/sodium-fabric/wiki/Resource-Packs",
117+
result.shaderIncludes);
103118
}
104119
}
105120

106-
if (detectedResourcePacks.containsValue(MessageLevel.WARN)) {
107-
showConsoleMessage(Text.translatable("sodium.console.core_shaders_warn"), MessageLevel.WARN);
121+
if (!builder.isEmpty()) {
122+
LOGGER.error("The following compatibility issues were found with installed resource packs:\n{}", builder);
123+
}
124+
}
108125

109-
for (Map.Entry<String, MessageLevel> entry : detectedResourcePacks.entrySet()) {
126+
private static void emitProblem(StringBuilder builder, String description, String url, List<String> resources) {
127+
builder.append("\t- Problem found: ").append("\n");
128+
builder.append("\t\t- Description:\n\t\t\t").append(description).append("\n");
129+
builder.append("\t\t- More information: ").append(url).append("\n");
130+
builder.append("\t\t- Files: ").append("\n");
110131

111-
if (entry.getValue() == MessageLevel.WARN) {
112-
// Omit 'file/' prefix for the in-game message
113-
var message = entry.getKey().startsWith("file/") ? entry.getKey().substring(5) : entry.getKey();
114-
showConsoleMessage(Text.literal(message), MessageLevel.WARN);
115-
}
116-
}
132+
for (var resource : resources) {
133+
builder.append("\t\t\t- ").append(resource).append("\n");
117134
}
135+
}
118136

119-
if (!detectedResourcePacks.isEmpty()) {
120-
showConsoleMessage(Text.translatable("sodium.console.core_shaders_info"), MessageLevel.INFO);
137+
@NotNull
138+
private static ScanResults scanResources(ResourcePack pack) {
139+
final var ignoredShaders = determineIgnoredShaders(pack);
140+
141+
if (!ignoredShaders.isEmpty()) {
142+
LOGGER.warn("Resource pack '{}' indicates the following shaders should be ignored: {}",
143+
getResourcePackName(pack.getName()), String.join(", ", ignoredShaders));
121144
}
145+
146+
final var unsupportedShaderPrograms = new ArrayList<String>();
147+
final var unsupportedShaderIncludes = new ArrayList<String>();
148+
149+
pack.findResources(ResourceType.CLIENT_RESOURCES, Identifier.DEFAULT_NAMESPACE, "shaders", (identifier, supplier) -> {
150+
// Trim full shader file path to only contain the filename
151+
final var path = identifier.getPath();
152+
final var name = path.substring(path.lastIndexOf('/') + 1);
153+
154+
// Check if the pack has already acknowledged the warnings in this file,
155+
// in this case we report a different info log about the situation
156+
if (ignoredShaders.contains(name)) {
157+
return;
158+
}
159+
160+
// Check the path against known problem files
161+
if (SHADER_PROGRAM_BLACKLIST.contains(name)) {
162+
unsupportedShaderPrograms.add(path);
163+
} else if (SHADER_INCLUDE_BLACKLIST.contains(name)) {
164+
unsupportedShaderIncludes.add(path);
165+
}
166+
});
167+
168+
return new ScanResults(unsupportedShaderPrograms, unsupportedShaderIncludes);
169+
}
170+
171+
private static boolean isBuiltInResourcePack(ResourcePack pack) {
172+
var name = pack.getName();
173+
return name.equals("vanilla") || name.equals("fabric");
174+
}
175+
176+
private static String getResourcePackName(String path) {
177+
// Omit 'file/' prefix for the in-game message
178+
return path.startsWith("file/") ? path.substring(5) : path;
122179
}
123180

124181
/**
@@ -143,7 +200,10 @@ private static List<String> determineIgnoredShaders(ResourcePack resourcePack) {
143200
}
144201

145202
private static void showConsoleMessage(MutableText message, MessageLevel messageLevel) {
146-
Console.instance().logMessage(messageLevel, message, 20.0);
203+
Console.instance().logMessage(messageLevel, message, 12.5);
147204
}
148205

206+
private record ScanResults(ArrayList<String> shaderPrograms, ArrayList<String> shaderIncludes) {
207+
208+
}
149209
}

0 commit comments

Comments
 (0)