Jump to content

Recommended Posts

Posted

So I am building a rank system for forge servers. Very basic as of right now. When the player joins the server it automatically serializes the arguments required for /ranks so suggestions do work. However if and admin creates a new rank, the rank wont be suggested till the player disconnects and rejoins(retrieves new serialized arguments).  Is there a way I can force the reserialization of ArgumentTypes to send to clients?

Example: Look at the images attached! First two images are on the first connection. I had to leave and rejoin to get the suggestion to work for the third image.

/ranks command:


	@Override
	protected void initCommand() {
		command = Commands.literal("ranks").requires(
				(commandContext) -> {return commandContext.hasPermission(3);}
				).then(join()).then(create()).then(delete()).then(modify());
	}
	
	private LiteralArgumentBuilder<CommandSourceStack> join(){
		return Commands.literal("join").then(Commands.argument("player", EntityArgument.player()).then(Commands.argument("rank", IterableArgumentType.choices(ModStatics.rankManager.getAvaliableRanks())).executes(
				(commandContext) -> { return joinRank(commandContext);}
				)));
	}

	private LiteralArgumentBuilder<CommandSourceStack> create(){
		return Commands.literal("create").then(Commands.argument("name", MessageArgument.message()).executes(
				(commandContext) -> { return createRank(commandContext);}
				));
	}
	
	private LiteralArgumentBuilder<CommandSourceStack> delete(){
		return Commands.literal("delete").then(Commands.argument("rank", IterableArgumentType.choices(ModStatics.rankManager.getAvaliableRanks())).executes(
				(commandContext) -> { return deleteRank(commandContext);}
				));
	}
	
	private LiteralArgumentBuilder<CommandSourceStack> modify(){
		return Commands.literal("modify").then(Commands.argument("rank", IterableArgumentType.choices(ModStatics.rankManager.getAvaliableRanks()))
				.then(modifySetColor())
				.then(modifySetColoredChat())
				.then(modifyAddCommand())
				.then(modifyRemoveCommand()));
	}
	
	private LiteralArgumentBuilder<CommandSourceStack> modifySetColor(){
		return Commands.literal("setColor").then(Commands.argument("color", ColorArgument.color()).executes(
				(commandContext) -> {return setColor(commandContext);}
				));
	}
	
	private LiteralArgumentBuilder<CommandSourceStack> modifySetColoredChat(){
		return Commands.literal("setColoredChat")
				.then(Commands.literal("true").executes(
				(commandContext) -> {return setColoredChat(commandContext,true);}
				))
				.then(Commands.literal("false").executes(
						(commandContext) -> {return setColoredChat(commandContext, false);}
				));
	}
	
	private LiteralArgumentBuilder<CommandSourceStack> modifyAddCommand(){
		return Commands.literal("addCommand").then(Commands.argument("command", IterableArgumentType.choices(ModStatics.modCommandList.getAvaliable())).executes(
				(commandContext) -> {return addCommand(commandContext);}
				));
	}
	
	private LiteralArgumentBuilder<CommandSourceStack> modifyRemoveCommand(){
		return Commands.literal("removeCommand").then(Commands.argument("command", IterableArgumentType.choices(ModStatics.modCommandList.getAvaliable())).executes(
				(commandContext) -> {return removeCommand(commandContext);}
				));
	}
	
	private int joinRank(CommandContext<CommandSourceStack> commandContext) throws CommandSyntaxException {
		String name = IterableArgumentType.getChoice(commandContext, "rank");
		Player player = EntityArgument.getPlayer(commandContext, "player");
		System.out.println(player.getUUID().toString() + " : " + name);
		if(ModStatics.rankManager.joinRank(player.getUUID(), name)) {
			commandContext.getSource().sendSuccess(new TextComponent("Joined rank ["+name+"] !"),true);
		}else {
			commandContext.getSource().sendFailure(new TextComponent("Failed to join rank ["+name+"] !"));
		}
		return 1;
	}
	
	private static int createRank(CommandContext<CommandSourceStack> commandContext) throws CommandSyntaxException {
		Component message = MessageArgument.getMessage(commandContext, "name");
		String name = message.getContents();
		if(ModStatics.rankManager.createRank(name)) {
			commandContext.getSource().sendSuccess(new TextComponent("Created rank ["+name+"] !"),true);
		}else {
			commandContext.getSource().sendFailure(new TextComponent("Failed to create rank ["+name+"] !"));
		}
		return 1;
	}
	
	private static int deleteRank(CommandContext<CommandSourceStack> commandContext) {
		String name = IterableArgumentType.getChoice(commandContext, "rank");
		if(ModStatics.rankManager.deleteRank(name)) {
			commandContext.getSource().sendSuccess(new TextComponent("Deleted rank ["+name+"] !"),true);
		}else {
			commandContext.getSource().sendFailure(new TextComponent("Failed to delete rank ["+name+"] !"));
		}
		return 1;
	}
	
	private static int addCommand(CommandContext<CommandSourceStack> commandContext) {
		String name = IterableArgumentType.getChoice(commandContext, "rank");
		String literal = IterableArgumentType.getChoice(commandContext, "command");
		
		if(ModStatics.rankManager.addCommandToRank(name, literal)) {
			commandContext.getSource().sendSuccess(new TextComponent("Added command /"+literal+" to rank ["+name+"] !"),true);
		}else {
			commandContext.getSource().sendFailure(new TextComponent("Failed to add command /"+literal+" to rank ["+name+"] !"));
		}
		
		return 1;
	}
	
	private static int removeCommand(CommandContext<CommandSourceStack> commandContext) {
		String name = IterableArgumentType.getChoice(commandContext, "rank");
		String literal = IterableArgumentType.getChoice(commandContext, "command");
		
		if(ModStatics.rankManager.removeCommandFromRank(name, literal)) {
			commandContext.getSource().sendSuccess(new TextComponent("Removed command "+literal+" to rank ["+name+"] !"),true);
		}else {
			commandContext.getSource().sendFailure(new TextComponent("Failed to removed command "+literal+" from rank ["+name+"] !"));
		}
		
		return 1;
	}
	
	private static int setColor(CommandContext<CommandSourceStack> commandContext) {
		String name = IterableArgumentType.getChoice(commandContext, "rank");
		ChatFormatting formatting = ColorArgument.getColor(commandContext, "color");
		if(ModStatics.rankManager.getRank(name).setColor(formatting)) {
			commandContext.getSource().sendSuccess(new TextComponent("Updated rank color!"),true);
		}else {
			commandContext.getSource().sendFailure(new TextComponent("Failed to update rank color!"));
		}
		return 1;
	}
	
	private static int setColoredChat(CommandContext<CommandSourceStack> commandContext, boolean b) {
		String name = IterableArgumentType.getChoice(commandContext, "rank");
		
		if(ModStatics.rankManager.setRankColoredChat(name, b)) {
			commandContext.getSource().sendSuccess(new TextComponent("Updated rank canColoredChat!"),true);
		}else {
			commandContext.getSource().sendFailure(new TextComponent("Failed to update rank canColoredChat!"));
		}
		return 1;
	}

