ViaVersion/api/src/main/java/com/viaversion/viaversion/api/protocol/ProtocolManager.java

288 lines
12 KiB
Java

/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2021 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.protocol;
import com.google.common.collect.Range;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
import com.viaversion.viaversion.api.protocol.packet.PacketType;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType;
import com.viaversion.viaversion.api.protocol.packet.VersionedPacketCreator;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.api.protocol.version.ServerProtocolVersion;
import io.netty.buffer.ByteBuf;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.List;
import java.util.SortedSet;
import java.util.concurrent.CompletableFuture;
public interface ProtocolManager {
/**
* Returns the server protocol version. Its methods will return -1 if not set yet.
*
* @return server protocol version
*/
ServerProtocolVersion getServerProtocolVersion();
/**
* Returns a protocol instance by its class.
*
* @param protocolClass class of the protocol
* @param <T> protocol
* @return protocol if present
*/
@Nullable <T extends Protocol> T getProtocol(Class<T> protocolClass);
/**
* Returns a protocol transforming packets for server version to the given client version.
*
* @param clientVersion client protocol version
* @param serverVersion server protocol version
* @return protocol if present, else null
* @see #getProtocolPath(int, int) to get a full path of Protocols between a larger gap of versions
*/
default @Nullable Protocol getProtocol(ProtocolVersion clientVersion, ProtocolVersion serverVersion) {
return getProtocol(clientVersion.getVersion(), serverVersion.getVersion());
}
/**
* Returns a protocol transforming packets for server version to the given client version.
*
* @param clientVersion client protocol version
* @param serverVersion server protocol version
* @return protocol if present, else null
* @see #getProtocolPath(int, int) to get a full path of Protocols between a larger gap of versions
*/
@Nullable Protocol getProtocol(int clientVersion, int serverVersion);
/**
* Returns the base protocol handling serverbound handshake packets.
*
* @return base protocol
*/
Protocol getBaseProtocol();
/**
* Returns the base protocol for a specific server protocol version.
* The standard base protocols deal with status and login packets for userconnection initialization.
*
* @param serverVersion server protocol version
* @return base protocol for the given server protocol version
* @throws IllegalStateException if no base protocol could be found
*/
Protocol getBaseProtocol(int serverVersion);
/**
* Returns whether the given protocol is a base protocol.
*
* @param protocol protocol
* @return whether the protocol is a base protocol
* @see Protocol#isBaseProtocol()
*/
default boolean isBaseProtocol(Protocol protocol) {
return protocol.isBaseProtocol();
}
/**
* Register and initializes a protocol.
*
* @param protocol protocol to register
* @param clientVersion supported client protocol versions
* @param serverVersion output server protocol version the protocol converts to
* @throws IllegalArgumentException if the client protocol version is equal to the server protocol version
*/
void registerProtocol(Protocol protocol, ProtocolVersion clientVersion, ProtocolVersion serverVersion);
/**
* Register and initializes protocol.
*
* @param protocol protocol to register
* @param supportedClientVersion supported client protocol versions
* @param serverVersion output server protocol version the protocol converts to
* @throws IllegalArgumentException if a supported client protocol version is equal to the server protocol version
*/
void registerProtocol(Protocol protocol, List<Integer> supportedClientVersion, int serverVersion);
/**
* Registers and initializes a base protocol. Base Protocols registered later have higher priority.
* Only base protocol will always be added to pipeline.
*
* @param baseProtocol base protocol to register
* @param supportedProtocols protocol versions supported by the base protocol
* @throws IllegalArgumentException if the protocol is not a base protocol as given by {@link Protocol#isBaseProtocol()}
*/
void registerBaseProtocol(Protocol baseProtocol, Range<Integer> supportedProtocols);
/**
* Calculates and returns the protocol path from a client protocol version to server protocol version.
* Returns null if no path could be found or the path length exceeds the value given by {@link #getMaxProtocolPathSize()}.
*
* @param clientVersion input client protocol version
* @param serverVersion desired output server protocol version
* @return path generated, or null if not supported or the length exceeds {@link #getMaxProtocolPathSize()}
*/
@Nullable List<ProtocolPathEntry> getProtocolPath(int clientVersion, int serverVersion);
/**
* Returns a versioned packet creator to send packets from a given base version to any client version supported by Via.
* The used packet types have to match the given protocol version.
*
* @param inputVersion input protocol version
* @param clientboundPacketsClass clientbound packets class
* @param serverboundPacketsClass serverbound packets class
* @return versioned packet creator
* @throws IllegalArgumentException if either of the packet classes are the base {@link ClientboundPacketType} or {@link ServerboundPacketType} interfaces
*/
VersionedPacketCreator createVersionedPacketCreator(ProtocolVersion inputVersion,
Class<? extends ClientboundPacketType> clientboundPacketsClass,
Class<? extends ServerboundPacketType> serverboundPacketsClass);
/**
* Returns whether protocol path calculation expects the path to come closer to the expected version with each entry, true by default.
* <p>
* In practice, this means a path will never go to a protocol version that puts it farther from the desired
* server protocol version, even if a path existed.
* If this is set to false, *all* possible paths will be checked until a fitting one is found.
* <p>
* Negative examples if this returns true:
* <ul>
* A possible path from 3 to 5 in order of 3→10→5 will be dismissed.
* A possible path from 5 to 3 in order of 5→0→3 will be dismissed.
* </ul>
* <p>
* Negative examples if this returns false:
* <ul>
* While searching for a path from 3 to 5, 3→2→1 could be checked first before 3→4→5 is found.
* While searching for a path from 5 to 3, 5→6→7 could be checked first before 5→4→3 is found.
* </ul>
*
* @return whether protocol path calculation expects the path to come closer to the expected version with each entry
*/
boolean onlyCheckLoweringPathEntries();
/**
* Sets whether protocol path calculation expects the path to come closer to the expected version with each entry.
*
* @param onlyCheckLoweringPathEntries whether protocol path calculation expects the path to come closer to the expected version with each entry
* @see #onlyCheckLoweringPathEntries()
*/
void setOnlyCheckLoweringPathEntries(boolean onlyCheckLoweringPathEntries);
/**
* Returns the maximum protocol path size applied to {@link #getProtocolPath(int, int)}.
*
* @return maximum protocol path size
*/
int getMaxProtocolPathSize();
/**
* Sets the maximum protocol path size applied to {@link #getProtocolPath(int, int)}.
* Its default is 50.
*
* @param maxProtocolPathSize maximum protocol path size
*/
void setMaxProtocolPathSize(int maxProtocolPathSize);
/**
* Returns the protocol versions compatible with the server.
*
* @return sorted, immutable set of supported protocol versions
*/
SortedSet<Integer> getSupportedVersions();
/**
* Check if this plugin is useful to the server.
*
* @return true if there is a useful pipe
*/
boolean isWorkingPipe();
/**
* Ensure that mapping data for that protocol has already been loaded, completes it otherwise.
*
* @param protocolClass protocol class
*/
void completeMappingDataLoading(Class<? extends Protocol> protocolClass) throws Exception;
/**
* Shuts down the executor and uncaches mappings if all futures have been completed.
*
* @return true if the executor has now been shut down
*/
boolean checkForMappingCompletion();
/**
* Executes the given runnable asynchronously, adding a {@link CompletableFuture}
* to the list of data to load bound to their protocols.
*
* @param protocolClass protocol class
* @param runnable runnable to be executed asynchronously
*/
void addMappingLoaderFuture(Class<? extends Protocol> protocolClass, Runnable runnable);
/**
* Executes the given runnable asynchronously after the other protocol has finished its data loading,
* adding a {@link CompletableFuture} to the list of data to load bound to their protocols.
*
* @param protocolClass protocol class
* @param dependsOn class of the protocol that the data loading depends on
* @param runnable runnable to be executed asynchronously
*/
void addMappingLoaderFuture(Class<? extends Protocol> protocolClass, Class<? extends Protocol> dependsOn, Runnable runnable);
/**
* Returns the data loading future bound to the protocol, or null if all loading is complete.
* The future may or may not have already been completed.
*
* @param protocolClass protocol class
* @return data loading future bound to the protocol, or null if all loading is complete
*/
@Nullable CompletableFuture<Void> getMappingLoaderFuture(Class<? extends Protocol> protocolClass);
/**
* Creates a new packet wrapper instance.
*
* @param packetType packet type, or null if none should be written to the packet (raw id = -1)
* @param buf input buffer
* @param connection user connection
* @return new packet wrapper instance
* @see PacketWrapper#create(PacketType, ByteBuf, UserConnection)
*/
PacketWrapper createPacketWrapper(@Nullable PacketType packetType, @Nullable ByteBuf buf, UserConnection connection);
/**
* Creates a new packet wrapper instance.
*
* @param packetId packet id
* @param buf input buffer
* @param connection user connection
* @return new packet wrapper instance
* @deprecated magic id; prefer using {@link #createPacketWrapper(PacketType, ByteBuf, UserConnection)}
*/
@Deprecated
PacketWrapper createPacketWrapper(int packetId, @Nullable ByteBuf buf, UserConnection connection);
}