Skip to content

Commit 4787981

Browse files
committed
Added mechanism to allow resource packs with modified core shaders to declare compatible features
Closes #323
1 parent 6b358a6 commit 4787981

File tree

2 files changed

+83
-29
lines changed

2 files changed

+83
-29
lines changed
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* This file is part of ImmediatelyFast - https://github.com/RaphiMC/ImmediatelyFast
3+
* Copyright (C) 2023-2025 RK_01/RaphiMC and contributors
4+
*
5+
* This program is free software; you can redistribute it and/or
6+
* modify it under the terms of the GNU Lesser General Public
7+
* License as published by the Free Software Foundation; either
8+
* version 3 of the License, or (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
package net.raphimc.immediatelyfast.feature.core;
19+
20+
import com.mojang.serialization.Codec;
21+
import com.mojang.serialization.codecs.RecordCodecBuilder;
22+
import net.minecraft.resource.metadata.ResourceMetadataSerializer;
23+
24+
import java.util.Collections;
25+
import java.util.List;
26+
27+
public record ImmediatelyFastResourcePackMetadata(List<String> compatibleFeatures) {
28+
29+
public static final ImmediatelyFastResourcePackMetadata DEFAULT = new ImmediatelyFastResourcePackMetadata(Collections.emptyList());
30+
public static final Codec<ImmediatelyFastResourcePackMetadata> CODEC = RecordCodecBuilder.create(instance ->
31+
instance.group(
32+
Codec.STRING.listOf().fieldOf("compatible_features").forGetter(ImmediatelyFastResourcePackMetadata::compatibleFeatures)
33+
).apply(instance, ImmediatelyFastResourcePackMetadata::new)
34+
);
35+
public static final ResourceMetadataSerializer<ImmediatelyFastResourcePackMetadata> SERIALIZER = ResourceMetadataSerializer.fromCodec("immediatelyfast", CODEC);
36+
37+
}

common/src/main/java/net/raphimc/immediatelyfast/injection/mixins/core/compat/MixinGameRenderer.java

Lines changed: 46 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,11 @@
2424
import net.minecraft.client.render.GameRenderer;
2525
import net.minecraft.resource.Resource;
2626
import net.minecraft.resource.ResourceFactory;
27+
import net.minecraft.resource.ResourcePack;
2728
import net.minecraft.util.Identifier;
2829
import net.raphimc.immediatelyfast.ImmediatelyFast;
2930
import net.raphimc.immediatelyfast.compat.CoreShaderBlacklist;
31+
import net.raphimc.immediatelyfast.feature.core.ImmediatelyFastResourcePackMetadata;
3032
import org.spongepowered.asm.mixin.Final;
3133
import org.spongepowered.asm.mixin.Mixin;
3234
import org.spongepowered.asm.mixin.Shadow;
@@ -35,55 +37,70 @@
3537
import org.spongepowered.asm.mixin.injection.Inject;
3638
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
3739

38-
import java.util.ArrayList;
39-
import java.util.List;
40-
import java.util.Map;
40+
import java.io.IOException;
41+
import java.util.*;
4142

4243
@Mixin(GameRenderer.class)
4344
public abstract class MixinGameRenderer {
4445

45-
@Shadow
46-
@Final
47-
MinecraftClient client;
48-
4946
@Shadow
5047
@Final
5148
private Map<String, ShaderProgram> programs;
5249

5350
@Inject(method = "loadPrograms", at = @At("RETURN"))
5451
private void checkForCoreShaderModifications(ResourceFactory factory, CallbackInfo ci) {
55-
boolean modified = false;
56-
for (Map.Entry<String, ShaderProgram> shaderProgramEntry : this.programs.entrySet()) {
57-
if (!CoreShaderBlacklist.isBlacklisted(shaderProgramEntry.getKey())) continue;
52+
if (ImmediatelyFast.config.experimental_disable_resource_pack_conflict_handling) {
53+
return;
54+
}
5855

59-
final Identifier vertexShaderIdentifier = new Identifier("shaders/core/" + shaderProgramEntry.getValue().getVertexShader().getName() + ".vsh");
60-
final Resource vertexShaderResource = factory.getResource(vertexShaderIdentifier).orElse(null);
61-
if (vertexShaderResource != null && !vertexShaderResource.getPack().equals(this.client.getDefaultResourcePack())) {
62-
modified = true;
63-
break;
56+
ResourcePack resourcePackWhichBreaksFontAtlasResizing = null;
57+
ResourcePack resourcePackWhichBreaksHudBatching = null;
58+
try {
59+
final Set<ResourcePack> breakingResourcePacks = new HashSet<>();
60+
for (Map.Entry<String, ShaderProgram> shaderProgramEntry : this.programs.entrySet()) {
61+
if (!CoreShaderBlacklist.isBlacklisted(shaderProgramEntry.getKey())) continue;
62+
63+
final Identifier vertexShaderIdentifier = new Identifier("shaders/core/" + shaderProgramEntry.getValue().getVertexShader().getName() + ".vsh");
64+
final ResourcePack vertexShaderResourcePack = factory.getResource(vertexShaderIdentifier).map(Resource::getPack).orElse(null);
65+
if (vertexShaderResourcePack != null && !vertexShaderResourcePack.equals(MinecraftClient.getInstance().getDefaultResourcePack())) {
66+
breakingResourcePacks.add(vertexShaderResourcePack);
67+
}
68+
final Identifier fragmentShaderIdentifier = new Identifier("shaders/core/" + shaderProgramEntry.getValue().getFragmentShader().getName() + ".fsh");
69+
final ResourcePack fragmentShaderResourcePack = factory.getResource(fragmentShaderIdentifier).map(Resource::getPack).orElse(null);
70+
if (fragmentShaderResourcePack != null && !fragmentShaderResourcePack.equals(MinecraftClient.getInstance().getDefaultResourcePack())) {
71+
breakingResourcePacks.add(fragmentShaderResourcePack);
72+
}
6473
}
65-
final Identifier fragmentShaderIdentifier = new Identifier("shaders/core/" + shaderProgramEntry.getValue().getFragmentShader().getName() + ".fsh");
66-
final Resource fragmentShaderResource = factory.getResource(fragmentShaderIdentifier).orElse(null);
67-
if (fragmentShaderResource != null && !fragmentShaderResource.getPack().equals(this.client.getDefaultResourcePack())) {
68-
modified = true;
69-
break;
74+
for (ResourcePack resourcePack : breakingResourcePacks) {
75+
ImmediatelyFastResourcePackMetadata metadata = resourcePack.parseMetadata(ImmediatelyFastResourcePackMetadata.SERIALIZER);
76+
if (metadata == null) {
77+
metadata = ImmediatelyFastResourcePackMetadata.DEFAULT;
78+
}
79+
if (!metadata.compatibleFeatures().contains("font_atlas_resizing")) {
80+
resourcePackWhichBreaksFontAtlasResizing = resourcePack;
81+
}
82+
if (!metadata.compatibleFeatures().contains("hud_batching")) {
83+
resourcePackWhichBreaksHudBatching = resourcePack;
84+
}
7085
}
86+
} catch (IOException e) {
87+
ImmediatelyFast.LOGGER.error("Failed to check for core shader modifications", e);
7188
}
7289

73-
if (modified && !ImmediatelyFast.config.experimental_disable_resource_pack_conflict_handling) {
74-
ImmediatelyFast.LOGGER.warn("Core shader modifications detected. Temporarily disabling some parts of ImmediatelyFast.");
75-
if (ImmediatelyFast.runtimeConfig.font_atlas_resizing) {
76-
ImmediatelyFast.runtimeConfig.font_atlas_resizing = false;
77-
this.immediatelyFast$reloadFontStorages();
78-
}
79-
80-
ImmediatelyFast.runtimeConfig.hud_batching = false;
90+
if (ImmediatelyFast.runtimeConfig.font_atlas_resizing && resourcePackWhichBreaksFontAtlasResizing != null) {
91+
ImmediatelyFast.LOGGER.warn("Resource pack " + resourcePackWhichBreaksFontAtlasResizing.getName() + " is not compatible with font atlas resizing. Temporarily disabling font atlas resizing.");
92+
ImmediatelyFast.runtimeConfig.font_atlas_resizing = false;
93+
this.immediatelyFast$reloadFontStorages();
8194
} else {
8295
if (!ImmediatelyFast.runtimeConfig.font_atlas_resizing && ImmediatelyFast.config.font_atlas_resizing) {
8396
ImmediatelyFast.runtimeConfig.font_atlas_resizing = true;
8497
this.immediatelyFast$reloadFontStorages();
8598
}
86-
99+
}
100+
if (ImmediatelyFast.runtimeConfig.hud_batching && resourcePackWhichBreaksHudBatching != null) {
101+
ImmediatelyFast.LOGGER.warn("Resource pack " + resourcePackWhichBreaksHudBatching.getName() + " is not compatible with HUD batching. Temporarily disabling HUD batching.");
102+
ImmediatelyFast.runtimeConfig.hud_batching = false;
103+
} else {
87104
ImmediatelyFast.runtimeConfig.hud_batching = ImmediatelyFast.config.hud_batching;
88105
}
89106
}

0 commit comments

Comments
 (0)