diff --git a/src/main/java/net/earthcomputer/clientcommands/ClientCommands.java b/src/main/java/net/earthcomputer/clientcommands/ClientCommands.java index a7febe05..a28d9b33 100644 --- a/src/main/java/net/earthcomputer/clientcommands/ClientCommands.java +++ b/src/main/java/net/earthcomputer/clientcommands/ClientCommands.java @@ -168,6 +168,7 @@ public static void registerCommands(CommandDispatcher // PlayerInfoCommand.register(dispatcher); PluginsCommand.register(dispatcher); PosCommand.register(dispatcher); + PostEffectCommand.register(dispatcher); RelogCommand.register(dispatcher); RenderCommand.register(dispatcher); ReplyCommand.register(dispatcher); diff --git a/src/main/java/net/earthcomputer/clientcommands/command/PostEffectCommand.java b/src/main/java/net/earthcomputer/clientcommands/command/PostEffectCommand.java new file mode 100644 index 00000000..7e4dd09d --- /dev/null +++ b/src/main/java/net/earthcomputer/clientcommands/command/PostEffectCommand.java @@ -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.PostChainArgument.*; +import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.*; + +public class PostEffectCommand { + public static void register(CommandDispatcher dispatcher) { + dispatcher.register(literal("cposteffect") + .then(argument("posteffect", postChain()) + .executes(ctx -> applyPostEffect(ctx.getSource(), getPostChain(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; + } +} diff --git a/src/main/java/net/earthcomputer/clientcommands/command/arguments/PostChainArgument.java b/src/main/java/net/earthcomputer/clientcommands/command/arguments/PostChainArgument.java new file mode 100644 index 00000000..61e3b611 --- /dev/null +++ b/src/main/java/net/earthcomputer/clientcommands/command/arguments/PostChainArgument.java @@ -0,0 +1,60 @@ +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.renderer.GameRenderer; +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.Set; +import java.util.concurrent.CompletableFuture; + +public class PostChainArgument implements ArgumentType { + + private static final Collection EXAMPLES = Arrays.asList("invert", "minecraft:spider", "minecraft:creeper"); + + private static final DynamicCommandExceptionType UNKNOWN_POST_CHAIN_EXCEPTION = new DynamicCommandExceptionType(postChain -> Component.translatable("commands.cposteffect.unknownPostEffect", postChain)); + + // known working post chains, "minecraft:entity_outline" and "minecraft:transparency" also exist but do not work directly + // see assets/minecraft/post_effect for all post chains + // perhaps this can be extracted from Minecraft.getInstance().getShaderManager().compilationCache.configs.postChains() + private static final Set SUPPORTED_POST_CHAINS = Set.of(GameRenderer.BLUR_POST_CHAIN_ID, ResourceLocation.withDefaultNamespace("creeper"), ResourceLocation.withDefaultNamespace("invert"), ResourceLocation.withDefaultNamespace("spider")); + + public static PostChainArgument postChain() { + return new PostChainArgument(); + } + + public static ResourceLocation getPostChain(final CommandContext context, final String name) { + return context.getArgument(name, ResourceLocation.class); + } + + @Override + public ResourceLocation parse(StringReader reader) throws CommandSyntaxException { + int start = reader.getCursor(); + ResourceLocation postChainId = ResourceLocation.read(reader); + if (!SUPPORTED_POST_CHAINS.contains(postChainId)) { + reader.setCursor(start); + throw UNKNOWN_POST_CHAIN_EXCEPTION.createWithContext(reader, postChainId); + } + return postChainId; + } + + @Override + public CompletableFuture listSuggestions(CommandContext context, SuggestionsBuilder builder) { + return SharedSuggestionProvider.suggestResource(SUPPORTED_POST_CHAINS, builder); + } + + @Override + public Collection getExamples() { + return EXAMPLES; + } +} diff --git a/src/main/resources/assets/clientcommands/lang/en_us.json b/src/main/resources/assets/clientcommands/lang/en_us.json index 67ffbdb5..6e057a4b 100644 --- a/src/main/resources/assets/clientcommands/lang/en_us.json +++ b/src/main/resources/assets/clientcommands/lang/en_us.json @@ -226,6 +226,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.crelog.failed": "Failed to relog", "commands.crender.entities.success": "Entity rendering rules have been updated", diff --git a/src/main/resources/clientcommands.aw b/src/main/resources/clientcommands.aw index 23a2ec78..003c8e3e 100644 --- a/src/main/resources/clientcommands.aw +++ b/src/main/resources/clientcommands.aw @@ -41,6 +41,10 @@ accessible field net/minecraft/network/codec/IdDispatchCodec toId Lit/unimi/dsi/ # 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 + # cwaypoint accessible field net/minecraft/server/MinecraftServer storageSource Lnet/minecraft/world/level/storage/LevelStorageSource$LevelStorageAccess; accessible method net/minecraft/client/renderer/GameRenderer getFov (Lnet/minecraft/client/Camera;FZ)F