Moves some teleportation code to the TeleportHelper class Changes some teleportation method names Tries to reduce some code duplication between teleporters Recursively teleports entities to make sure the teleported entity will arrive in the same shape it entered as Makes player checks for teleported vehicles account for any number of players riding any entity in the stack
222 lines
9.1 KiB
Java
222 lines
9.1 KiB
Java
package net.knarcraft.stargate.utility;
|
|
|
|
import net.knarcraft.stargate.Stargate;
|
|
import net.knarcraft.stargate.portal.Portal;
|
|
import net.knarcraft.stargate.portal.PortalHandler;
|
|
import net.knarcraft.stargate.portal.teleporter.PlayerTeleporter;
|
|
import net.md_5.bungee.api.ChatColor;
|
|
import org.bukkit.entity.Player;
|
|
import org.bukkit.event.player.PlayerMoveEvent;
|
|
|
|
import java.io.ByteArrayInputStream;
|
|
import java.io.ByteArrayOutputStream;
|
|
import java.io.DataInputStream;
|
|
import java.io.DataOutputStream;
|
|
import java.io.IOException;
|
|
import java.util.HashMap;
|
|
import java.util.Map;
|
|
import java.util.UUID;
|
|
|
|
/**
|
|
* This class contains helpful functions to help with sending and receiving BungeeCord plugin messages
|
|
*/
|
|
public final class BungeeHelper {
|
|
|
|
private final static String bungeeSubChannel = "SGBungee";
|
|
private final static String bungeeChannel = "BungeeCord";
|
|
private final static String teleportMessageDelimiter = "#@#";
|
|
private final static Map<UUID, String> bungeeQueue = new HashMap<>();
|
|
|
|
private BungeeHelper() {
|
|
|
|
}
|
|
|
|
/**
|
|
* Get the plugin message channel use for BungeeCord messages
|
|
*
|
|
* @return <p>The bungee plugin channel</p>
|
|
*/
|
|
public static String getBungeeChannel() {
|
|
return bungeeChannel;
|
|
}
|
|
|
|
/**
|
|
* Removes a player from the queue of players teleporting through BungeeCord
|
|
*
|
|
* <p>Whenever a BungeeCord teleportation message is received and the player is not currently connected to this
|
|
* server, it'll be added to this queue. Once the player joins this server, the player should be removed from the
|
|
* queue and teleported to the destination.</p>
|
|
*
|
|
* @param playerUUID <p>The UUID of the player to remove</p>
|
|
* @return <p>The name of the destination portal the player should be teleported to</p>
|
|
*/
|
|
public static String removeFromQueue(UUID playerUUID) {
|
|
return bungeeQueue.remove(playerUUID);
|
|
}
|
|
|
|
/**
|
|
* Sends a plugin message to BungeeCord allowing the target server to catch it
|
|
*
|
|
* @param player <p>The teleporting player</p>
|
|
* @param entrancePortal <p>The portal the player is teleporting from</p>
|
|
* @return <p>True if the message was successfully sent</p>
|
|
*/
|
|
public static boolean sendTeleportationMessage(Player player, Portal entrancePortal) {
|
|
try {
|
|
//Build the teleportation message, format is <player identifier>delimiter<destination>
|
|
String message = player.getUniqueId() + teleportMessageDelimiter + entrancePortal.getDestinationName();
|
|
|
|
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
|
DataOutputStream dataOutputStream = new DataOutputStream(byteArrayOutputStream);
|
|
|
|
//Build the message data and send it over the SGBungee BungeeCord channel
|
|
dataOutputStream.writeUTF("Forward");
|
|
//Send the message to the server defined in the entrance portal's network line
|
|
dataOutputStream.writeUTF(stripColor(entrancePortal.getNetwork()));
|
|
//Specify the sub-channel/tag to make it recognizable on arrival
|
|
dataOutputStream.writeUTF(bungeeSubChannel);
|
|
//Write the length of the message
|
|
dataOutputStream.writeShort(message.length());
|
|
//Write the actual message
|
|
dataOutputStream.writeBytes(message);
|
|
//Send the plugin message
|
|
player.sendPluginMessage(Stargate.getInstance(), bungeeChannel, byteArrayOutputStream.toByteArray());
|
|
} catch (IOException ex) {
|
|
Stargate.logSevere("Error sending BungeeCord teleport packet");
|
|
ex.printStackTrace();
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Sends the bungee message necessary to make a player connect to another server
|
|
*
|
|
* @param player <p>The player to teleport</p>
|
|
* @param entrancePortal <p>The bungee portal the player is teleporting from</p>
|
|
* @return <p>True if the plugin message was sent successfully</p>
|
|
*/
|
|
public static boolean changeServer(Player player, Portal entrancePortal) {
|
|
try {
|
|
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
|
DataOutputStream dataOutputStream = new DataOutputStream(byteArrayOutputStream);
|
|
|
|
//Send a connect-message to connect the player to the server defined in the entrance portal's network line
|
|
dataOutputStream.writeUTF("Connect");
|
|
dataOutputStream.writeUTF(stripColor(entrancePortal.getNetwork()));
|
|
|
|
//Send the plugin message
|
|
player.sendPluginMessage(Stargate.getInstance(), bungeeChannel, byteArrayOutputStream.toByteArray());
|
|
} catch (IOException ex) {
|
|
Stargate.logSevere("Error sending BungeeCord connect packet");
|
|
ex.printStackTrace();
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Reads a plugin message byte array to a string if it's sent from another stargate plugin
|
|
*
|
|
* @param message <p>The byte array to read</p>
|
|
* @return <p>The message contained in the byte array, or null on failure</p>
|
|
*/
|
|
public static String readPluginMessage(byte[] message) {
|
|
byte[] data;
|
|
try {
|
|
DataInputStream dataInputStream = new DataInputStream(new ByteArrayInputStream(message));
|
|
String subChannel = dataInputStream.readUTF();
|
|
//Only listen for the SGBungee channel
|
|
if (!subChannel.equals(bungeeSubChannel)) {
|
|
return null;
|
|
}
|
|
|
|
//Get the length of the contained message
|
|
short dataLength = dataInputStream.readShort();
|
|
//Prepare a byte array for the sent message
|
|
data = new byte[dataLength];
|
|
//Read the message to the prepared array
|
|
dataInputStream.readFully(data);
|
|
} catch (IOException ex) {
|
|
Stargate.logSevere("Error receiving BungeeCord message");
|
|
ex.printStackTrace();
|
|
return null;
|
|
}
|
|
return new String(data);
|
|
}
|
|
|
|
/**
|
|
* Handles the receival of a teleport message
|
|
*
|
|
* @param receivedMessage <p>The received teleport message</p>
|
|
*/
|
|
public static void handleTeleportMessage(String receivedMessage) {
|
|
//Get the player id and destination from the message
|
|
String[] messageParts = receivedMessage.split(teleportMessageDelimiter);
|
|
UUID playerUUID = UUID.fromString(messageParts[0]);
|
|
String destination = messageParts[1];
|
|
|
|
//Check if the player is online, if so, teleport, otherwise, queue
|
|
Player player = Stargate.getInstance().getServer().getPlayer(playerUUID);
|
|
if (player == null) {
|
|
bungeeQueue.put(playerUUID, destination);
|
|
} else {
|
|
Portal destinationPortal = PortalHandler.getBungeePortal(destination);
|
|
//If teleporting to an invalid portal, let the server decide where the player arrives
|
|
if (destinationPortal == null) {
|
|
Stargate.logInfo(String.format("Bungee portal %s does not exist", destination));
|
|
return;
|
|
}
|
|
new PlayerTeleporter(destinationPortal, player).teleport(destinationPortal, null);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Teleports a player to a bungee gate
|
|
*
|
|
* @param player <p>The player to teleport</p>
|
|
* @param entrancePortal <p>The gate the player is entering from</p>
|
|
* @param event <p>The event causing the teleportation</p>
|
|
* @return <p>True if the teleportation was successful</p>
|
|
*/
|
|
public static boolean bungeeTeleport(Player player, Portal entrancePortal, PlayerMoveEvent event) {
|
|
//Check if bungee is actually enabled
|
|
if (!Stargate.getGateConfig().enableBungee()) {
|
|
if (!entrancePortal.getOptions().isSilent()) {
|
|
Stargate.getMessageSender().sendErrorMessage(player, Stargate.getString("bungeeDisabled"));
|
|
}
|
|
entrancePortal.getPortalOpener().closePortal(false);
|
|
return false;
|
|
}
|
|
|
|
//Teleport the player back to this gate, for sanity's sake
|
|
new PlayerTeleporter(entrancePortal, player).teleportPlayer(entrancePortal, event);
|
|
|
|
//Send the SGBungee packet first, it will be queued by BC if required
|
|
if (!BungeeHelper.sendTeleportationMessage(player, entrancePortal)) {
|
|
Stargate.debug("bungeeTeleport", "Unable to send teleportation message");
|
|
return false;
|
|
}
|
|
|
|
//Send the connect-message to make the player change server
|
|
if (!BungeeHelper.changeServer(player, entrancePortal)) {
|
|
Stargate.debug("bungeeTeleport", "Unable to change server");
|
|
return false;
|
|
}
|
|
|
|
Stargate.debug("bungeeTeleport", "Teleported player to another server");
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Strips all color tags from a string
|
|
*
|
|
* @param string <p>The string to strip color from</p>
|
|
* @return <p>The string without color codes</p>
|
|
*/
|
|
private static String stripColor(String string) {
|
|
return ChatColor.stripColor(ChatColor.translateAlternateColorCodes('&', string));
|
|
}
|
|
|
|
}
|