|
28 | 28 | import com.google.common.base.Joiner;
|
29 | 29 | import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
30 | 30 | import com.google.inject.Inject;
|
| 31 | +import com.google.inject.Injector; |
| 32 | +import com.google.inject.Key; |
| 33 | +import com.google.inject.TypeLiteral; |
31 | 34 | import com.velocitypowered.api.command.CommandManager;
|
| 35 | +import com.velocitypowered.api.command.CommandSource; |
32 | 36 | import com.velocitypowered.api.event.EventManager;
|
33 | 37 | import com.velocitypowered.api.event.Subscribe;
|
34 | 38 | import com.velocitypowered.api.event.proxy.ProxyInitializeEvent;
|
35 | 39 | import com.velocitypowered.api.plugin.Plugin;
|
36 | 40 | import com.velocitypowered.api.plugin.annotation.DataDirectory;
|
| 41 | +import com.velocitypowered.api.proxy.ConsoleCommandSource; |
| 42 | +import com.velocitypowered.api.proxy.Player; |
37 | 43 | import com.velocitypowered.api.proxy.ProxyServer;
|
38 | 44 | import com.velocitypowered.api.proxy.messages.ChannelIdentifier;
|
39 | 45 | import com.velocitypowered.api.proxy.messages.MinecraftChannelIdentifier;
|
|
73 | 79 | import de.jvstvshd.necrify.velocity.user.VelocityUser;
|
74 | 80 | import de.jvstvshd.necrify.velocity.user.VelocityUserManager;
|
75 | 81 | 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; |
76 | 86 | import org.jetbrains.annotations.NotNull;
|
77 | 87 | import org.slf4j.Logger;
|
78 | 88 |
|
@@ -105,6 +115,9 @@ public class NecrifyVelocityPlugin extends AbstractNecrifyPlugin {
|
105 | 115 | private final MessagingChannelCommunicator communicator;
|
106 | 116 | private EventDispatcher eventDispatcher;
|
107 | 117 |
|
| 118 | + @Inject |
| 119 | + private Injector injector; |
| 120 | + |
108 | 121 | /**
|
109 | 122 | * 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
|
110 | 123 | * 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) {
|
178 | 191 | commandManager.register(TempmuteCommand.tempmuteCommand(this));
|
179 | 192 | commandManager.register(KickCommand.kickCommand(this));
|
180 | 193 | 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()); |
181 | 202 | }
|
182 | 203 |
|
183 | 204 | @SuppressWarnings({"unchecked", "UnstableApiUsage"})
|
@@ -278,19 +299,54 @@ public void setUserManager(@NotNull UserManager userManager) {
|
278 | 299 | public <T extends Punishment> CompletableFuture<Optional<T>> getPunishment(@NotNull UUID punishmentId) {
|
279 | 300 | 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 -> {
|
280 | 301 | 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); |
291 | 303 | }).first(), getExecutor());
|
292 | 304 | }
|
293 | 305 |
|
| 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 | + |
294 | 350 | @Override
|
295 | 351 | public @NotNull EventDispatcher getEventDispatcher() {
|
296 | 352 | return eventDispatcher;
|
|
0 commit comments