ViaVersion/api/src/main/java/com/viaversion/viaversion/api/connection/UserConnection.java

340 lines
11 KiB
Java
Raw Normal View History

/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
2024-01-12 10:01:48 +01:00
* Copyright (C) 2016-2024 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.
*/
2021-04-26 21:35:29 +02:00
package com.viaversion.viaversion.api.connection;
2021-04-26 22:54:43 +02:00
import com.viaversion.viaversion.api.configuration.ViaVersionConfig;
Refactor entity tracking and meta handling This essentially merges the two approaches to the metadata handling from ViaVersion and ViaBackwards and improves on both designs. ViaVersion did not track every single entity, but only those needed (at least in theory) and can work with untracked entities' metadata. It had a very simple method overridden by metadata rewriter implementations, directly operating on the full metadata list and manually handling meta index changes as well as item/block/particle id changes. ViaBackwards on the other hand had to track *every single* entity and threw warnings otherwise - while less prone to errors due to giving obvious warnings in the console, it unnecessarily tracks a lot of entities, and those warnings also annoys users when encountering virtual entity plugins (operating asynchronously and sending update packets while already untracked or not yet tracked). Dedicated MetaHandlers made id changes and filtering a lot easier to read and write. However, the actual metadata list handling and its distribution to handlers was not very well implemented and required a lot of list copying and creation as well as exception throws to cancel individual metadata entries. This version has MetaFilters built with a Builder containing multiple helper functions, and the entity tracking is properly given its own map, hashed by a Protocol's class, to be easily and generically accessible from anywhere with only a Protocol class from the UserConnection, along with more optimized metadata list iteration. The entity tracking is largely unchanged, keeping ViaVersion's approach to not having to track *all* entities (and being able to handle null types in meta handlers). All of this is by no means absolutely perfect, but is much less prone to errors than both previous systems and takes a lot less effort to actually write. A last possible change would be to use a primitive int to object map that is built to be concurrency save for the EntityTracker, tho that would have to be chosen carefully.
2021-05-24 23:24:50 +02:00
import com.viaversion.viaversion.api.data.entity.EntityTracker;
import com.viaversion.viaversion.api.protocol.Protocol;
2021-04-26 21:16:10 +02:00
import com.viaversion.viaversion.api.protocol.packet.PacketTracker;
2021-04-26 22:54:43 +02:00
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.exception.CancelException;
import com.viaversion.viaversion.exception.InformativeException;
import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
Refactor entity tracking and meta handling This essentially merges the two approaches to the metadata handling from ViaVersion and ViaBackwards and improves on both designs. ViaVersion did not track every single entity, but only those needed (at least in theory) and can work with untracked entities' metadata. It had a very simple method overridden by metadata rewriter implementations, directly operating on the full metadata list and manually handling meta index changes as well as item/block/particle id changes. ViaBackwards on the other hand had to track *every single* entity and threw warnings otherwise - while less prone to errors due to giving obvious warnings in the console, it unnecessarily tracks a lot of entities, and those warnings also annoys users when encountering virtual entity plugins (operating asynchronously and sending update packets while already untracked or not yet tracked). Dedicated MetaHandlers made id changes and filtering a lot easier to read and write. However, the actual metadata list handling and its distribution to handlers was not very well implemented and required a lot of list copying and creation as well as exception throws to cancel individual metadata entries. This version has MetaFilters built with a Builder containing multiple helper functions, and the entity tracking is properly given its own map, hashed by a Protocol's class, to be easily and generically accessible from anywhere with only a Protocol class from the UserConnection, along with more optimized metadata list iteration. The entity tracking is largely unchanged, keeping ViaVersion's approach to not having to track *all* entities (and being able to handle null types in meta handlers). All of this is by no means absolutely perfect, but is much less prone to errors than both previous systems and takes a lot less effort to actually write. A last possible change would be to use a primitive int to object map that is built to be concurrency save for the EntityTracker, tho that would have to be chosen carefully.
2021-05-24 23:24:50 +02:00
import java.util.Collection;
import java.util.Map;
import java.util.UUID;
2020-06-07 10:35:27 +02:00
import java.util.function.Function;
import org.checkerframework.checker.nullness.qual.Nullable;
2021-04-26 22:54:43 +02:00
public interface UserConnection {
/**
2020-06-07 11:32:49 +02:00
* Get an object from the storage.
*
* @param objectClass The class of the object to get
2016-05-26 14:54:22 +02:00
* @param <T> The type of the class you want to get.
* @return The requested object
*/
@Nullable <T extends StorableObject> T get(Class<T> objectClass);
/**
2020-06-07 11:32:49 +02:00
* Check if the storage has an object.
*
* @param objectClass The object class to check
* @return True if the object is in the storage
*/
boolean has(Class<? extends StorableObject> objectClass);
2022-04-27 21:06:34 +02:00
/**
* Removes and returns an object from the storage.
*
* @param objectClass class of the object to get
* @param <T> type of the class you want to get
* @return removed storable object if present
*/
@Nullable <T extends StorableObject> T remove(Class<T> objectClass);
/**
2020-06-07 11:32:49 +02:00
* Put an object into the stored objects based on class.
*
* @param object The object to store.
*/
void put(StorableObject object);
Refactor entity tracking and meta handling This essentially merges the two approaches to the metadata handling from ViaVersion and ViaBackwards and improves on both designs. ViaVersion did not track every single entity, but only those needed (at least in theory) and can work with untracked entities' metadata. It had a very simple method overridden by metadata rewriter implementations, directly operating on the full metadata list and manually handling meta index changes as well as item/block/particle id changes. ViaBackwards on the other hand had to track *every single* entity and threw warnings otherwise - while less prone to errors due to giving obvious warnings in the console, it unnecessarily tracks a lot of entities, and those warnings also annoys users when encountering virtual entity plugins (operating asynchronously and sending update packets while already untracked or not yet tracked). Dedicated MetaHandlers made id changes and filtering a lot easier to read and write. However, the actual metadata list handling and its distribution to handlers was not very well implemented and required a lot of list copying and creation as well as exception throws to cancel individual metadata entries. This version has MetaFilters built with a Builder containing multiple helper functions, and the entity tracking is properly given its own map, hashed by a Protocol's class, to be easily and generically accessible from anywhere with only a Protocol class from the UserConnection, along with more optimized metadata list iteration. The entity tracking is largely unchanged, keeping ViaVersion's approach to not having to track *all* entities (and being able to handle null types in meta handlers). All of this is by no means absolutely perfect, but is much less prone to errors than both previous systems and takes a lot less effort to actually write. A last possible change would be to use a primitive int to object map that is built to be concurrency save for the EntityTracker, tho that would have to be chosen carefully.
2021-05-24 23:24:50 +02:00
/**
* Returns a collection of entity trackers currently registered.
*
* @return collection of entity trackers currently registered
*/
Collection<EntityTracker> getEntityTrackers();
/**
* Returns the entity tracker by the given protocol class if present.
*
* @param protocolClass protocol class
* @param <T> entity tracker type
* @return entity tracker if present
*/
@Nullable <T extends EntityTracker> T getEntityTracker(Class<? extends Protocol> protocolClass);
/**
* Adds an entity tracker to the user connection.
* Does not override existing entity trackers.
Refactor entity tracking and meta handling This essentially merges the two approaches to the metadata handling from ViaVersion and ViaBackwards and improves on both designs. ViaVersion did not track every single entity, but only those needed (at least in theory) and can work with untracked entities' metadata. It had a very simple method overridden by metadata rewriter implementations, directly operating on the full metadata list and manually handling meta index changes as well as item/block/particle id changes. ViaBackwards on the other hand had to track *every single* entity and threw warnings otherwise - while less prone to errors due to giving obvious warnings in the console, it unnecessarily tracks a lot of entities, and those warnings also annoys users when encountering virtual entity plugins (operating asynchronously and sending update packets while already untracked or not yet tracked). Dedicated MetaHandlers made id changes and filtering a lot easier to read and write. However, the actual metadata list handling and its distribution to handlers was not very well implemented and required a lot of list copying and creation as well as exception throws to cancel individual metadata entries. This version has MetaFilters built with a Builder containing multiple helper functions, and the entity tracking is properly given its own map, hashed by a Protocol's class, to be easily and generically accessible from anywhere with only a Protocol class from the UserConnection, along with more optimized metadata list iteration. The entity tracking is largely unchanged, keeping ViaVersion's approach to not having to track *all* entities (and being able to handle null types in meta handlers). All of this is by no means absolutely perfect, but is much less prone to errors than both previous systems and takes a lot less effort to actually write. A last possible change would be to use a primitive int to object map that is built to be concurrency save for the EntityTracker, tho that would have to be chosen carefully.
2021-05-24 23:24:50 +02:00
*
* @param protocolClass protocol class
* @param tracker entity tracker
*/
void addEntityTracker(Class<? extends Protocol> protocolClass, EntityTracker tracker);
/**
* Clear stored objects and entity trackers.
*/
default void clearStoredObjects() {
clearStoredObjects(false);
}
/**
* Clear stored objects and entity trackers.
* If cleared for a proxy server switch, some stored objects and tracker data will be retained.
*
* @param isServerSwitch whether the clear is due to a server switch
*/
void clearStoredObjects(boolean isServerSwitch);
/**
* Sends a raw packet to the connection on the current thread.
*
* @param packet raw packet to send
*/
void sendRawPacket(ByteBuf packet);
/**
* Send a raw packet to the player, submitted to the netty event loop.
*
* @param packet raw packet to send
*/
void scheduleSendRawPacket(ByteBuf packet);
/**
2021-04-29 17:31:16 +02:00
* Send a raw packet to the player with returning the future.
*
2021-04-29 17:31:16 +02:00
* @param packet The raw packet to send
* @return ChannelFuture of the packet being sent
*/
2021-04-29 17:31:16 +02:00
ChannelFuture sendRawPacketFuture(ByteBuf packet);
/**
* Returns the user's packet tracker used for the inbuilt packet-limiter.
2020-06-07 11:32:49 +02:00
*
* @return packet tracker
2020-06-07 11:32:49 +02:00
*/
2021-04-26 22:54:43 +02:00
PacketTracker getPacketTracker();
2016-09-26 11:16:20 +02:00
/**
2020-06-07 11:32:49 +02:00
* Disconnect a connection.
*
* @param reason The reason to use, not used if player is not active.
*/
2021-04-26 22:54:43 +02:00
void disconnect(String reason);
2018-08-28 19:02:48 +02:00
2018-09-21 19:46:22 +02:00
/**
* Sends a raw packet to the server on the current thread.
2018-09-21 19:46:22 +02:00
*
* @param packet raw packet to be sent
2018-09-21 19:46:22 +02:00
*/
void sendRawPacketToServer(ByteBuf packet);
2018-09-21 19:46:22 +02:00
/**
* Sends a raw packet to the server, submitted to the netty event loop.
2018-09-21 19:46:22 +02:00
*
* @param packet raw packet to be sent
2018-09-21 19:46:22 +02:00
*/
void scheduleSendRawPacketToServer(ByteBuf packet);
2020-06-07 11:32:49 +02:00
/**
* Monitors serverbound packets and returns whether a packet can/should be processed.
2020-06-07 11:32:49 +02:00
*
* @return false if this packet should be cancelled
*/
boolean checkServerboundPacket();
2020-06-07 11:32:49 +02:00
/**
* Monitors clientbound packets and returns whether a packet can/should be processed.
*
* @return false if this packet should be cancelled
2020-06-07 11:32:49 +02:00
*/
boolean checkClientboundPacket();
/**
* @see #checkClientboundPacket()
* @see #checkServerboundPacket()
*/
default boolean checkIncomingPacket() {
return isClientSide() ? checkClientboundPacket() : checkServerboundPacket();
}
/**
* @see #checkClientboundPacket()
* @see #checkServerboundPacket()
*/
default boolean checkOutgoingPacket() {
return isClientSide() ? checkServerboundPacket() : checkClientboundPacket();
}
2020-06-07 11:32:49 +02:00
/**
* Checks if packets needs transforming.
*
* @return whether packets should be passed through
2020-06-07 11:32:49 +02:00
*/
2021-04-26 22:54:43 +02:00
boolean shouldTransformPacket();
2020-06-07 11:32:49 +02:00
/**
* Transforms the clientbound packet contained in ByteBuf.
2020-06-07 11:32:49 +02:00
*
2020-06-09 17:53:31 +02:00
* @param buf ByteBuf with packet id and packet contents
* @param cancelSupplier function called with original CancelException for generating the Exception when the packet is cancelled
* @throws CancelException if the packet should be cancelled
* @throws InformativeException if packet transforming failed
* @throws Exception if any other processing outside of transforming fails
2020-06-07 11:32:49 +02:00
*/
void transformClientbound(ByteBuf buf, Function<Throwable, Exception> cancelSupplier) throws Exception;
2020-06-07 11:32:49 +02:00
/**
* Transforms the serverbound packet contained in ByteBuf.
2020-06-07 11:32:49 +02:00
*
2020-06-09 17:53:31 +02:00
* @param buf ByteBuf with packet id and packet contents
2020-06-07 11:32:49 +02:00
* @param cancelSupplier Function called with original CancelException for generating the Exception used when
* packet is cancelled
* @throws CancelException if the packet should be cancelled
* @throws InformativeException if packet transforming failed
* @throws Exception if any other processing outside of transforming fails
2020-06-07 11:32:49 +02:00
*/
void transformServerbound(ByteBuf buf, Function<Throwable, Exception> cancelSupplier) throws Exception;
/**
* Transforms the packet depending on whether the connection is clientside or not.
*
* @see #transformClientbound(ByteBuf, Function)
* @see #transformServerbound(ByteBuf, Function)
*/
default void transformOutgoing(ByteBuf buf, Function<Throwable, Exception> cancelSupplier) throws Exception {
if (isClientSide()) {
transformServerbound(buf, cancelSupplier);
} else {
transformClientbound(buf, cancelSupplier);
}
}
/**
* Transforms the packet depending on whether the connection is clientside or not.
*
* @see #transformClientbound(ByteBuf, Function)
* @see #transformServerbound(ByteBuf, Function)
*/
default void transformIncoming(ByteBuf buf, Function<Throwable, Exception> cancelSupplier) throws Exception {
if (isClientSide()) {
transformClientbound(buf, cancelSupplier);
} else {
transformServerbound(buf, cancelSupplier);
}
}
2020-06-07 11:32:49 +02:00
/**
* Returns the internal id incremented for each new connection.
*
* @return internal id
*/
2021-04-26 22:54:43 +02:00
long getId();
/**
* Returns the netty channel if present.
*
* @return netty channel if present
*/
2021-04-26 22:54:43 +02:00
@Nullable Channel getChannel();
/**
* Returns info containing the current protocol state and userdata.
*
* @return info containing the current protocol state and userdata
*/
ProtocolInfo getProtocolInfo();
2020-06-07 12:19:36 +02:00
/**
* Returns a map of stored objects.
*
* @return map of stored objects
* @see #has(Class)
* @see #get(Class)
* @see #put(StorableObject)
*/
Map<Class<?>, StorableObject> getStoredObjects();
/**
* Returns whether the connection has protocols other than the base protocol applied.
*
* @return whether the connection is active
*/
2021-04-26 22:54:43 +02:00
boolean isActive();
2021-04-26 22:54:43 +02:00
void setActive(boolean active);
/**
* Returns whether the connection is pending a disconnect, initiated through {@link #disconnect(String)}.
*
* @return whether the connection is pending a disconnect
*/
2021-04-26 22:54:43 +02:00
boolean isPendingDisconnect();
2021-04-26 22:54:43 +02:00
void setPendingDisconnect(boolean pendingDisconnect);
/**
* Returns whether this is a client-side connection.
* This is a mod integrated into the client itself, or for example a backend Velocity connection.
*
* @return whether this is a client-side connection
*/
2021-04-26 22:54:43 +02:00
boolean isClientSide();
/**
* Returns whether {@link ViaVersionConfig#blockedProtocolVersions()} should be checked for this connection.
*
* @return whether blocked protocols should be applied
*/
2021-04-26 22:54:43 +02:00
boolean shouldApplyBlockProtocol();
/**
* Returns whether the packet limiter applies to this user.
*
* @return whether the packet limiter applies to this user
*/
boolean isPacketLimiterEnabled();
/**
* Sets the status of the packet limiter.
*
* @param packetLimiterEnabled whether the packet limiter should be enabled
*/
void setPacketLimiterEnabled(boolean packetLimiterEnabled);
/**
* Returns a newly generated uuid that will let a packet be passed through without
* transformig its contents if used together with {@link PacketWrapper#PASSTHROUGH_ID}.
*
* @return generated passthrough token
*/
2021-04-26 22:54:43 +02:00
UUID generatePassthroughToken();
}