use of codecrafter47.bungeetablistplus.player.BungeePlayer in project BungeeTabListPlus by CodeCrafter47.
the class BukkitBridge method handlePluginMessage.
private void handlePluginMessage(ProxiedPlayer player, Server server, DataInput input) throws IOException {
PlayerConnectionInfo connectionInfo = playerPlayerConnectionInfoMap.get(player);
if (connectionInfo == null) {
return;
}
int messageId = input.readUnsignedByte();
if (messageId == BridgeProtocolConstants.MESSAGE_ID_INTRODUCE) {
int serverIdentifier = input.readInt();
int protocolVersion = input.readInt();
int minimumCompatibleProtocolVersion = input.readInt();
String proxyPluginVersion = input.readUTF();
int connectionId = serverIdentifier + proxyIdentifier;
if (connectionId == connectionInfo.connectionIdentifier) {
return;
}
if (BridgeProtocolConstants.VERSION < minimumCompatibleProtocolVersion) {
rlExecutor.execute(() -> {
logger.log(Level.WARNING, "Incompatible version of BTLP on server " + server.getInfo().getName() + " detected: " + proxyPluginVersion);
});
return;
}
// reset connection state
connectionInfo.connectionIdentifier = connectionId;
connectionInfo.isConnectionValid = true;
connectionInfo.nextIntroducePacketDelay = 1;
connectionInfo.introducePacketDelay = 1;
connectionInfo.hasReceived = false;
connectionInfo.protocolVersion = Integer.min(BridgeProtocolConstants.VERSION, protocolVersion);
BungeePlayer bungeePlayer = bungeePlayerProvider.getPlayerIfPresent(player);
if (bungeePlayer == null) {
logger.severe("Internal error - Bridge functionality not available for " + player.getName());
} else {
connectionInfo.playerBridgeData = bungeePlayer.getBridgeDataCache();
connectionInfo.playerBridgeData.setConnectionId(connectionId);
connectionInfo.playerBridgeData.connection = server;
connectionInfo.playerBridgeData.requestMissingData();
}
connectionInfo.serverBridgeData = getServerDataCache(server.getInfo().getName());
connectionInfo.serverBridgeData.setConnectionId(connectionId);
connectionInfo.serverBridgeData.addConnection(server);
connectionInfo.serverBridgeData.requestMissingData();
// send ACK 0
ByteArrayOutputStream byteArrayOutput = new ByteArrayOutputStream();
DataOutput output = new DataOutputStream(byteArrayOutput);
output.writeByte(BridgeProtocolConstants.MESSAGE_ID_ACK);
output.writeInt(connectionId);
output.writeInt(0);
byte[] message = byteArrayOutput.toByteArray();
server.sendData(BridgeProtocolConstants.CHANNEL, message);
} else {
if (!connectionInfo.isConnectionValid) {
return;
}
int connectionId = input.readInt();
if (connectionId != connectionInfo.connectionIdentifier) {
return;
}
connectionInfo.hasReceived = true;
int sequenceNumber = input.readInt();
BridgeData bridgeData;
boolean isServerMessage;
if ((messageId & 0x80) == 0) {
bridgeData = connectionInfo.playerBridgeData;
isServerMessage = false;
} else {
bridgeData = connectionInfo.serverBridgeData;
isServerMessage = true;
}
if (bridgeData == null) {
return;
}
messageId = messageId & 0x7f;
synchronized (bridgeData) {
if (messageId == BridgeProtocolConstants.MESSAGE_ID_ACK) {
int confirmed = sequenceNumber - bridgeData.lastConfirmed;
if (confirmed > bridgeData.messagesPendingConfirmation.size()) {
return;
}
while (confirmed-- > 0) {
bridgeData.lastConfirmed++;
bridgeData.messagesPendingConfirmation.remove();
}
} else if (messageId == BridgeProtocolConstants.MESSAGE_ID_UPDATE_DATA) {
if (sequenceNumber > bridgeData.nextIncomingMessageId) {
// ignore messages from the future
return;
}
ByteArrayOutputStream byteArrayOutput = new ByteArrayOutputStream();
DataOutput output = new DataOutputStream(byteArrayOutput);
output.writeByte(BridgeProtocolConstants.MESSAGE_ID_ACK | (isServerMessage ? 0x80 : 0x00));
output.writeInt(connectionId);
output.writeInt(sequenceNumber);
byte[] message = byteArrayOutput.toByteArray();
server.sendData(BridgeProtocolConstants.CHANNEL, message);
if (sequenceNumber < bridgeData.nextIncomingMessageId) {
// ignore messages from the past after sending ACK
return;
}
bridgeData.nextIncomingMessageId++;
int size = input.readInt();
if (size > 0) {
onDataReceived(bridgeData, input, size);
}
} else {
throw new IllegalArgumentException("Unexpected message id: " + messageId);
}
}
}
}
use of codecrafter47.bungeetablistplus.player.BungeePlayer in project BungeeTabListPlus by CodeCrafter47.
the class BungeePlayerProvider method onPlayerConnected.
public BungeePlayer onPlayerConnected(ProxiedPlayer player) {
BungeePlayer bungeePlayer = new BungeePlayer(player);
String version = BungeeTabListPlus.getInstance().getProtocolVersionProvider().getVersion(player);
boolean version_below_1_8 = !BungeeTabListPlus.getInstance().getProtocolVersionProvider().has18OrLater(player);
mainThread.execute(() -> {
bungeePlayer.getLocalDataCache().updateValue(BTLPBungeeDataKeys.DATA_KEY_CLIENT_VERSION, version);
bungeePlayer.getLocalDataCache().updateValue(BTLPBungeeDataKeys.DATA_KEY_CLIENT_VERSION_BELOW_1_8, version_below_1_8);
players.put(player, bungeePlayer);
listeners.forEach(listener -> listener.onPlayerAdded(bungeePlayer));
});
return bungeePlayer;
}
use of codecrafter47.bungeetablistplus.player.BungeePlayer in project BungeeTabListPlus by CodeCrafter47.
the class BungeePlayerProvider method onPlayerDisconnected.
public void onPlayerDisconnected(ProxiedPlayer player) {
mainThread.execute(() -> {
BungeePlayer bungeePlayer;
if (null == (bungeePlayer = players.remove(player))) {
return;
}
listeners.forEach(listener -> listener.onPlayerRemoved(bungeePlayer));
});
}
use of codecrafter47.bungeetablistplus.player.BungeePlayer in project BungeeTabListPlus by CodeCrafter47.
the class RedisPlayerManager method onRedisMessage.
@EventHandler
@SuppressWarnings("unchecked")
public void onRedisMessage(PubSubMessageEvent event) {
String channel = event.getChannel();
if (channel.equals(CHANNEL_DATA_REQUEST)) {
ByteArrayDataInput input = ByteStreams.newDataInput(Base64.getDecoder().decode(event.getMessage()));
try {
UUID uuid = DataStreamUtils.readUUID(input);
ProxiedPlayer proxiedPlayer = ProxyServer.getInstance().getPlayer(uuid);
if (proxiedPlayer != null) {
BungeePlayer player = bungeePlayerProvider.getPlayerIfPresent(proxiedPlayer);
if (player != null) {
DataKey<?> key = DataStreamUtils.readDataKey(input, keyRegistry, missingDataKeyLogger);
if (key != null) {
player.addDataChangeListener((DataKey<Object>) key, new DataChangeListener(player, (DataKey<Object>) key));
updateData(uuid, (DataKey<Object>) key, player.get(key));
}
}
}
} catch (IOException ex) {
logger.log(Level.SEVERE, "Unexpected error reading redis message", ex);
}
} else if (channel.equals(CHANNEL_DATA_UPDATE)) {
ByteArrayDataInput input = ByteStreams.newDataInput(Base64.getDecoder().decode(event.getMessage()));
try {
UUID uuid = DataStreamUtils.readUUID(input);
RedisPlayer player = byUUID.get(uuid);
if (player != null) {
DataCache cache = player.getData();
DataKey<?> key = DataStreamUtils.readDataKey(input, keyRegistry, missingDataKeyLogger);
if (key != null) {
boolean removed = input.readBoolean();
if (removed) {
mainThread.execute(() -> cache.updateValue(key, null));
} else {
Object value = typeRegistry.getTypeAdapter(key.getType()).read(input);
mainThread.execute(() -> cache.updateValue((DataKey<Object>) key, value));
}
}
}
} catch (IOException ex) {
logger.log(Level.SEVERE, "Unexpected error reading redis message", ex);
}
} else if (channel.equals(CHANNEL_DATA_OLD) || channel.equals(CHANNEL_REQUEST_DATA_OLD)) {
logger.warning("BungeeTabListPlus on at least one proxy in your network is outdated.");
}
}
use of codecrafter47.bungeetablistplus.player.BungeePlayer in project BungeeTabListPlus by CodeCrafter47.
the class CommandHide method hidePlayer.
private void hidePlayer(ProxiedPlayer player) {
BungeePlayer bungeePlayer = BungeeTabListPlus.getInstance().getBungeePlayerProvider().getPlayer(player);
bungeePlayer.getLocalDataCache().updateValue(BTLPBungeeDataKeys.DATA_KEY_IS_HIDDEN_PLAYER_COMMAND, true);
}
Aggregations