Skip to content

Commit 5278d92

Browse files
committed
Initialize work for #11
Add a base structure for all commands
1 parent b592420 commit 5278d92

File tree

6 files changed

+124
-15
lines changed

6 files changed

+124
-15
lines changed

gradle/libs.versions.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ adventure-api = { group = "net.kyori", name = "adventure-api", version.ref = "ad
4343
adventure-text-minimessage = { group = "net.kyori", name = "adventure-text-minimessage", version.ref = "adventure" }
4444
cloud-core = { group = "org.incendo", name = "cloud-core", version.ref = "cloud" }
4545
cloud-annotations = { group = "org.incendo", name = "cloud-annotations", version.ref = "cloud" }
46+
cloud-velocity = { group = "org.incendo", name = "cloud-velocity", version.ref = "cloud" }
4647
jetbrains-annotations = { group = "org.jetbrains", name = "annotations", version.ref = "jetbrains-annotations" }
4748
eventbus = { group = "org.greenrobot", name = "eventbus-java", version.ref = "eventbus" }
4849
slf4j-api = { group = "org.slf4j", name = "slf4j-api", version.ref = "slf4j" }

plugin-common/src/main/java/de/jvstvshd/necrify/common/AbstractNecrifyPlugin.java

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,14 @@
2626

2727
import de.jvstvshd.necrify.api.Necrify;
2828
import de.jvstvshd.necrify.api.user.NecrifyUser;
29+
import de.jvstvshd.necrify.common.commands.NecrifyCommand;
2930
import de.jvstvshd.necrify.common.punishment.NecrifyKick;
3031
import net.kyori.adventure.text.Component;
32+
import org.incendo.cloud.CommandManager;
33+
import org.incendo.cloud.annotations.AnnotationParser;
3134
import org.jetbrains.annotations.NotNull;
3235

36+
import java.util.ArrayList;
3337
import java.util.UUID;
3438
import java.util.concurrent.ExecutorService;
3539

@@ -41,9 +45,6 @@ public AbstractNecrifyPlugin(ExecutorService executorService) {
4145
this.executorService = executorService;
4246
}
4347

44-
public AbstractNecrifyPlugin() {
45-
}
46-
4748
@Override
4849
public @NotNull ExecutorService getExecutor() {
4950
return executorService;
@@ -55,4 +56,23 @@ public AbstractNecrifyPlugin() {
5556
}
5657

5758
public abstract NecrifyKick createKick(Component reason, NecrifyUser user, UUID punishmentUuid);
59+
60+
/**
61+
* Registers commands for the plugin via the {@link AnnotationParser} from the cloud framework. It is possible to only
62+
* register the commands of the /necrify root, but also the top-level ones (e.g. /ban, /kick, etc.).
63+
*
64+
* @param manager the command manager to register the commands to.
65+
* @param topLevelCommands whether to register top-level commands (/ban, /kick, etc.) or not (i.e. only /necrify commands).
66+
*/
67+
public final void registerCommands(CommandManager<NecrifyUser> manager, boolean topLevelCommands) {
68+
AnnotationParser<NecrifyUser> parser = new AnnotationParser<>(manager, NecrifyUser.class);
69+
final var oldExtractor = parser.commandExtractor();
70+
if (!topLevelCommands) {
71+
parser.commandExtractor(instance -> {
72+
var commands = new ArrayList<>(oldExtractor.extractCommands(instance));
73+
return commands.stream().filter(commandDescriptor -> commandDescriptor.commandToken().startsWith("necrify")).toList();
74+
});
75+
}
76+
parser.parse(new NecrifyCommand(this));
77+
}
5878
}

plugin-common/src/main/java/de/jvstvshd/necrify/common/commands/NecrifyCommand.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,25 @@
2424

2525
package de.jvstvshd.necrify.common.commands;
2626

27+
import de.jvstvshd.necrify.common.AbstractNecrifyPlugin;
28+
import org.incendo.cloud.annotations.Command;
29+
2730
public class NecrifyCommand {
2831

32+
private final AbstractNecrifyPlugin plugin;
33+
34+
public NecrifyCommand(AbstractNecrifyPlugin plugin) {
35+
this.plugin = plugin;
36+
}
37+
38+
@Command("necrify ban")
39+
@Command("ban")
40+
public void banCommand() {
41+
42+
}
43+
44+
@Command("necrify kick")
45+
public void kickCommand() {
2946

47+
}
3048
}

plugin/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ repositories {
1414

1515
dependencies {
1616
api(projects.pluginCommon)
17+
api(libs.cloud.velocity)
1718
annotationProcessor(libs.velocity.api)
1819
compileOnly(libs.velocity.api)
1920
compileOnly(libs.luckperms.api)

plugin/src/main/java/de/jvstvshd/necrify/velocity/NecrifyVelocityPlugin.java

Lines changed: 66 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,18 @@
2828
import com.google.common.base.Joiner;
2929
import com.google.common.util.concurrent.ThreadFactoryBuilder;
3030
import com.google.inject.Inject;
31+
import com.google.inject.Injector;
32+
import com.google.inject.Key;
33+
import com.google.inject.TypeLiteral;
3134
import com.velocitypowered.api.command.CommandManager;
35+
import com.velocitypowered.api.command.CommandSource;
3236
import com.velocitypowered.api.event.EventManager;
3337
import com.velocitypowered.api.event.Subscribe;
3438
import com.velocitypowered.api.event.proxy.ProxyInitializeEvent;
3539
import com.velocitypowered.api.plugin.Plugin;
3640
import com.velocitypowered.api.plugin.annotation.DataDirectory;
41+
import com.velocitypowered.api.proxy.ConsoleCommandSource;
42+
import com.velocitypowered.api.proxy.Player;
3743
import com.velocitypowered.api.proxy.ProxyServer;
3844
import com.velocitypowered.api.proxy.messages.ChannelIdentifier;
3945
import com.velocitypowered.api.proxy.messages.MinecraftChannelIdentifier;
@@ -73,6 +79,10 @@
7379
import de.jvstvshd.necrify.velocity.user.VelocityUser;
7480
import de.jvstvshd.necrify.velocity.user.VelocityUserManager;
7581
import net.kyori.adventure.text.Component;
82+
import org.incendo.cloud.SenderMapper;
83+
import org.incendo.cloud.execution.ExecutionCoordinator;
84+
import org.incendo.cloud.velocity.CloudInjectionModule;
85+
import org.incendo.cloud.velocity.VelocityCommandManager;
7686
import org.jetbrains.annotations.NotNull;
7787
import org.slf4j.Logger;
7888

@@ -105,6 +115,9 @@ public class NecrifyVelocityPlugin extends AbstractNecrifyPlugin {
105115
private final MessagingChannelCommunicator communicator;
106116
private EventDispatcher eventDispatcher;
107117

118+
@Inject
119+
private Injector injector;
120+
108121
/**
109122
* Since 1.19.1, cancelling chat messages on proxy is not possible anymore. Therefore, we have to listen to the chat event on the actual game server. This means
110123
* that there has to be a spigot/paper extension to this plugin which is not yet available unless there's a possibility. Therefore all mute related features are disabled for now.
@@ -178,6 +191,14 @@ private void setup(CommandManager commandManager, EventManager eventManager) {
178191
commandManager.register(TempmuteCommand.tempmuteCommand(this));
179192
commandManager.register(KickCommand.kickCommand(this));
180193
commandManager.register(WhitelistCommand.whitelistCommand(this));
194+
195+
final Injector childInjector = injector.createChildInjector(
196+
new CloudInjectionModule<>(
197+
NecrifyUser.class,
198+
ExecutionCoordinator.simpleCoordinator(),
199+
SenderMapper.create(this::createUser, this::getCommandSource)));
200+
registerCommands(childInjector.getInstance(Key.get(new TypeLiteral<VelocityCommandManager<NecrifyUser>>() {
201+
})), getConfig().getConfiguration().isAllowTopLevelCommands());
181202
}
182203

183204
@SuppressWarnings({"unchecked", "UnstableApiUsage"})
@@ -278,19 +299,54 @@ public void setUserManager(@NotNull UserManager userManager) {
278299
public <T extends Punishment> CompletableFuture<Optional<T>> getPunishment(@NotNull UUID punishmentId) {
279300
return Util.executeAsync(() -> (Optional<T>) Query.query("SELECT u.* FROM punishment.necrify_user u " + "INNER JOIN punishment.necrify_punishment p ON u.uuid = p.uuid " + "WHERE p.punishment_id = ?;").single(Call.of().bind(punishmentId, Adapters.UUID_ADAPTER)).map(row -> {
280301
var userId = row.getObject(1, UUID.class);
281-
var cachedUser = getUserManager().getUser(userId);
282-
if (cachedUser.isPresent()) {
283-
return cachedUser.get().getPunishment(punishmentId).orElse(null);
284-
}
285-
var user = new VelocityUser(row.getObject(1, UUID.class), row.getString(2), row.getBoolean(3), this);
286-
getExecutor().execute(() -> {
287-
Query.query("SELECT type, expiration, reason, punishment_id FROM punishment.necrify_punishment WHERE uuid = ?;").single(Call.of().bind(userId, Adapters.UUID_ADAPTER)).map(user::addPunishment).all();
288-
getEventDispatcher().dispatch(new UserLoadedEvent(user).setOrigin(EventOrigin.ofClass(getClass())));
289-
});
290-
return user.getPunishment(punishmentId).orElse(null);
302+
return createUser(userId).getPunishment(punishmentId).orElse(null);
291303
}).first(), getExecutor());
292304
}
293305

306+
public NecrifyUser createUser(CommandSource source) {
307+
if (source instanceof Player) {
308+
return createUser(((Player) source).getUniqueId());
309+
} else if (source instanceof ConsoleCommandSource) {
310+
return new VelocityUser(new UUID(0, 0), "CONSOLE", true, this);
311+
} else {
312+
return new VelocityUser(UUID.randomUUID(), "unknown_source", false, this);
313+
}
314+
}
315+
316+
/**
317+
* Creates a user with the given UUID. If the user is already cached, the cached user is returned.
318+
* <p>Note: this user does not hold any valid data besides his uuid and maybe player instance (if online). After returning
319+
* the value, the missing user data will be loaded, whereafter the {@link UserLoadedEvent} will be fired.</p>
320+
*
321+
* @param userId the UUID of the user to create.
322+
* @return the created user.
323+
*/
324+
public NecrifyUser createUser(UUID userId) {
325+
var cachedUser = getUserManager().getUser(userId);
326+
if (cachedUser.isPresent()) {
327+
return cachedUser.get();
328+
}
329+
var user = new VelocityUser(userId, "unknown", false, this);
330+
getExecutor().execute(() -> {
331+
Query.query("SELECT type, expiration, reason, punishment_id FROM punishment.necrify_punishment WHERE uuid = ?;").single(Call.of().bind(userId, Adapters.UUID_ADAPTER)).map(user::addPunishment).all();
332+
getEventDispatcher().dispatch(new UserLoadedEvent(user).setOrigin(EventOrigin.ofClass(getClass())));
333+
});
334+
return user;
335+
}
336+
337+
public CommandSource getCommandSource(NecrifyUser user) {
338+
if (user instanceof VelocityUser velocityUser) {
339+
var player = velocityUser.getPlayer();
340+
if (player != null) {
341+
return player;
342+
}
343+
}
344+
if ("console".equalsIgnoreCase(user.getUsername()) && user.getUuid().equals(new UUID(0, 0))) {
345+
return server.getConsoleCommandSource();
346+
}
347+
return server.getPlayer(user.getUuid()).orElse(null);
348+
}
349+
294350
@Override
295351
public @NotNull EventDispatcher getEventDispatcher() {
296352
return eventDispatcher;

plugin/src/main/java/de/jvstvshd/necrify/velocity/config/ConfigData.java

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,19 @@ public class ConfigData {
4242
@JsonAlias("whitelistActivated")
4343
private boolean whitelistActivated;
4444

45-
public ConfigData(DataBaseData dataBaseData, Locale defaultLanguage, boolean whitelistActivated) {
45+
@JsonProperty("allow-top-level-commands")
46+
@JsonAlias("allowTopLevelCommands")
47+
private boolean allowTopLevelCommands;
48+
49+
public ConfigData(DataBaseData dataBaseData, Locale defaultLanguage, boolean whitelistActivated, boolean allowTopLevelCommands) {
4650
this.dataBaseData = dataBaseData;
4751
this.defaultLanguage = defaultLanguage;
4852
this.whitelistActivated = whitelistActivated;
53+
this.allowTopLevelCommands = allowTopLevelCommands;
4954
}
5055

5156
public ConfigData() {
52-
this(new DataBaseData(), Locale.ENGLISH, false);
57+
this(new DataBaseData(), Locale.ENGLISH, false, true);
5358
}
5459

5560
public final DataBaseData getDataBaseData() {
@@ -67,4 +72,12 @@ public boolean isWhitelistActivated() {
6772
public void setWhitelistActivated(boolean whitelistActivated) {
6873
this.whitelistActivated = whitelistActivated;
6974
}
75+
76+
public boolean isAllowTopLevelCommands() {
77+
return allowTopLevelCommands;
78+
}
79+
80+
public void setAllowTopLevelCommands(boolean allowTopLevelCommands) {
81+
this.allowTopLevelCommands = allowTopLevelCommands;
82+
}
7083
}

0 commit comments

Comments
 (0)