Skip to content

Commit

Permalink
add /taglist command
Browse files Browse the repository at this point in the history
  • Loading branch information
Treetrain1 committed Nov 22, 2023
1 parent 4a9135f commit 085b535
Show file tree
Hide file tree
Showing 5 changed files with 283 additions and 3 deletions.
19 changes: 16 additions & 3 deletions src/main/java/net/frozenblock/lib/FrozenMain.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,15 @@
import net.frozenblock.lib.screenshake.impl.ScreenShakeStorage;
import net.frozenblock.lib.sound.api.predicate.SoundPredicate;
import net.frozenblock.lib.spotting_icons.api.SpottingIconPredicate;
import net.frozenblock.lib.tag.api.TagKeyArgument;
import net.frozenblock.lib.tag.api.TagListCommand;
import net.frozenblock.lib.wind.api.WindManager;
import net.frozenblock.lib.wind.api.command.WindOverrideCommand;
import net.frozenblock.lib.wind.impl.WindStorage;
import net.frozenblock.lib.worldgen.feature.api.FrozenFeatures;
import net.frozenblock.lib.worldgen.feature.api.placementmodifier.FrozenPlacementModifiers;
import net.frozenblock.lib.worldgen.surface.impl.BiomeTagConditionSource;
import net.minecraft.commands.synchronization.ArgumentTypeInfos;
import net.minecraft.core.Registry;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceLocation;
Expand Down Expand Up @@ -76,9 +79,19 @@ public void onInitialize() {
}
});

CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> WindOverrideCommand.register(dispatcher));
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> ScreenShakeCommand.register(dispatcher));
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> ConfigCommand.register(dispatcher));
ArgumentTypeInfos.register(
BuiltInRegistries.COMMAND_ARGUMENT_TYPE,
string("tag_key"),
ArgumentTypeInfos.fixClassType(TagKeyArgument.class),
new TagKeyArgument.Info<>()
);

CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
WindOverrideCommand.register(dispatcher);
ScreenShakeCommand.register(dispatcher);
ConfigCommand.register(dispatcher);
TagListCommand.register(dispatcher);
});

if (FrozenLibConfig.get().wardenSpawnTrackerCommand)
CommandRegistrationCallback.EVENT.register(((dispatcher, registryAccess, environment) -> WardenSpawnTrackerCommand.register(dispatcher)));
Expand Down
116 changes: 116 additions & 0 deletions src/main/java/net/frozenblock/lib/tag/api/TagKeyArgument.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
package net.frozenblock.lib.tag.api;

import com.google.gson.JsonObject;
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.minecraft.commands.CommandBuildContext;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.SharedSuggestionProvider;
import net.minecraft.commands.synchronization.ArgumentTypeInfo;
import net.minecraft.core.Registry;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.TagKey;
import java.util.Arrays;
import java.util.Collection;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;

