From f69745e1c1df8decb097d83b94cd3117dc5ca477 Mon Sep 17 00:00:00 2001
From: phinner <62483793+phinner@users.noreply.github.com>
Date: Mon, 8 Apr 2024 17:29:19 +0200
Subject: [PATCH] feat: Add lamp in the available command APIs
---
.../distributor.base-conventions.gradle.kts | 4 +
distributor-command-lamp/build.gradle.kts | 13 ++
.../command/lamp/LampCommandFacade.java | 130 +++++++++++++++++
.../distributor/command/lamp/LampElement.java | 96 +++++++++++++
.../command/lamp/MindustryCommandActor.java | 27 ++++
.../lamp/MindustryCommandActorImpl.java | 75 ++++++++++
.../command/lamp/MindustryCommandHandler.java | 37 +++++
.../lamp/MindustryCommandHandlerImpl.java | 133 ++++++++++++++++++
.../command/lamp/package-info.java | 4 +
gradle/libs.versions.toml | 4 +
settings.gradle.kts | 1 +
11 files changed, 524 insertions(+)
create mode 100644 distributor-command-lamp/build.gradle.kts
create mode 100644 distributor-command-lamp/src/main/java/com/xpdustry/distributor/command/lamp/LampCommandFacade.java
create mode 100644 distributor-command-lamp/src/main/java/com/xpdustry/distributor/command/lamp/LampElement.java
create mode 100644 distributor-command-lamp/src/main/java/com/xpdustry/distributor/command/lamp/MindustryCommandActor.java
create mode 100644 distributor-command-lamp/src/main/java/com/xpdustry/distributor/command/lamp/MindustryCommandActorImpl.java
create mode 100644 distributor-command-lamp/src/main/java/com/xpdustry/distributor/command/lamp/MindustryCommandHandler.java
create mode 100644 distributor-command-lamp/src/main/java/com/xpdustry/distributor/command/lamp/MindustryCommandHandlerImpl.java
create mode 100644 distributor-command-lamp/src/main/java/com/xpdustry/distributor/command/lamp/package-info.java
diff --git a/distributor-build-logic/src/main/kotlin/distributor.base-conventions.gradle.kts b/distributor-build-logic/src/main/kotlin/distributor.base-conventions.gradle.kts
index c4ab2183..30f41445 100644
--- a/distributor-build-logic/src/main/kotlin/distributor.base-conventions.gradle.kts
+++ b/distributor-build-logic/src/main/kotlin/distributor.base-conventions.gradle.kts
@@ -18,6 +18,10 @@ repositories {
name = "xpdustry-mindustry"
mavenContent { releasesOnly() }
}
+ maven("https://jitpack.io") {
+ name = "jitpack"
+ mavenContent { releasesOnly() }
+ }
}
dependencies {
diff --git a/distributor-command-lamp/build.gradle.kts b/distributor-command-lamp/build.gradle.kts
new file mode 100644
index 00000000..7dc5307e
--- /dev/null
+++ b/distributor-command-lamp/build.gradle.kts
@@ -0,0 +1,13 @@
+plugins {
+ id("distributor.base-conventions")
+ id("distributor.publish-conventions")
+}
+
+dependencies {
+ api(libs.lamp.common)
+ compileOnlyApi(projects.distributorCommonApi)
+ compileOnlyApi(libs.bundles.mindustry)
+ compileOnlyApi(libs.immutables.annotations)
+ compileOnly(libs.jetbrains.annotations)
+ annotationProcessor(libs.immutables.processor)
+}
diff --git a/distributor-command-lamp/src/main/java/com/xpdustry/distributor/command/lamp/LampCommandFacade.java b/distributor-command-lamp/src/main/java/com/xpdustry/distributor/command/lamp/LampCommandFacade.java
new file mode 100644
index 00000000..676da51b
--- /dev/null
+++ b/distributor-command-lamp/src/main/java/com/xpdustry/distributor/command/lamp/LampCommandFacade.java
@@ -0,0 +1,130 @@
+/*
+ * Distributor, a feature-rich framework for Mindustry plugins.
+ *
+ * Copyright (C) 2024 Xpdustry
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package com.xpdustry.distributor.command.lamp;
+
+import arc.util.CommandHandler;
+import com.xpdustry.distributor.command.CommandFacade;
+import com.xpdustry.distributor.command.CommandHelp;
+import com.xpdustry.distributor.command.CommandSender;
+import com.xpdustry.distributor.command.DescriptionFacade;
+import com.xpdustry.distributor.plugin.MindustryPlugin;
+import java.util.Map;
+import mindustry.gen.Player;
+import org.jspecify.annotations.Nullable;
+import revxrsal.commands.core.CommandPath;
+
+final class LampCommandFacade extends CommandHandler.Command implements CommandFacade {
+
+ final MindustryCommandHandler handler;
+ private final String name;
+ private final DescriptionFacade description;
+ private final boolean alias;
+ private final boolean prefixed;
+
+ LampCommandFacade(
+ final MindustryCommandHandler handler,
+ final String name,
+ final DescriptionFacade description,
+ final boolean alias,
+ final boolean prefixed) {
+ super(
+ prefixed ? handler.getPlugin().getMetadata().getName() + ":" + name : name,
+ "[args...]",
+ description.getText(),
+ new LampCommandRunner(name, handler));
+ this.handler = handler;
+ this.name = name;
+ this.description = description;
+ this.alias = alias;
+ this.prefixed = prefixed;
+ }
+
+ @Override
+ public String getRealName() {
+ return this.name;
+ }
+
+ @Override
+ public String getName() {
+ return this.text;
+ }
+
+ @Override
+ public DescriptionFacade getDescription() {
+ return this.description;
+ }
+
+ @Override
+ public boolean isAlias() {
+ return this.alias;
+ }
+
+ @Override
+ public boolean isPrefixed() {
+ return this.prefixed;
+ }
+
+ @Override
+ public boolean isVisible(final CommandSender sender) {
+ final var actor = this.handler.wrap(sender);
+ final var root = CommandPath.get(this.name);
+ return this.handler.getCommands().entrySet().stream()
+ .filter(entry -> entry.getKey().isChildOf(root))
+ .map(Map.Entry::getValue)
+ .anyMatch(command -> command.hasPermission(actor));
+ }
+
+ @Override
+ public CommandHelp getHelp(final CommandSender sender, final String query) {
+ return CommandHelp.Empty.getInstance();
+ }
+
+ @Override
+ public MindustryPlugin getPlugin() {
+ return this.handler.getPlugin();
+ }
+
+ @SuppressWarnings("ClassCanBeRecord")
+ private static class LampCommandRunner implements CommandHandler.CommandRunner {
+
+ private final String name;
+ private final MindustryCommandHandler handler;
+
+ private LampCommandRunner(final String name, final MindustryCommandHandler handler) {
+ this.name = name;
+ this.handler = handler;
+ }
+
+ @Override
+ public void accept(final String[] args, final @Nullable Player player) {
+ final var actor = this.handler.wrap(player != null ? CommandSender.player(player) : CommandSender.server());
+
+ final var input = new StringBuilder(this.name);
+ for (final var arg : args) {
+ input.append(' ').append(arg);
+ }
+
+ try {
+ this.handler.dispatch(actor, input.toString());
+ } catch (final Throwable throwable) {
+ this.handler.getExceptionHandler().handleException(throwable, actor);
+ }
+ }
+ }
+}
diff --git a/distributor-command-lamp/src/main/java/com/xpdustry/distributor/command/lamp/LampElement.java b/distributor-command-lamp/src/main/java/com/xpdustry/distributor/command/lamp/LampElement.java
new file mode 100644
index 00000000..555db856
--- /dev/null
+++ b/distributor-command-lamp/src/main/java/com/xpdustry/distributor/command/lamp/LampElement.java
@@ -0,0 +1,96 @@
+/*
+ * Distributor, a feature-rich framework for Mindustry plugins.
+ *
+ * Copyright (C) 2024 Xpdustry
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package com.xpdustry.distributor.command.lamp;
+
+import com.xpdustry.distributor.internal.DistributorDataClass;
+import java.util.Objects;
+import org.immutables.value.Value;
+import revxrsal.commands.command.CommandCategory;
+import revxrsal.commands.command.CommandParameter;
+import revxrsal.commands.command.ExecutableCommand;
+
+public sealed interface LampElement {
+
+ String getName();
+
+ String getDescription();
+
+ @DistributorDataClass
+ @Value.Immutable
+ sealed interface Category extends LampElement permits CategoryImpl {
+
+ static Category of(final CommandCategory category) {
+ return CategoryImpl.of(category);
+ }
+
+ CommandCategory getCategory();
+
+ @Override
+ default String getName() {
+ return getCategory().getName();
+ }
+
+ @Override
+ default String getDescription() {
+ return "";
+ }
+ }
+
+ @DistributorDataClass
+ @Value.Immutable
+ sealed interface Command extends LampElement permits CommandImpl {
+
+ static Command of(final ExecutableCommand command) {
+ return CommandImpl.of(command);
+ }
+
+ ExecutableCommand getCommand();
+
+ @Override
+ default String getName() {
+ return getCommand().getName();
+ }
+
+ @Override
+ default String getDescription() {
+ return Objects.requireNonNullElse(getCommand().getDescription(), "");
+ }
+ }
+
+ @DistributorDataClass
+ @Value.Immutable
+ sealed interface Parameter extends LampElement permits ParameterImpl {
+
+ static Parameter of(final CommandParameter parameter) {
+ return ParameterImpl.of(parameter);
+ }
+
+ CommandParameter getParameter();
+
+ @Override
+ default String getName() {
+ return getParameter().getName();
+ }
+
+ @Override
+ default String getDescription() {
+ return Objects.requireNonNullElse(getParameter().getDescription(), "");
+ }
+ }
+}
diff --git a/distributor-command-lamp/src/main/java/com/xpdustry/distributor/command/lamp/MindustryCommandActor.java b/distributor-command-lamp/src/main/java/com/xpdustry/distributor/command/lamp/MindustryCommandActor.java
new file mode 100644
index 00000000..83bd40d2
--- /dev/null
+++ b/distributor-command-lamp/src/main/java/com/xpdustry/distributor/command/lamp/MindustryCommandActor.java
@@ -0,0 +1,27 @@
+/*
+ * Distributor, a feature-rich framework for Mindustry plugins.
+ *
+ * Copyright (C) 2024 Xpdustry
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package com.xpdustry.distributor.command.lamp;
+
+import com.xpdustry.distributor.command.CommandSender;
+import revxrsal.commands.command.CommandActor;
+
+public interface MindustryCommandActor extends CommandActor {
+
+ CommandSender getCommandSender();
+}
diff --git a/distributor-command-lamp/src/main/java/com/xpdustry/distributor/command/lamp/MindustryCommandActorImpl.java b/distributor-command-lamp/src/main/java/com/xpdustry/distributor/command/lamp/MindustryCommandActorImpl.java
new file mode 100644
index 00000000..3d62c38a
--- /dev/null
+++ b/distributor-command-lamp/src/main/java/com/xpdustry/distributor/command/lamp/MindustryCommandActorImpl.java
@@ -0,0 +1,75 @@
+/*
+ * Distributor, a feature-rich framework for Mindustry plugins.
+ *
+ * Copyright (C) 2024 Xpdustry
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package com.xpdustry.distributor.command.lamp;
+
+import com.xpdustry.distributor.command.CommandSender;
+import com.xpdustry.distributor.player.MUUID;
+import java.util.Locale;
+import java.util.UUID;
+import revxrsal.commands.CommandHandler;
+
+final class MindustryCommandActorImpl implements MindustryCommandActor {
+
+ private static final UUID CONSOLE_UUID = new UUID(0, 0);
+
+ private final MindustryCommandHandler handler;
+ private final CommandSender sender;
+
+ MindustryCommandActorImpl(final MindustryCommandHandler handler, final CommandSender sender) {
+ this.handler = handler;
+ this.sender = sender;
+ }
+
+ @Override
+ public CommandSender getCommandSender() {
+ return this.sender;
+ }
+
+ @Override
+ public String getName() {
+ return this.sender.getName();
+ }
+
+ @Override
+ public UUID getUniqueId() {
+ return this.sender.isServer()
+ ? CONSOLE_UUID
+ : MUUID.from(this.sender.getPlayer()).toRealUUID();
+ }
+
+ @Override
+ public void reply(final String message) {
+ this.sender.sendMessage(message);
+ }
+
+ @Override
+ public void error(final String message) {
+ this.sender.sendWarning(message);
+ }
+
+ @Override
+ public CommandHandler getCommandHandler() {
+ return this.handler;
+ }
+
+ @Override
+ public Locale getLocale() {
+ return this.sender.getLocale();
+ }
+}
diff --git a/distributor-command-lamp/src/main/java/com/xpdustry/distributor/command/lamp/MindustryCommandHandler.java b/distributor-command-lamp/src/main/java/com/xpdustry/distributor/command/lamp/MindustryCommandHandler.java
new file mode 100644
index 00000000..a9a9f92d
--- /dev/null
+++ b/distributor-command-lamp/src/main/java/com/xpdustry/distributor/command/lamp/MindustryCommandHandler.java
@@ -0,0 +1,37 @@
+/*
+ * Distributor, a feature-rich framework for Mindustry plugins.
+ *
+ * Copyright (C) 2024 Xpdustry
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package com.xpdustry.distributor.command.lamp;
+
+import com.xpdustry.distributor.command.CommandSender;
+import com.xpdustry.distributor.command.DescriptionMapper;
+import com.xpdustry.distributor.plugin.MindustryPlugin;
+import com.xpdustry.distributor.plugin.PluginAware;
+import revxrsal.commands.CommandHandler;
+
+public interface MindustryCommandHandler extends CommandHandler, PluginAware {
+
+ static MindustryCommandHandler create(
+ final MindustryPlugin plugin, final DescriptionMapper descriptionMapper) {
+ return new MindustryCommandHandlerImpl(plugin, descriptionMapper);
+ }
+
+ MindustryCommandActor wrap(final CommandSender sender);
+
+ void initialize(final arc.util.CommandHandler handler);
+}
diff --git a/distributor-command-lamp/src/main/java/com/xpdustry/distributor/command/lamp/MindustryCommandHandlerImpl.java b/distributor-command-lamp/src/main/java/com/xpdustry/distributor/command/lamp/MindustryCommandHandlerImpl.java
new file mode 100644
index 00000000..b32b9e24
--- /dev/null
+++ b/distributor-command-lamp/src/main/java/com/xpdustry/distributor/command/lamp/MindustryCommandHandlerImpl.java
@@ -0,0 +1,133 @@
+/*
+ * Distributor, a feature-rich framework for Mindustry plugins.
+ *
+ * Copyright (C) 2024 Xpdustry
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package com.xpdustry.distributor.command.lamp;
+
+import arc.struct.ObjectMap;
+import arc.util.CommandHandler;
+import com.xpdustry.distributor.collection.ArcCollections;
+import com.xpdustry.distributor.command.CommandFacade;
+import com.xpdustry.distributor.command.CommandSender;
+import com.xpdustry.distributor.command.DescriptionFacade;
+import com.xpdustry.distributor.command.DescriptionMapper;
+import com.xpdustry.distributor.plugin.MindustryPlugin;
+import java.lang.reflect.Field;
+import java.util.Objects;
+import org.jspecify.annotations.Nullable;
+import revxrsal.commands.command.CommandCategory;
+import revxrsal.commands.command.ExecutableCommand;
+import revxrsal.commands.core.BaseCommandHandler;
+import revxrsal.commands.core.CommandPath;
+
+@SuppressWarnings("UnstableApiUsage")
+final class MindustryCommandHandlerImpl extends BaseCommandHandler implements MindustryCommandHandler {
+
+ private static final Field COMMAND_MAP_ACCESSOR;
+
+ static {
+ try {
+ COMMAND_MAP_ACCESSOR = CommandHandler.class.getDeclaredField("commands");
+ COMMAND_MAP_ACCESSOR.setAccessible(true);
+ } catch (final Exception e) {
+ throw new RuntimeException("Unable to access CommandHandler#commands.", e);
+ }
+ }
+
+ private final MindustryPlugin plugin;
+ final DescriptionMapper descriptionMapper;
+ private @Nullable CommandHandler handler = null;
+
+ MindustryCommandHandlerImpl(final MindustryPlugin plugin, final DescriptionMapper descriptionMapper) {
+ this.plugin = plugin;
+ this.descriptionMapper = descriptionMapper;
+ }
+
+ @Override
+ public MindustryCommandHandler register(final Object... commands) {
+ super.register(commands);
+ for (final ExecutableCommand command : this.executables.values()) {
+ if (command.getParent() != null) continue;
+ createArcCommand(
+ command.getName(),
+ descriptionMapper.map(LampElement.Command.of(command)),
+ this.executables.values().stream()
+ .anyMatch((ExecutableCommand cmd) -> cmd.getId() == command.getId()));
+ }
+ for (final CommandCategory category : this.categories.values()) {
+ if (category.getParent() != null) continue;
+ createArcCommand(category.getName(), this.descriptionMapper.map(LampElement.Category.of(category)), false);
+ }
+ return this;
+ }
+
+ @Override
+ public boolean unregister(final CommandPath path) {
+ if (path.isRoot()) {
+ for (final var command :
+ ArcCollections.immutableList(getArcHandler().getCommandList())) {
+ if (CommandFacade.from(command) instanceof LampCommandFacade facade
+ && facade.handler == this
+ && facade.getRealName().equalsIgnoreCase(path.getName())) {
+ getArcHandler().removeCommand(command.text);
+ }
+ }
+ }
+ return super.unregister(path);
+ }
+
+ @Override
+ public MindustryPlugin getPlugin() {
+ return this.plugin;
+ }
+
+ @Override
+ public MindustryCommandActor wrap(final CommandSender sender) {
+ return new MindustryCommandActorImpl(this, sender);
+ }
+
+ @Override
+ public void initialize(final CommandHandler handler) {
+ if (this.handler != null) {
+ throw new IllegalStateException("This handler is already initialized.");
+ }
+ this.handler = handler;
+ }
+
+ @SuppressWarnings("unchecked")
+ private ObjectMap getArcHandlerInternalMap() {
+ try {
+ return (ObjectMap) COMMAND_MAP_ACCESSOR.get(getArcHandler());
+ } catch (final IllegalAccessException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private void createArcCommand(final String name, final DescriptionFacade description, final boolean alias) {
+ addCommand(new LampCommandFacade(
+ this, name, description, alias, getArcHandlerInternalMap().containsKey(name)));
+ }
+
+ private arc.util.CommandHandler getArcHandler() {
+ return Objects.requireNonNull(this.handler, "This lamp command handler is not initialized yet.");
+ }
+
+ private void addCommand(final LampCommandFacade command) {
+ getArcHandlerInternalMap().put(command.text, command);
+ getArcHandler().getCommandList().add(command);
+ }
+}
diff --git a/distributor-command-lamp/src/main/java/com/xpdustry/distributor/command/lamp/package-info.java b/distributor-command-lamp/src/main/java/com/xpdustry/distributor/command/lamp/package-info.java
new file mode 100644
index 00000000..242a068e
--- /dev/null
+++ b/distributor-command-lamp/src/main/java/com/xpdustry/distributor/command/lamp/package-info.java
@@ -0,0 +1,4 @@
+@NullMarked
+package com.xpdustry.distributor.command.lamp;
+
+import org.jspecify.annotations.NullMarked;
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index a0f60b65..8d69b635 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -12,6 +12,7 @@ slf4j = "2.0.12"
# command
cloud = "2.0.0-beta.4"
+lamp = "3.2.1"
# utilities
immutables = "2.10.1"
@@ -26,6 +27,7 @@ jspecify = "0.3.0"
errorprone-gradle = "3.1.0"
errorprone-core = "2.26.1"
nullaway = "0.10.24"
+jetbrains-annotations = "24.1.0"
# linting
palantir = "2.41.0"
@@ -51,6 +53,7 @@ slf4j-from-jul = { module = "org.slf4j:jul-to-slf4j", version.ref = "slf4j" }
# command
cloud-core = { module = "org.incendo:cloud-core", version.ref = "cloud" }
+lamp-common = { module = "com.github.Revxrsal.Lamp:common", version.ref = "lamp" }
# utilities
immutables-processor = { module = "org.immutables:value-processor", version.ref = "immutables" }
@@ -68,6 +71,7 @@ jspecify = { module = "org.jspecify:jspecify", version.ref = "jspecify" }
errorprone-gradle = { module = "net.ltgt.gradle:gradle-errorprone-plugin", version.ref = "errorprone-gradle" }
errorprone-core = { module = "com.google.errorprone:error_prone_core", version.ref = "errorprone-core" }
nullaway = { module = "com.uber.nullaway:nullaway", version.ref = "nullaway" }
+jetbrains-annotations = { module = "org.jetbrains:annotations", version.ref = "jetbrains-annotations" }
# gradle
toxopid = { module = "fr.xpdustry:toxopid", version.ref = "toxopid" }
diff --git a/settings.gradle.kts b/settings.gradle.kts
index e74af619..6aff44bf 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -7,4 +7,5 @@ include(":distributor-logging-simple")
include(":distributor-common-api")
include(":distributor-common")
include(":distributor-command-cloud")
+include(":distributor-command-lamp")
include(":distributor-permission-rank")