001/* 002 * PermissionsEx 003 * Copyright (C) zml and PermissionsEx contributors 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package ca.stellardrift.permissionsex.minecraft.command; 018 019import ca.stellardrift.permissionsex.PermissionsEngine; 020import ca.stellardrift.permissionsex.minecraft.MinecraftPermissionsEx; 021import cloud.commandframework.Command; 022import cloud.commandframework.CommandManager; 023import org.checkerframework.checker.nullness.qual.Nullable; 024 025import java.util.ArrayDeque; 026import java.util.Arrays; 027import java.util.Deque; 028import java.util.function.Consumer; 029import java.util.function.Function; 030 031/** 032 * Context for executing command registrations 033 */ 034public final class CommandRegistrationContext { 035 private final String commandPrefix; 036 private final CommandManager<Commander> commandManager; 037 private final MinecraftPermissionsEx<?> manager; 038 private final Deque<Command.Builder<Commander>> builderStack = new ArrayDeque<>(); 039 040 public CommandRegistrationContext( 041 final String commandPrefix, 042 final MinecraftPermissionsEx<?> manager, 043 final CommandManager<Commander> commandManager) { 044 this.commandPrefix = commandPrefix; 045 this.manager = manager; 046 this.commandManager = commandManager; 047 } 048 049 public PermissionsEngine engine() { 050 return this.manager.engine(); 051 } 052 053 public MinecraftPermissionsEx<?> manager() { 054 return this.manager; 055 } 056 057 public String commandPrefix() { 058 return this.commandPrefix; 059 } 060 061 public CommandManager<Commander> commandManager() { 062 return this.commandManager; 063 } 064 065 /** 066 * Get the current command builder at the head of the command stack. 067 * 068 * @return the head of the stack 069 */ 070 public Command.Builder<Commander> head() { 071 final Command.@Nullable Builder<Commander> head = this.builderStack.peek(); 072 if (head == null) { 073 throw new IllegalStateException("Tried to peek command registration while stack was empty"); 074 } else { 075 return head; 076 } 077 } 078 079 public void push(final Command.Builder<Commander> builder, final Consumer<CommandRegistrationContext> handler) { 080 final int startSize = this.builderStack.size(); 081 this.builderStack.push(builder); 082 try { 083 handler.accept(this); 084 } finally { 085 this.builderStack.pop(); 086 if (this.builderStack.size() != startSize) { 087 throw new IllegalStateException("Command registration stack corruption detected while popping " + builder.build()); 088 } 089 } 090 } 091 092 public void push(final Consumer<CommandRegistrationContext> handler, final String primaryAlias, final String... aliases) { 093 push(this.head().literal(primaryAlias, aliases), handler); 094 } 095 096 /** 097 * Simple helper to register a subcommand of the PEX base command. 098 * 099 * @param maker a function that will add arguments to the PEX base command 100 * @param primaryAlias the primary alias for this subcommand 101 * @param aliases any other aliases 102 */ 103 public Command<Commander> register(final Function<Command.Builder<Commander>, Command.Builder<Commander>> maker, final String primaryAlias, final String... aliases) { 104 final Command.@Nullable Builder<Commander> headBuilder = this.builderStack.peek(); 105 if (headBuilder != null) { 106 return register(maker.apply(headBuilder.literal(primaryAlias, aliases))); 107 } else { 108 return register(maker.apply(absoluteBuilder(primaryAlias, aliases))); 109 } 110 } 111 112 /** 113 * Register a command with the manager. 114 * 115 * @param builder the builder to register 116 * @return the built command 117 */ 118 public Command<Commander> register(final Command.Builder<Commander> builder) { 119 final Command<Commander> built = builder.manager(this.commandManager).build(); 120 this.commandManager.command(built); 121 return built; 122 } 123 124 /** 125 * Create a new command builder at the root of the tree. 126 * 127 * @param primaryAlias the primary command alias 128 * @param aliases the aliases so tadd 129 * @return the builder 130 */ 131 public Command.Builder<Commander> absoluteBuilder(String primaryAlias, String... aliases) { 132 if (!this.commandPrefix.isEmpty()) { 133 primaryAlias = this.commandPrefix + primaryAlias; 134 aliases = Arrays.copyOf(aliases, aliases.length); 135 for (int i = 0, length = aliases.length; i < length; ++i) { 136 aliases[i] = this.commandPrefix + aliases[i]; 137 } 138 } 139 return this.commandManager.commandBuilder(primaryAlias, aliases); 140 } 141}