IterableArgumentType:

private Iterable<String> choices;
	
	private IterableArgumentType(Iterable<String> choices) {	
		this.choices = choices;
	}
	
	public static IterableArgumentType choices(Iterable<String> choices) {
		return new IterableArgumentType(choices);
	}
	
	public static String getChoice(CommandContext<CommandSourceStack> commandContext, String name) {
	      return commandContext.getArgument(name, String.class);
	}
	
	@Override
	public String parse(StringReader reader) throws CommandSyntaxException {
		String string = reader.readString();
		return string;
	}

	public <S> CompletableFuture<Suggestions> listSuggestions(CommandContext<S> commandContext, SuggestionsBuilder suggestionBuilder) {
		return SharedSuggestionProvider.suggest(choices, suggestionBuilder);
	}
	
	public Iterable<String> getChoices(){
		return choices;
	}
	
	public static class Serializer implements ArgumentSerializer<IterableArgumentType>{
		
		private String delimiter = "-";
		
		public String convertToString(Iterable<String> choices) {
			StringBuilder builder = new StringBuilder();
			
			ArrayList<String> array_choices = new ArrayList<String>();
			for(String choice : choices) {
				array_choices.add(choice);
			}
			for(int i = 0; i < array_choices.size(); i++) {
				builder.append(array_choices.get(i));
				if(i != array_choices.size()-1) {
					builder.append(delimiter);
				}
			}
			
			return builder.toString();
		}
		
		public Iterable<String> convertToIterable(String choices){
			String[] array_choices = choices.split(delimiter);
			
			Hashtable<String, Byte> hashtable_choices = new Hashtable<String, Byte>();
			for(String choice : array_choices) {
				hashtable_choices.put(choice, (byte) 0);
			}
			
			return hashtable_choices.keySet();
		}
		
        @Override
        public void serializeToNetwork(IterableArgumentType argument, FriendlyByteBuf buffer)
        {
            buffer.writeUtf(convertToString(argument.getChoices()));
        }

        @Override
        public IterableArgumentType deserializeFromNetwork(FriendlyByteBuf buffer)
        {
            String utf = buffer.readUtf();
			return new IterableArgumentType(convertToIterable(utf));
        }

        @Override
        public void serializeToJson(IterableArgumentType argument, JsonObject json)
        {
            json.addProperty("iterableargumenttype", convertToString(argument.getChoices()));
        }
    }

 