public class TagKeyArgument<T> implements ArgumentType<TagKeyArgument.Result<T>> {
private static final Collection<String> EXAMPLES = Arrays.asList("foo", "foo:bar", "012", "#skeletons", "#minecraft:skeletons");
final ResourceKey<? extends Registry<T>> registryKey;

public TagKeyArgument(ResourceKey<? extends Registry<T>> registryKey) {
this.registryKey = registryKey;
}

public static <T> TagKeyArgument<T> tagKey(ResourceKey<? extends Registry<T>> registryKey) {
return new TagKeyArgument<>(registryKey);
}

public static <T> TagKeyArgument.Result<T> getTagKey(
CommandContext<CommandSourceStack> context, String argument, ResourceKey<Registry<T>> registryKey, DynamicCommandExceptionType dynamicCommandExceptionType
) throws CommandSyntaxException {
TagKeyArgument.Result<?> result = context.getArgument(argument, TagKeyArgument.Result.class);
Optional<TagKeyArgument.Result<T>> optional = result.cast(registryKey);
return optional.orElseThrow(() -> dynamicCommandExceptionType.create(result));
}

public TagKeyArgument.Result<T> parse(StringReader reader) throws CommandSyntaxException {
int cursor = reader.getCursor();

try {
reader.skip();
ResourceLocation resourceLocation = ResourceLocation.read(reader);
return new Result<>(TagKey.create(this.registryKey, resourceLocation));
} catch (CommandSyntaxException var4) {
reader.setCursor(cursor);
throw var4;
}
}

@Override
public <S> CompletableFuture<Suggestions> listSuggestions(CommandContext<S> commandContext, SuggestionsBuilder suggestionsBuilder) {
Object var4 = commandContext.getSource();
return var4 instanceof SharedSuggestionProvider sharedSuggestionProvider
? sharedSuggestionProvider.suggestRegistryElements(this.registryKey, SharedSuggestionProvider.ElementSuggestionType.TAGS, suggestionsBuilder, commandContext)
: suggestionsBuilder.buildFuture();
}

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

public static class Info<T> implements ArgumentTypeInfo<TagKeyArgument<T>, TagKeyArgument.Info<T>.Template> {
public void serializeToNetwork(TagKeyArgument.Info<T>.Template template, FriendlyByteBuf buffer) {
buffer.writeResourceLocation(template.registryKey.location());
}

public TagKeyArgument.Info<T>.Template deserializeFromNetwork(FriendlyByteBuf buffer) {
ResourceLocation resourceLocation = buffer.readResourceLocation();
return new TagKeyArgument.Info.Template(ResourceKey.createRegistryKey(resourceLocation));
}

public void serializeToJson(TagKeyArgument.Info<T>.Template template, JsonObject json) {
json.addProperty("registry", template.registryKey.location().toString());
}

public TagKeyArgument.Info<T>.Template unpack(TagKeyArgument<T> argument) {
return new TagKeyArgument.Info.Template(argument.registryKey);
}

public final class Template implements ArgumentTypeInfo.Template<TagKeyArgument<T>> {
final ResourceKey<? extends Registry<T>> registryKey;

Template(ResourceKey<? extends Registry<T>> registryKey) {
this.registryKey = registryKey;
}

public TagKeyArgument<T> instantiate(CommandBuildContext context) {
return new TagKeyArgument<>(this.registryKey);
}

@Override
public ArgumentTypeInfo<TagKeyArgument<T>, ?> type() {
return TagKeyArgument.Info.this;
}
}
}

record Result<T>(TagKey<T> key) {
public <E> Optional<TagKeyArgument.Result<E>> cast(ResourceKey<? extends Registry<E>> registryKey) {
return this.key.cast(registryKey).map(Result::new);
}

public String asPrintable() {
return "#" + this.key.location();
}
}
}
144 changes: 144 additions & 0 deletions src/main/java/net/frozenblock/lib/tag/api/TagListCommand.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
package net.frozenblock.lib.tag.api;

import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.exceptions.DynamicCommandExceptionType;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
import net.minecraft.core.Holder;
import net.minecraft.core.HolderSet;
import net.minecraft.core.Registry;
import net.minecraft.core.registries.Registries;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceKey;

