diff --git a/bukkit/src/main/java/net/william278/huskhomes/command/BukkitCommand.java b/bukkit/src/main/java/net/william278/huskhomes/command/BukkitCommand.java
index 4590c970..94d0798e 100644
--- a/bukkit/src/main/java/net/william278/huskhomes/command/BukkitCommand.java
+++ b/bukkit/src/main/java/net/william278/huskhomes/command/BukkitCommand.java
@@ -146,7 +146,7 @@ public enum Type {
TPA_HERE_COMMAND((plugin) -> new TeleportRequestCommand(plugin, TeleportRequest.Type.TPA_HERE)),
TPACCEPT_COMMAND((plugin) -> new TpRespondCommand(plugin, true)),
TPDECLINE_COMMAND((plugin) -> new TpRespondCommand(plugin, false)),
- RTP_COMMAND(RtpCommand::new),
+ RTP_COMMAND(RTPCommand::new),
TP_IGNORE_COMMAND(TpIgnoreCommand::new),
TP_OFFLINE_COMMAND(TpOfflineCommand::new),
TP_ALL_COMMAND(TpAllCommand::new),
diff --git a/common/src/main/java/net/william278/huskhomes/api/BaseHuskHomesAPI.java b/common/src/main/java/net/william278/huskhomes/api/BaseHuskHomesAPI.java
index 843016b6..e2ee29fc 100644
--- a/common/src/main/java/net/william278/huskhomes/api/BaseHuskHomesAPI.java
+++ b/common/src/main/java/net/william278/huskhomes/api/BaseHuskHomesAPI.java
@@ -23,6 +23,9 @@
import net.william278.huskhomes.HuskHomes;
import net.william278.huskhomes.config.Locales;
import net.william278.huskhomes.config.Settings;
+import net.william278.huskhomes.network.Broker;
+import net.william278.huskhomes.network.Message;
+import net.william278.huskhomes.network.Payload;
import net.william278.huskhomes.position.Home;
import net.william278.huskhomes.position.Position;
import net.william278.huskhomes.position.Warp;
@@ -38,10 +41,7 @@
import java.time.Duration;
import java.time.Instant;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.UUID;
+import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;
import java.util.stream.Collectors;
@@ -63,6 +63,11 @@ public class BaseHuskHomesAPI {
*/
protected final HuskHomes plugin;
+ /**
+ * (Internal use only - Random integer for RTP.
+ */
+ private final Random random = new Random();
+
/**
* (Internal use only) - Constructor, instantiating the base API class.
*/
@@ -766,16 +771,67 @@ public final TeleportBuilder teleportBuilder() {
/**
* Attempt to teleport an {@link OnlineUser} to a randomly generated {@link Position}. The {@link Position} will be
- * generated by the current {@link RandomTeleportEngine}.
+ * generated by the current {@link RandomTeleportEngine} on a randomly chosen server from
+ * {@link Settings.RtpSettings Allowed Servers} (If {@link Settings.CrossServerSettings Broker Type}
+ * is {@link Broker.Type#REDIS}.
*
* @param user The {@link OnlineUser} to teleport
* @param timedTeleport Whether the teleport should be timed or not (requiring a warmup where they must stand still
* for a period of time)
* @param rtpArgs Arguments that will be passed to the implementing {@link RandomTeleportEngine}
* @since 3.0
+ * @apiNote This method was updated in version 4.6.3 to support the new Cross-Server RTP function,
+ * for the original function use {@link #randomlyTeleportPlayerLocally(OnlineUser, boolean, String...)}
*/
public final void randomlyTeleportPlayer(@NotNull OnlineUser user, boolean timedTeleport,
@NotNull String... rtpArgs) {
+ if (plugin.getSettings().getRtp().isCrossServer() && (plugin.getSettings().getCrossServer().isEnabled()
+ && plugin.getSettings().getCrossServer().getBrokerType() == Broker.Type.REDIS)) {
+ List allowedServers = plugin.getSettings().getRtp().getRandomTargetServers();
+ String randomServer = allowedServers.get(random.nextInt(allowedServers.size()));
+ if (randomServer.equals(plugin.getServerName())) {
+ randomlyTeleportPlayerLocally(user, timedTeleport, rtpArgs);
+ return;
+ }
+ Message.builder()
+ .scope(Message.Scope.SERVER)
+ .target(randomServer)
+ .type(Message.Type.REQUEST_RTP_LOCATION)
+ .payload(Payload.withStringList(
+ List.of(user.getPosition().getWorld().getName(), user.getUsername())))
+ .build().send(plugin.getMessenger(), user);
+ return;
+ }
+ randomlyTeleportPlayerLocally(user, timedTeleport, rtpArgs);
+ }
+
+ /**
+ * Attempt to teleport an {@link OnlineUser} to a randomly generated {@link Position}. The {@link Position} will be
+ * generated by the current {@link RandomTeleportEngine}.
+ *
+ * @param user The {@link OnlineUser} to teleport
+ * @since 3.0
+ * @apiNote This method was updated in version 4.6.3 to support the new Cross-Server RTP function,
+ * for the original function use {@link #randomlyTeleportPlayerLocally(OnlineUser)}
+ */
+ public final void randomlyTeleportPlayer(@NotNull OnlineUser user) {
+ this.randomlyTeleportPlayer(user, false);
+ }
+
+
+ /**
+ * Attempt to teleport an {@link OnlineUser} to a randomly generated {@link Position}. The {@link Position} will be
+ * generated by the current {@link RandomTeleportEngine}. (Does not RTP cross-server, use
+ * {@link #randomlyTeleportPlayer(OnlineUser, boolean, String...)})
+ *
+ * @param user The {@link OnlineUser} to teleport
+ * @param timedTeleport Whether the teleport should be timed or not (requiring a warmup where they must stand still
+ * for a period of time)
+ * @param rtpArgs Arguments that will be passed to the implementing {@link RandomTeleportEngine}
+ * @since 4.6.3
+ */
+ public final void randomlyTeleportPlayerLocally(@NotNull OnlineUser user, boolean timedTeleport,
+ @NotNull String... rtpArgs) {
plugin.getRandomTeleportEngine()
.getRandomPosition(user.getPosition().getWorld(), rtpArgs)
.thenAccept(position -> {
@@ -794,13 +850,14 @@ public final void randomlyTeleportPlayer(@NotNull OnlineUser user, boolean timed
/**
* Attempt to teleport an {@link OnlineUser} to a randomly generated {@link Position}. The {@link Position} will be
- * generated by the current {@link RandomTeleportEngine}.
+ * generated by the current {@link RandomTeleportEngine}. (Does not RTP cross-server, use
+ * {@link #randomlyTeleportPlayer(OnlineUser)})
*
* @param user The {@link OnlineUser} to teleport
- * @since 3.0
+ * @since 4.6.3
*/
- public final void randomlyTeleportPlayer(@NotNull OnlineUser user) {
- this.randomlyTeleportPlayer(user, false);
+ public final void randomlyTeleportPlayerLocally(@NotNull OnlineUser user) {
+ this.randomlyTeleportPlayerLocally(user, false);
}
/**
diff --git a/common/src/main/java/net/william278/huskhomes/command/RtpCommand.java b/common/src/main/java/net/william278/huskhomes/command/RTPCommand.java
similarity index 79%
rename from common/src/main/java/net/william278/huskhomes/command/RtpCommand.java
rename to common/src/main/java/net/william278/huskhomes/command/RTPCommand.java
index 1b6f63cb..cea3ed74 100644
--- a/common/src/main/java/net/william278/huskhomes/command/RtpCommand.java
+++ b/common/src/main/java/net/william278/huskhomes/command/RTPCommand.java
@@ -20,6 +20,9 @@
package net.william278.huskhomes.command;
import net.william278.huskhomes.HuskHomes;
+import net.william278.huskhomes.network.Broker;
+import net.william278.huskhomes.network.Message;
+import net.william278.huskhomes.network.Payload;
import net.william278.huskhomes.position.World;
import net.william278.huskhomes.teleport.Teleport;
import net.william278.huskhomes.teleport.TeleportBuilder;
@@ -32,10 +35,13 @@
import java.util.List;
import java.util.Map;
import java.util.Optional;
+import java.util.Random;
-public class RtpCommand extends Command implements UserListTabProvider {
+public class RTPCommand extends Command implements UserListTabProvider {
- protected RtpCommand(@NotNull HuskHomes plugin) {
+ private final Random random = new Random();
+
+ protected RTPCommand(@NotNull HuskHomes plugin) {
super("rtp", List.of(), "[player] [world]", plugin);
addAdditionalPermissions(Map.of(
@@ -140,6 +146,37 @@ private void executeRtp(@NotNull OnlineUser teleporter, @NotNull CommandUser exe
// Generate a random position
plugin.getLocales().getLocale("teleporting_random_generation")
.ifPresent(teleporter::sendMessage);
+
+ if (plugin.getSettings().getRtp().isCrossServer() && plugin.getSettings().getCrossServer().isEnabled()
+ && plugin.getSettings().getCrossServer().getBrokerType() == Broker.Type.REDIS) {
+ List allowedServers = plugin.getSettings().getRtp().getRandomTargetServers();
+ String randomServer = allowedServers.get(random.nextInt(allowedServers.size()));
+ if (randomServer.equals(plugin.getServerName())) {
+ performLocalRTP(teleporter, executor, world, args);
+ return;
+ }
+ Message.builder()
+ .type(Message.Type.REQUEST_RTP_LOCATION)
+ .scope(Message.Scope.SERVER)
+ .target(randomServer)
+ .payload(Payload.withRTPRequest(Payload.RTPRequest.of(teleporter.getUsername(), world.getName())))
+ .build().send(plugin.getMessenger(), teleporter);
+ return;
+ }
+
+ performLocalRTP(teleporter, executor, world, args);
+ }
+
+ /**
+ * Performs the RTP locally.
+ *
+ * @param teleporter person to teleport
+ * @param executor the person executing the teleport
+ * @param world the world to teleport to
+ * @param args rtp engine args
+ */
+ private void performLocalRTP(@NotNull OnlineUser teleporter, @NotNull CommandUser executor, @NotNull World world,
+ @NotNull String[] args) {
plugin.getRandomTeleportEngine()
.getRandomPosition(world, args.length > 1 ? removeFirstArg(args) : args)
.thenAccept(position -> {
@@ -157,5 +194,4 @@ private void executeRtp(@NotNull OnlineUser teleporter, @NotNull CommandUser exe
builder.buildAndComplete(executor.equals(teleporter), args);
});
}
-
}
diff --git a/common/src/main/java/net/william278/huskhomes/config/Settings.java b/common/src/main/java/net/william278/huskhomes/config/Settings.java
index b16b8b9a..fa4f2637 100644
--- a/common/src/main/java/net/william278/huskhomes/config/Settings.java
+++ b/common/src/main/java/net/william278/huskhomes/config/Settings.java
@@ -340,6 +340,13 @@ public boolean isWorldRtpRestricted(@NotNull World world) {
.map(n -> n.startsWith("minecraft:") ? n.substring(10) : n)
.anyMatch(n -> n.equalsIgnoreCase(filteredName));
}
+
+ @Comment("Whether or not RTP should perform cross-server.")
+ private boolean crossServer = false;
+
+ @Comment({"List of server in which /rtp is allowed. (Only relevant when using cross server mode WITH REDIS)",
+ "If a server is not defined here the RTP logic has no way of knowing its existence."})
+ private List randomTargetServers = List.of("server-01", "server-02");
}
@Comment("Action cooldown settings. Docs: https://william278.net/docs/huskhomes/cooldowns")
diff --git a/common/src/main/java/net/william278/huskhomes/network/Broker.java b/common/src/main/java/net/william278/huskhomes/network/Broker.java
index bd2f7320..18233e9a 100644
--- a/common/src/main/java/net/william278/huskhomes/network/Broker.java
+++ b/common/src/main/java/net/william278/huskhomes/network/Broker.java
@@ -23,8 +23,11 @@
import net.william278.huskhomes.HuskHomes;
import net.william278.huskhomes.position.Home;
import net.william278.huskhomes.position.Warp;
+import net.william278.huskhomes.position.World;
import net.william278.huskhomes.teleport.Teleport;
+import net.william278.huskhomes.teleport.TeleportBuilder;
import net.william278.huskhomes.user.OnlineUser;
+import net.william278.huskhomes.util.TransactionResolver;
import org.jetbrains.annotations.NotNull;
import java.util.Locale;
@@ -113,10 +116,55 @@ protected void handle(@NotNull OnlineUser receiver, @NotNull Message message) {
plugin.getManager().homes().updatePublicHomeCache();
plugin.getManager().warps().updateWarpCache();
}
+ case RTP_LOCATION -> message.getPayload()
+ .getRTPResponse()
+ .ifPresentOrElse(response -> {
+ final TeleportBuilder builder = Teleport.builder(plugin)
+ .teleporter(receiver)
+ .actions(TransactionResolver.Action.RANDOM_TELEPORT)
+ .target(response.getPosition());
+ builder.buildAndComplete(true);
+ }, () -> plugin.getLocales().getLocale("error_rtp_randomization_timeout")
+ .ifPresent(receiver::sendMessage));
default -> throw new IllegalStateException("Unexpected value: " + message.getType());
}
}
+ /**
+ * Separate handler for RTP Request because it doesn't need a receiver to handle it.
+ *
+ * @param message the message to handle
+ */
+ protected void handleRTPRequest(@NotNull Message message) {
+ if (message.getSourceServer().equals(getServer())) {
+ return;
+ }
+
+ message.getPayload()
+ .getRTPRequest()
+ .ifPresent((request) -> {
+ Optional world = plugin.getWorlds().stream()
+ .filter(w -> w.getName().equals(request.getWorldName())).findFirst();
+ if (world.isEmpty()) {
+ throw new RuntimeException("%s requested a position in a world we don't have! World: %s"
+ .formatted(message.getSourceServer(), request.getWorldName()));
+ }
+ plugin.getRandomTeleportEngine().getRandomPosition(world.get(), null)
+ .thenAccept((position) -> {
+ final Message.Builder builder = Message.builder()
+ .type(Message.Type.RTP_LOCATION)
+ .target(request.getUsername());
+ if (position.isEmpty()) {
+ builder.payload(Payload.empty());
+ } else {
+ builder.payload(Payload.withRTPResponse(
+ Payload.RTPResponse.of(request.getUsername(), position.get())));
+ }
+ builder.build().send(plugin.getMessenger(), request.getUsername());
+ });
+ });
+ }
+
/**
* Initialize the message broker.
*
@@ -132,6 +180,13 @@ protected void handle(@NotNull OnlineUser receiver, @NotNull Message message) {
*/
protected abstract void send(@NotNull Message message, @NotNull OnlineUser sender);
+ /**
+ * Send a message to the broker. (For Redis Only)
+ *
+ * @param message the message to send
+ */
+ protected abstract void send(@NotNull Message message);
+
/**
* Move an {@link OnlineUser} to a new server on the proxy network.
*
diff --git a/common/src/main/java/net/william278/huskhomes/network/Message.java b/common/src/main/java/net/william278/huskhomes/network/Message.java
index 285599c9..ecfb4768 100644
--- a/common/src/main/java/net/william278/huskhomes/network/Message.java
+++ b/common/src/main/java/net/william278/huskhomes/network/Message.java
@@ -75,6 +75,13 @@ public void send(@NotNull Broker broker, @NotNull OnlineUser sender) {
broker.send(this, sender);
}
+ public void send(@NotNull Broker broker, @NotNull String sender) {
+ this.sender = sender;
+ this.sourceServer = broker.getServer();
+ broker.send(this);
+ }
+
+
@NotNull
public Type getType() {
return type;
@@ -173,6 +180,8 @@ public enum Type {
UPDATE_HOME,
UPDATE_WARP,
UPDATE_CACHES,
+ REQUEST_RTP_LOCATION,
+ RTP_LOCATION,
}
public enum Scope {
diff --git a/common/src/main/java/net/william278/huskhomes/network/Payload.java b/common/src/main/java/net/william278/huskhomes/network/Payload.java
index 21807785..d92e22d4 100644
--- a/common/src/main/java/net/william278/huskhomes/network/Payload.java
+++ b/common/src/main/java/net/william278/huskhomes/network/Payload.java
@@ -21,7 +21,9 @@
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
+import lombok.Value;
import net.william278.huskhomes.position.Position;
+import net.william278.huskhomes.position.World;
import net.william278.huskhomes.teleport.TeleportRequest;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -38,11 +40,25 @@ public class Payload {
@Expose
private Position position;
+ @Nullable
+ @Expose
+ private World world;
+
@Nullable
@Expose
@SerializedName("teleport_request")
private TeleportRequest teleportRequest;
+ @Nullable
+ @Expose
+ @SerializedName("rtp_response")
+ private RTPResponse rtpResponse;
+
+ @Nullable
+ @Expose
+ @SerializedName("rtp_request")
+ private RTPRequest rtpRequest;
+
@Nullable
@Expose
private String string;
@@ -75,6 +91,19 @@ public static Payload withPosition(@NotNull Position position) {
return payload;
}
+ /**
+ * Returns a payload containing a {@link World}.
+ *
+ * @param world the world to send
+ * @return a payload containing the world
+ */
+ @NotNull
+ public static Payload withWorld(@NotNull World world) {
+ final Payload payload = new Payload();
+ payload.world = world;
+ return payload;
+ }
+
/**
* Returns a payload containing a {@link TeleportRequest}.
*
@@ -108,6 +137,26 @@ public static Payload withStringList(@NotNull List target) {
return payload;
}
+ /**
+ * An RTP Response field.
+ */
+ @NotNull
+ public static Payload withRTPResponse(@NotNull RTPResponse rtpResponse) {
+ final Payload payload = new Payload();
+ payload.rtpResponse = rtpResponse;
+ return payload;
+ }
+
+ /**
+ * An RTP Request field.
+ */
+ @NotNull
+ public static Payload withRTPRequest(@NotNull RTPRequest rtpRequest) {
+ final Payload payload = new Payload();
+ payload.rtpRequest = rtpRequest;
+ return payload;
+ }
+
private Payload() {
}
@@ -118,6 +167,12 @@ public Optional getPosition() {
return Optional.ofNullable(position);
}
+ /**
+ * A world field.
+ */
+ public Optional getWorld() {
+ return Optional.ofNullable(world);
+ }
/**
* A teleport request field.
@@ -140,4 +195,29 @@ public Optional> getStringList() {
return Optional.ofNullable(stringList);
}
+ /**
+ * An RTP response.
+ */
+ public Optional getRTPResponse() {
+ return Optional.ofNullable(rtpResponse);
+ }
+
+ /**
+ * An RTP request.
+ */
+ public Optional getRTPRequest() {
+ return Optional.ofNullable(rtpRequest);
+ }
+
+ @Value(staticConstructor = "of")
+ public static class RTPResponse {
+ @Expose String username;
+ @Expose Position position;
+ }
+
+ @Value(staticConstructor = "of")
+ public static class RTPRequest {
+ @Expose String username;
+ @Expose String worldName;
+ }
}
diff --git a/common/src/main/java/net/william278/huskhomes/network/PluginMessageBroker.java b/common/src/main/java/net/william278/huskhomes/network/PluginMessageBroker.java
index 5c4eb8b1..45c95852 100644
--- a/common/src/main/java/net/william278/huskhomes/network/PluginMessageBroker.java
+++ b/common/src/main/java/net/william278/huskhomes/network/PluginMessageBroker.java
@@ -96,6 +96,16 @@ protected void send(@NotNull Message message, @NotNull OnlineUser sender) {
sender.sendPluginMessage(messageWriter.toByteArray());
}
+ /**
+ * Send a message to the broker. (For Redis Only)
+ *
+ * @param message the message to send
+ */
+ @Override
+ protected void send(@NotNull Message message) {
+ throw new IllegalStateException("Tried to send a plugin message without a sender!");
+ }
+
@Override
public void changeServer(@NotNull OnlineUser user, @NotNull String server) {
user.dismount().thenRun(() -> {
diff --git a/common/src/main/java/net/william278/huskhomes/network/RedisBroker.java b/common/src/main/java/net/william278/huskhomes/network/RedisBroker.java
index d1fe3611..4b5b4c4e 100644
--- a/common/src/main/java/net/william278/huskhomes/network/RedisBroker.java
+++ b/common/src/main/java/net/william278/huskhomes/network/RedisBroker.java
@@ -100,6 +100,11 @@ protected void send(@NotNull Message message, @NotNull OnlineUser sender) {
plugin.runAsync(() -> subscriber.send(message));
}
+ @Override
+ protected void send(@NotNull Message message) {
+ plugin.runAsync(() -> subscriber.send(message));
+ }
+
@Override
@Blocking
public void close() {
@@ -199,6 +204,11 @@ public void onMessage(@NotNull String channel, @NotNull String encoded) {
return;
}
+ if (message.getType() == Message.Type.REQUEST_RTP_LOCATION) {
+ broker.handleRTPRequest(message);
+ return;
+ }
+
if (message.getScope() == Message.Scope.PLAYER) {
broker.plugin.getOnlineUsers().stream()
.filter(online -> message.getTarget().equals(Message.TARGET_ALL)
diff --git a/common/src/main/java/net/william278/huskhomes/random/NormalDistributionEngine.java b/common/src/main/java/net/william278/huskhomes/random/NormalDistributionEngine.java
index 7611d313..8e0920b3 100644
--- a/common/src/main/java/net/william278/huskhomes/random/NormalDistributionEngine.java
+++ b/common/src/main/java/net/william278/huskhomes/random/NormalDistributionEngine.java
@@ -21,6 +21,7 @@
import net.william278.huskhomes.HuskHomes;
import net.william278.huskhomes.config.Settings;
+import net.william278.huskhomes.network.Broker;
import net.william278.huskhomes.position.Location;
import net.william278.huskhomes.position.Position;
import net.william278.huskhomes.position.World;
@@ -45,6 +46,13 @@ public NormalDistributionEngine(@NotNull HuskHomes plugin) {
this.radius = plugin.getSettings().getRtp().getRegion();
this.mean = plugin.getSettings().getRtp().getDistributionMean();
this.standardDeviation = plugin.getSettings().getRtp().getDistributionStandardDeviation();
+
+ if (plugin.getSettings().getRtp().isCrossServer()
+ && (plugin.getSettings().getCrossServer().isEnabled()
+ && plugin.getSettings().getCrossServer().getBrokerType() != Broker.Type.REDIS)) {
+ plugin.log(Level.WARNING, "Cross-server /rtp support has been disabled as "
+ + "a REDIS message broker is required for this feature.");
+ }
}
// Utility for determining a valid spawn radius
diff --git a/docs/Setup.md b/docs/Setup.md
index 3ed7504e..9a1102db 100644
--- a/docs/Setup.md
+++ b/docs/Setup.md
@@ -49,6 +49,15 @@ These instructions are for installing HuskHomes on multiple Spigot, Fabric or Sp
- Provided your MySQL database credentials were correct, your network should now be setup to use HuskHomes!
- You can delete the `HuskHomesData.db` SQLite flat file that was generated, if you would like.
+
+Cross-Server RTP
+
+When using Cross-Server RTP 3 things must be true:
+1. You must set `rtp.cross-server` to `true`
+2. You must be using Redis as your message broker
+3. The server names in `rtp.allowed-servers` must match the `server.yml` & Proxy values!
+
+
## Next steps
* [Commands & Permissions](Commands)
* [[Config Files]]
diff --git a/fabric/src/main/java/net/william278/huskhomes/command/FabricCommand.java b/fabric/src/main/java/net/william278/huskhomes/command/FabricCommand.java
index 9628d369..7a881282 100644
--- a/fabric/src/main/java/net/william278/huskhomes/command/FabricCommand.java
+++ b/fabric/src/main/java/net/william278/huskhomes/command/FabricCommand.java
@@ -146,7 +146,7 @@ public enum Type {
TPA_HERE_COMMAND((plugin) -> new TeleportRequestCommand(plugin, TeleportRequest.Type.TPA_HERE)),
TPACCEPT_COMMAND((plugin) -> new TpRespondCommand(plugin, true)),
TPDECLINE_COMMAND((plugin) -> new TpRespondCommand(plugin, false)),
- RTP_COMMAND(RtpCommand::new),
+ RTP_COMMAND(RTPCommand::new),
TP_IGNORE_COMMAND(TpIgnoreCommand::new),
TP_OFFLINE_COMMAND(TpOfflineCommand::new),
TP_ALL_COMMAND(TpAllCommand::new),
diff --git a/sponge/src/main/java/net/william278/huskhomes/command/SpongeCommand.java b/sponge/src/main/java/net/william278/huskhomes/command/SpongeCommand.java
index a0177369..8356613b 100644
--- a/sponge/src/main/java/net/william278/huskhomes/command/SpongeCommand.java
+++ b/sponge/src/main/java/net/william278/huskhomes/command/SpongeCommand.java
@@ -173,7 +173,7 @@ public enum Type {
TPA_HERE_COMMAND((plugin) -> new TeleportRequestCommand(plugin, TeleportRequest.Type.TPA_HERE)),
TPACCEPT_COMMAND((plugin) -> new TpRespondCommand(plugin, true)),
TPDECLINE_COMMAND((plugin) -> new TpRespondCommand(plugin, false)),
- RTP_COMMAND(RtpCommand::new),
+ RTP_COMMAND(RTPCommand::new),
TP_IGNORE_COMMAND(TpIgnoreCommand::new),
TP_OFFLINE_COMMAND(TpOfflineCommand::new),
TP_ALL_COMMAND(TpAllCommand::new),