Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ public static void registerCommands(CommandDispatcher<FabricClientCommandSource>
// PlayerInfoCommand.register(dispatcher);
PluginsCommand.register(dispatcher);
PosCommand.register(dispatcher);
PostEffectCommand.register(dispatcher);
PredictBrushablesCommand.register(dispatcher);
RelogCommand.register(dispatcher);
RenderCommand.register(dispatcher);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package net.earthcomputer.clientcommands.command;

import com.mojang.brigadier.Command;
import com.mojang.brigadier.CommandDispatcher;
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import org.jetbrains.annotations.Nullable;

import static net.earthcomputer.clientcommands.command.arguments.PostEffectArgument.*;
import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.*;

public class PostEffectCommand {
public static void register(CommandDispatcher<FabricClientCommandSource> dispatcher) {
dispatcher.register(literal("cposteffect")
.then(argument("posteffect", postEffect())
.executes(ctx -> applyPostEffect(ctx.getSource(), getPostEffect(ctx, "posteffect"))))
.then(literal("reset")
.executes(ctx -> applyPostEffect(ctx.getSource(), null))));
}

private static int applyPostEffect(FabricClientCommandSource source, @Nullable ResourceLocation postEffect) {
if (postEffect == null) {
source.getClient().gameRenderer.clearPostEffect();
source.sendFeedback(Component.translatable("commands.cposteffect.reset.success"));
return Command.SINGLE_SUCCESS;
}
source.getClient().gameRenderer.setPostEffect(postEffect);
source.sendFeedback(Component.translatable("commands.cposteffect.apply.success", postEffect));
return Command.SINGLE_SUCCESS;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package net.earthcomputer.clientcommands.command.arguments;

import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.arguments.ArgumentType;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.exceptions.DynamicCommandExceptionType;
import com.mojang.brigadier.suggestion.Suggestions;
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.LevelTargetBundle;
import net.minecraft.client.renderer.PostChainConfig;
import net.minecraft.commands.SharedSuggestionProvider;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;

import java.util.Arrays;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Stream;

public class PostEffectArgument implements ArgumentType<ResourceLocation> {

private static final Collection<String> EXAMPLES = Arrays.asList("invert", "minecraft:spider", "clientcommands:crt");

private static final DynamicCommandExceptionType UNKNOWN_POST_EFFECT_EXCEPTION = new DynamicCommandExceptionType(postEffect -> Component.translatable("commands.cposteffect.unknownPostEffect", postEffect));

public static PostEffectArgument postEffect() {
return new PostEffectArgument();
}

public static ResourceLocation getPostEffect(final CommandContext<FabricClientCommandSource> context, final String name) {
return context.getArgument(name, ResourceLocation.class);
}

@Override
public ResourceLocation parse(StringReader reader) throws CommandSyntaxException {
int start = reader.getCursor();
ResourceLocation postEffectId = ResourceLocation.read(reader);

boolean valid = getValidPostChains().anyMatch(id -> id.equals(postEffectId));
if (!valid) {
reader.setCursor(start);
throw UNKNOWN_POST_EFFECT_EXCEPTION.createWithContext(reader, postEffectId);
}
return postEffectId;
}

@Override
public <S> CompletableFuture<Suggestions> listSuggestions(CommandContext<S> context, SuggestionsBuilder builder) {
return SharedSuggestionProvider.suggestResource(getValidPostChains(), builder);
}

@Override
public Collection<String> getExamples() {
return EXAMPLES;
}

private Stream<ResourceLocation> getValidPostChains() {
return Minecraft.getInstance().getShaderManager().compilationCache.configs.postChains().entrySet().stream()
.filter(entry -> entry.getValue().passes().stream()
.flatMap(PostChainConfig.Pass::referencedTargets)
.filter(location -> !entry.getValue().internalTargets().containsKey(location))
.allMatch(LevelTargetBundle.MAIN_TARGETS::contains))
.map(Map.Entry::getKey);
}
}
4 changes: 4 additions & 0 deletions src/main/resources/assets/clientcommands/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,10 @@
"commands.cpos.level.the_end": "the End",
"commands.cpos.level.the_nether": "the Nether",

"commands.cposteffect.apply.success": "Successfully applied post effect %s",
"commands.cposteffect.reset.success": "Successfully reset post effect",
"commands.cposteffect.unknownPostEffect": "Unknown post effect %s",

"commands.cpredictbrushables.foundBrushableBlock": "Found %s at %s with item %s %s",
"commands.cpredictbrushables.notFound": "No brushable blocks found",
"commands.cpredictbrushables.starting": "Searching for brushable blocks",
Expand Down
44 changes: 44 additions & 0 deletions src/main/resources/assets/clientcommands/post_effect/crt.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{
"targets": {
"swap": {}
},
"passes": [
{
"vertex_shader": "minecraft:core/screenquad",
"fragment_shader": "clientcommands:post/crt",
"inputs": [
{
"sampler_name": "In",
"target": "minecraft:main"
}
],
"output": "swap",
"uniforms": {}
},
{
"vertex_shader": "minecraft:core/screenquad",
"fragment_shader": "minecraft:post/bits",
"inputs": [
{
"sampler_name": "In",
"target": "swap"
}
],
"output": "minecraft:main",
"uniforms": {
"BitsConfig": [
{
"name": "Resolution",
"type": "float",
"value": 16.0
},
{
"name": "MosaicSize",
"type": "float",
"value": 4.0
}
]
}
}
]
}
32 changes: 32 additions & 0 deletions src/main/resources/assets/clientcommands/shaders/post/crt.fsh
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#version 330

uniform sampler2D InSampler;

in vec2 texCoord;

layout(std140) uniform SamplerInfo {
vec2 OutSize;
vec2 InSize;
};

out vec4 fragColor;

void main() {
vec2 oneTexel = 1.0 / InSize;

float aberr = 0.002;
vec3 col;
col.r = texture(InSampler, texCoord + vec2(aberr, 0.0)).r;
col.g = texture(InSampler, texCoord).g;
col.b = texture(InSampler, texCoord - vec2(aberr, 0.0)).b;

// Add scanlines
float scan = sin(texCoord.y * 800.0) * 0.1; // adjust frequency
col *= 1.0 - scan * 0.3;

// Vignette
float vignette = smoothstep(1.2, 0.6, length(texCoord - 0.5));
col *= vignette;

fragColor = vec4(col, 1.0);
}
6 changes: 6 additions & 0 deletions src/main/resources/clientcommands.aw
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ accessible method net/minecraft/client/Screenshot getFile (Ljava/io/File;)Ljava/
# cpermissionlevel
accessible method net/minecraft/client/player/LocalPlayer getPermissionLevel ()I

# cposteffect
accessible field net/minecraft/client/renderer/GameRenderer BLUR_POST_CHAIN_ID Lnet/minecraft/resources/ResourceLocation;
accessible method net/minecraft/client/renderer/GameRenderer setPostEffect (Lnet/minecraft/resources/ResourceLocation;)V
accessible field net/minecraft/client/renderer/ShaderManager compilationCache Lnet/minecraft/client/renderer/ShaderManager$CompilationCache;
accessible field net/minecraft/client/renderer/ShaderManager$CompilationCache configs Lnet/minecraft/client/renderer/ShaderManager$Configs;

# Game Options
accessible field net/minecraft/client/OptionInstance value Ljava/lang/Object;

Expand Down