Capture1.PNG

Capture2.PNG

Capture3.PNG

Posted
58 minutes ago, diesieben07 said:

I would store the ranks separately and sync them in a separate packet. Then you can just reference that separately stored "thing" from your argument type. Otherwise you'd have to resend the entire command tree.

I found a solution! I modified the /ranks command to use a custom StringArgument. StringArgument is empty and wont have any suggestions. Then I follow up this Commands.argument with a .suggest() that calls a function  to return uptodate suggestions.

Did not have to mess with packets at all!

This is new code incase anyone in the future needs this!

Command /ranks:

public class RankCommands extends ModCommand{

	@Override
	protected void initCommand() {
		command = Commands.literal("ranks").requires(
				(commandContext) -> {return commandContext.hasPermission(3);}
				).then(join()).then(create()).then(delete()).then(modify());
	}
	
	private LiteralArgumentBuilder<CommandSourceStack> join(){
		return Commands.literal("join").then(Commands.argument("player", EntityArgument.player()).then(Commands.argument("rank", StringArgument.string()).suggests(CustomSuggestionProvider::getRankSuggestions).executes(
				(commandContext) -> { return joinRank(commandContext);}
				)));
	}

	private LiteralArgumentBuilder<CommandSourceStack> create(){
		return Commands.literal("create").then(Commands.argument("name", StringArgument.string()).executes(
				(commandContext) -> { return createRank(commandContext);}
				));
	}
	
	private LiteralArgumentBuilder<CommandSourceStack> delete(){
		return Commands.literal("delete").then(Commands.argument("rank", StringArgument.string()).suggests(CustomSuggestionProvider::getRankSuggestions).executes(
				(commandContext) -> { return deleteRank(commandContext);}
				));
	}
	
	private LiteralArgumentBuilder<CommandSourceStack> modify(){
		return Commands.literal("modify").then(Commands.argument("rank", StringArgument.string()).suggests(CustomSuggestionProvider::getRankSuggestions)
				.then(modifySetColor())
				.then(modifySetColoredChat())
				.then(modifyAddCommand())
				.then(modifyRemoveCommand()));
	}
	
	private LiteralArgumentBuilder<CommandSourceStack> modifySetColor(){
		return Commands.literal("setColor").then(Commands.argument("color", ColorArgument.color()).executes(
				(commandContext) -> {return setColor(commandContext);}
				));
	}
	
	private LiteralArgumentBuilder<CommandSourceStack> modifySetColoredChat(){
		return Commands.literal("setColoredChat")
				.then(Commands.literal("true").executes(
				(commandContext) -> {return setColoredChat(commandContext,true);}
				))
				.then(Commands.literal("false").executes(
						(commandContext) -> {return setColoredChat(commandContext, false);}
				));
	}
	
	private LiteralArgumentBuilder<CommandSourceStack> modifyAddCommand(){
		return Commands.literal("addCommand").then(Commands.argument("command", StringArgument.string()).suggests(CustomSuggestionProvider::getCommandSuggestions).executes(
				(commandContext) -> {return addCommand(commandContext);}
				));
	}
	
	private LiteralArgumentBuilder<CommandSourceStack> modifyRemoveCommand(){
		return Commands.literal("removeCommand").then(Commands.argument("command", StringArgument.string()).suggests(CustomSuggestionProvider::getCommandSuggestions).executes(
				(commandContext) -> {return removeCommand(commandContext);}
				));
	}
	
	private int joinRank(CommandContext<CommandSourceStack> commandContext) throws CommandSyntaxException {
		String name = StringArgument.getString(commandContext, "rank");
		Player player = EntityArgument.getPlayer(commandContext, "player");
		if(ModStatics.rankManager.joinRank(player.getUUID(), name)) {
			commandContext.getSource().sendSuccess(new TextComponent("Joined rank ["+name+"] !"),true);
		}else {
			commandContext.getSource().sendFailure(new TextComponent("Failed to join rank ["+name+"] !"));
		}
		return 1;
	}
	
	private static int createRank(CommandContext<CommandSourceStack> commandContext) throws CommandSyntaxException {
		String name = StringArgument.getString(commandContext, "name");
		if(ModStatics.rankManager.createRank(name)) {
			commandContext.getSource().sendSuccess(new TextComponent("Created rank ["+name+"] !"),true);
		}else {
			commandContext.getSource().sendFailure(new TextComponent("Failed to create rank ["+name+"] !"));
		}
		return 1;
	}
	
