Fix #2237: Allow registering argument types without interacting with the class map (#2252)

* Fix #2237: Allow registering argument types without interacting with the class map

* Add testmod :)
This commit is contained in:
Technici4n 2022-06-07 20:44:12 +02:00 committed by GitHub
parent 59c610c9f3
commit e8d1ecd4c1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 240 additions and 1 deletions

View file

@ -0,0 +1,45 @@
/*
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.fabricmc.fabric.api.command.v2;
import com.mojang.brigadier.arguments.ArgumentType;
import net.minecraft.command.argument.serialize.ArgumentSerializer;
import net.minecraft.util.Identifier;
import net.minecraft.util.registry.Registry;
import net.fabricmc.fabric.mixin.command.ArgumentTypesAccessor;
public class ArgumentTypeRegistry {
/**
* Register a new argument type.
*
* @param id the identifier of the argument type
* @param clazz the class of the argument type
* @param serializer the serializer for the argument type
* @param <A> the argument type
* @param <T> the argument type properties
*/
public static <A extends ArgumentType<?>, T extends ArgumentSerializer.ArgumentTypeProperties<A>> void registerArgumentType(
Identifier id, Class<? extends A> clazz, ArgumentSerializer<A, T> serializer) {
ArgumentTypesAccessor.fabric_getClassMap().put(clazz, serializer);
Registry.register(Registry.COMMAND_ARGUMENT_TYPE, id, serializer);
}
private ArgumentTypeRegistry() {
}
}

View file

@ -0,0 +1,33 @@
/*
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.fabricmc.fabric.mixin.command;
import java.util.Map;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import net.minecraft.command.argument.ArgumentTypes;
import net.minecraft.command.argument.serialize.ArgumentSerializer;
@Mixin(ArgumentTypes.class)
public interface ArgumentTypesAccessor {
@Accessor("CLASS_MAP")
static Map<Class<?>, ArgumentSerializer<?, ?>> fabric_getClassMap() {
throw new AssertionError("");
}
}

View file

@ -3,6 +3,7 @@
"package": "net.fabricmc.fabric.mixin.command",
"compatibilityLevel": "JAVA_16",
"mixins": [
"ArgumentTypesAccessor",
"CommandManagerMixin",
"HelpCommandAccessor"
],

View file

@ -0,0 +1,60 @@
/*
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.fabricmc.fabric.test.command;
import static net.minecraft.server.command.CommandManager.argument;
import static net.minecraft.server.command.CommandManager.literal;
import com.mojang.brigadier.context.CommandContext;
import net.minecraft.command.argument.serialize.ConstantArgumentSerializer;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.command.v2.ArgumentTypeRegistry;
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
import net.fabricmc.fabric.test.command.argument.SmileyArgument;
import net.fabricmc.fabric.test.command.argument.SmileyArgumentType;
public class CustomArgumentTest implements ModInitializer {
private static final String ARG_NAME = "smiley_value";
@Override
public void onInitialize() {
ArgumentTypeRegistry.registerArgumentType(new Identifier("fabric-command-test", "smiley"), SmileyArgumentType.class, ConstantArgumentSerializer.of(SmileyArgumentType::smiley));
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
dispatcher.register(
literal("fabric_custom_argument_test").then(
argument(ARG_NAME, SmileyArgumentType.smiley())
.executes(CustomArgumentTest::executeSmileyCommand)));
});
}
private static int executeSmileyCommand(CommandContext<ServerCommandSource> context) {
SmileyArgument smiley = context.getArgument(ARG_NAME, SmileyArgument.class);
String feedback = switch (smiley) {
case SAD -> "Oh no, here is a heart: <3";
case HAPPY -> "Nice to see that you are having a good day :)";
};
context.getSource().sendFeedback(Text.literal(feedback), false);
return 1;
}
}

View file

@ -0,0 +1,28 @@
/*
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.fabricmc.fabric.test.command.argument;
public enum SmileyArgument {
HAPPY(":)"),
SAD(":(");
public final String smiley;
SmileyArgument(String smiley) {
this.smiley = smiley;
}
}

View file

@ -0,0 +1,71 @@
/*
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.fabricmc.fabric.test.command.argument;
import java.util.Arrays;
import java.util.Collection;
import java.util.concurrent.CompletableFuture;
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.command.CommandSource;
import net.minecraft.text.Text;
public class SmileyArgumentType implements ArgumentType<SmileyArgument> {
private static final Collection<String> SMILEY_VALUES = Arrays.stream(SmileyArgument.values()).map(s -> s.smiley).toList();
public static final DynamicCommandExceptionType INVALID_COLOR_EXCEPTION = new DynamicCommandExceptionType(smiley -> {
return Text.literal("Invalid smiley: " + smiley); // use Text.translatable in your mod!
});
public static SmileyArgumentType smiley() {
return new SmileyArgumentType();
}
@Override
public SmileyArgument parse(StringReader reader) throws CommandSyntaxException {
// Note: normally we would use reader.readUnquotedString(), but that won't allow : that we want for our smiley!
String string = "" + reader.read();
if (reader.canRead()) {
string += reader.read();
for (SmileyArgument possibleSmiley : SmileyArgument.values()) {
if (string.equals(possibleSmiley.smiley)) {
return possibleSmiley;
}
}
}
throw INVALID_COLOR_EXCEPTION.create(string);
}
@Override
public <S> CompletableFuture<Suggestions> listSuggestions(CommandContext<S> context, SuggestionsBuilder builder) {
return CommandSource.suggestMatching(SMILEY_VALUES, builder);
}
@Override
public Collection<String> getExamples() {
return SMILEY_VALUES;
}
}

View file

@ -10,7 +10,8 @@
},
"entrypoints": {
"main": [
"net.fabricmc.fabric.test.command.CommandTest"
"net.fabricmc.fabric.test.command.CommandTest",
"net.fabricmc.fabric.test.command.CustomArgumentTest"
],
"client": [
"net.fabricmc.fabric.test.command.client.ClientCommandTest"