public class TagListCommand {
private TagListCommand() {}

private static final DynamicCommandExceptionType ERROR_TAG_INVALID = new DynamicCommandExceptionType(
type -> Component.translatable("commands.frozenlib.taglist.tag.invalid", type)
);

public static void register(CommandDispatcher<CommandSourceStack> dispatcher) {
dispatcher.register(
Commands.literal("taglist")
.requires(source -> source.hasPermission(2))
.then(
Commands.literal("biome")
.then(
Commands.argument("biome", TagKeyArgument.tagKey(Registries.BIOME))
.executes(
context -> list(
context.getSource(),
Registries.BIOME,
TagKeyArgument.getTagKey(context, "biome", Registries.BIOME, ERROR_TAG_INVALID)
)
)
)
)
.then(
Commands.literal("block")
.then(
Commands.argument("block", TagKeyArgument.tagKey(Registries.BLOCK))
.executes(
context -> list(
context.getSource(),
Registries.BLOCK,
TagKeyArgument.getTagKey(context, "block", Registries.BLOCK, ERROR_TAG_INVALID)
)
)
)
)
.then(
Commands.literal("entity_type")
.then(
Commands.argument("entity_type", TagKeyArgument.tagKey(Registries.ENTITY_TYPE))
.executes(
context -> list(
context.getSource(),
Registries.ENTITY_TYPE,
TagKeyArgument.getTagKey(context, "entity_type", Registries.ENTITY_TYPE, ERROR_TAG_INVALID)
)
)
)
)
.then(
Commands.literal("fluid")
.then(
Commands.argument("fluid", TagKeyArgument.tagKey(Registries.FLUID))
.executes(
context -> list(
context.getSource(),
Registries.FLUID,
TagKeyArgument.getTagKey(context, "fluid", Registries.FLUID, ERROR_TAG_INVALID)
)
)
)
)
.then(
Commands.literal("instrument")
.then(
Commands.argument("instrument", TagKeyArgument.tagKey(Registries.INSTRUMENT))
.executes(
context -> list(
context.getSource(),
Registries.INSTRUMENT,
TagKeyArgument.getTagKey(context, "instrument", Registries.INSTRUMENT, ERROR_TAG_INVALID)
)
)
)
)
.then(
Commands.literal("item")
.then(
Commands.argument("item", TagKeyArgument.tagKey(Registries.ITEM))
.executes(
context -> list(
context.getSource(),
Registries.ITEM,
TagKeyArgument.getTagKey(context, "item", Registries.ITEM, ERROR_TAG_INVALID)
)
)
)
)
.then(
Commands.literal("structure")
.then(
Commands.argument("structure", TagKeyArgument.tagKey(Registries.STRUCTURE))
.executes(
context -> list(
context.getSource(),
Registries.STRUCTURE,
TagKeyArgument.getTagKey(context, "structure", Registries.STRUCTURE, ERROR_TAG_INVALID)
)
)
)
)
);
}

private static <T> int list(CommandSourceStack source, ResourceKey<Registry<T>> registryKey, TagKeyArgument.Result<T> tag) throws CommandSyntaxException {
Registry<T> registry = source.getLevel().registryAccess().registryOrThrow(registryKey);
String printable = tag.asPrintable();
HolderSet.Named<T> holderSet = registry.getTag(tag.key()).orElseThrow(
() -> ERROR_TAG_INVALID.create(printable)
);
int size = holderSet.size();

for (Holder<T> value : holderSet) {
if (holderSet.contains(value)) {
source.sendSuccess(
() -> Component.literal(
value.unwrapKey().orElseThrow().location().toString()
),
true
);
}
}
source.sendSuccess(
() -> Component.translatable("commands.frozenlib.taglist.footer", size, printable),
true
);
return size;
}
}
3 changes: 3 additions & 0 deletions src/main/resources/assets/frozenlib/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@
"commands.frozenlib_config.reload.single": "Reloaded 1 config from %s.",
"commands.frozenlib_config.reload.multiple": "Reloaded %s configs from %s.",

"commands.frozenlib.taglist.footer": "Listed %s tags in %s.",
"commands.frozenlib.taglist.tag.invalid": "Invalid tag: %s",

"commands.warden_spawn_tracker.clear.success.multiple": "Cleared warden spawn warnings from %s players",
"commands.warden_spawn_tracker.clear.success.single": "Cleared warden spawn warnings from %s",
"commands.warden_spawn_tracker.set.success.multiple": "Set warden spawn warning %s to %s players",
Expand Down
4 changes: 4 additions & 0 deletions src/main/resources/frozenlib.accesswidener
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ transitive-accessible field net/minecraft/advancements/critereon/EffectsChangedT
transitive-accessible field net/minecraft/advancements/critereon/MobEffectsPredicate effectMap Ljava/util/Map;
transitive-mutable field net/minecraft/advancements/critereon/MobEffectsPredicate effectMap Ljava/util/Map;

# Command
transitive-accessible method net/minecraft/commands/synchronization/ArgumentTypeInfos register (Lnet/minecraft/core/Registry;Ljava/lang/String;Ljava/lang/Class;Lnet/minecraft/commands/synchronization/ArgumentTypeInfo;)Lnet/minecraft/commands/synchronization/ArgumentTypeInfo;
transitive-accessible method net/minecraft/commands/synchronization/ArgumentTypeInfos fixClassType (Ljava/lang/Class;)Ljava/lang/Class;

# Recipe
transitive-accessible method net/minecraft/world/item/crafting/Ingredient$ItemValue <init> (Lnet/minecraft/world/item/ItemStack;)V
transitive-accessible field net/minecraft/world/item/crafting/CraftingRecipeCodecs ITEMSTACK_NONAIR_CODEC Lcom/mojang/serialization/Codec;
Expand Down

0 comments on commit 085b535

Please sign in to comment.