	private static int deleteRank(CommandContext<CommandSourceStack> commandContext) {
		String name = StringArgument.getString(commandContext, "rank");
		if(ModStatics.rankManager.deleteRank(name)) {
			commandContext.getSource().sendSuccess(new TextComponent("Deleted rank ["+name+"] !"),true);
		}else {
			commandContext.getSource().sendFailure(new TextComponent("Failed to delete rank ["+name+"] !"));
		}
		return 1;
	}
	
	private static int addCommand(CommandContext<CommandSourceStack> commandContext) {
		String name = StringArgument.getString(commandContext, "rank");
		String literal = StringArgument.getString(commandContext, "command");
		
		if(ModStatics.rankManager.addCommandToRank(name, literal)) {
			commandContext.getSource().sendSuccess(new TextComponent("Added command /"+literal+" to rank ["+name+"] !"),true);
		}else {
			commandContext.getSource().sendFailure(new TextComponent("Failed to add command /"+literal+" to rank ["+name+"] !"));
		}
		
		return 1;
	}
	
	private static int removeCommand(CommandContext<CommandSourceStack> commandContext) {
		String name = StringArgument.getString(commandContext, "rank");
		String literal = StringArgument.getString(commandContext, "command");
		
		if(ModStatics.rankManager.removeCommandFromRank(name, literal)) {
			commandContext.getSource().sendSuccess(new TextComponent("Removed command "+literal+" to rank ["+name+"] !"),true);
		}else {
			commandContext.getSource().sendFailure(new TextComponent("Failed to removed command "+literal+" from rank ["+name+"] !"));
		}
		
		return 1;
	}
	
	private static int setColor(CommandContext<CommandSourceStack> commandContext) {
		String name = StringArgument.getString(commandContext, "rank");
		ChatFormatting formatting = ColorArgument.getColor(commandContext, "color");
		if(ModStatics.rankManager.getRank(name).setColor(formatting)) {
			commandContext.getSource().sendSuccess(new TextComponent("Updated rank color!"),true);
		}else {
			commandContext.getSource().sendFailure(new TextComponent("Failed to update rank color!"));
		}
		return 1;
	}
	
	private static int setColoredChat(CommandContext<CommandSourceStack> commandContext, boolean b) {
		String name = StringArgument.getString(commandContext, "rank");
		
		if(ModStatics.rankManager.setRankColoredChat(name, b)) {
			commandContext.getSource().sendSuccess(new TextComponent("Updated rank canColoredChat!"),true);
		}else {
			commandContext.getSource().sendFailure(new TextComponent("Failed to update rank canColoredChat!"));
		}
		return 1;
	}

}

StringArgument:

public class StringArgument implements ArgumentType<String>{

	private StringArgument() {
		
	}
	
	public static StringArgument string() {
		return new StringArgument();
	}
	
	public static String getString(CommandContext<CommandSourceStack> commandContext, String name) {
	      return commandContext.getArgument(name, String.class);
	}
	
	@Override
	public String parse(StringReader reader) throws CommandSyntaxException {
		String string = reader.readString();
		return string;
	}
	
	public static class Serializer implements ArgumentSerializer<StringArgument>{

        @Override
        public StringArgument deserializeFromNetwork(FriendlyByteBuf buffer)
        {
			return new StringArgument();
        }

		@Override
		public void serializeToNetwork(StringArgument p_121579_, FriendlyByteBuf p_121580_) {

		}

		@Override
		public void serializeToJson(StringArgument p_121577_, JsonObject p_121578_) {

		}
    }

}

CustomSuggestionProvider:

public class CustomSuggestionProvider{
	
	public static CompletableFuture getRankSuggestions(CommandContext context, SuggestionsBuilder builder)throws CommandSyntaxException {
		Iterable<String> choices = ModStatics.rankManager.getAvaliableRanks();
		for(String choice : choices) {
			builder.suggest(choice);
		}
		return builder.buildFuture();
	}
	
	public static CompletableFuture getCommandSuggestions(CommandContext context, SuggestionsBuilder builder)throws CommandSyntaxException {
		Iterable<String> choices = ModStatics.modCommandList.getAvaliable();
		for(String choice : choices) {
			builder.suggest(choice);
		}
		return builder.buildFuture();
	}

}

Also don't forget to registry the custom argument type:

ArgumentTypes.register("se:stringargument", StringArgument.class, new StringArgument.Serializer());

 

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.