mirror of
https://github.com/ViaVersion/ViaVersion.git
synced 2024-11-25 11:35:18 +01:00
Optimize/improve Protocol packet mapping
Also makes it possible to work with packet types of different states in a Protocol
This commit is contained in:
parent
cb2165eb93
commit
f5ddc6550d
@ -32,24 +32,41 @@ import com.viaversion.viaversion.api.protocol.packet.PacketType;
|
|||||||
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
||||||
import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType;
|
import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType;
|
||||||
import com.viaversion.viaversion.api.protocol.packet.State;
|
import com.viaversion.viaversion.api.protocol.packet.State;
|
||||||
|
import com.viaversion.viaversion.api.protocol.packet.mapping.PacketMapping;
|
||||||
|
import com.viaversion.viaversion.api.protocol.packet.mapping.PacketMappings;
|
||||||
|
import com.viaversion.viaversion.api.protocol.packet.provider.PacketTypeMap;
|
||||||
|
import com.viaversion.viaversion.api.protocol.packet.provider.PacketTypesProvider;
|
||||||
|
import com.viaversion.viaversion.api.protocol.packet.provider.SimplePacketTypesProvider;
|
||||||
import com.viaversion.viaversion.api.protocol.remapper.PacketHandler;
|
import com.viaversion.viaversion.api.protocol.remapper.PacketHandler;
|
||||||
import com.viaversion.viaversion.exception.CancelException;
|
import com.viaversion.viaversion.exception.CancelException;
|
||||||
import com.viaversion.viaversion.exception.InformativeException;
|
import com.viaversion.viaversion.exception.InformativeException;
|
||||||
import java.util.Arrays;
|
import java.util.Collections;
|
||||||
|
import java.util.EnumMap;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
import java.util.function.Predicate;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
public abstract class AbstractProtocol<C1 extends ClientboundPacketType, C2 extends ClientboundPacketType, S1 extends ServerboundPacketType, S2 extends ServerboundPacketType>
|
/**
|
||||||
implements Protocol<C1, C2, S1, S2> {
|
* Abstract protocol class to handle packet transformation between two protocol versions.
|
||||||
private final Map<Packet, ProtocolPacket> serverbound = new HashMap<>();
|
*
|
||||||
private final Map<Packet, ProtocolPacket> clientbound = new HashMap<>();
|
* @param <C1> unmapped clientbound packet type
|
||||||
private final Map<Class<?>, Object> storedObjects = new HashMap<>(); // currently only used for MetadataRewriters
|
* @param <C2> mapped clientbound packet type
|
||||||
|
* @param <S1> mapped serverbound packet type
|
||||||
|
* @param <S2> unmapped serverbound packet type
|
||||||
|
*/
|
||||||
|
public abstract class AbstractProtocol<C1 extends ClientboundPacketType, C2 extends ClientboundPacketType,
|
||||||
|
S1 extends ServerboundPacketType, S2 extends ServerboundPacketType> implements Protocol<C1, C2, S1, S2> {
|
||||||
protected final Class<C1> unmappedClientboundPacketType;
|
protected final Class<C1> unmappedClientboundPacketType;
|
||||||
protected final Class<C2> mappedClientboundPacketType;
|
protected final Class<C2> mappedClientboundPacketType;
|
||||||
protected final Class<S1> mappedServerboundPacketType;
|
protected final Class<S1> mappedServerboundPacketType;
|
||||||
protected final Class<S2> unmappedServerboundPacketType;
|
protected final Class<S2> unmappedServerboundPacketType;
|
||||||
|
private final PacketTypesProvider<C1, C2, S1, S2> packetTypesProvider;
|
||||||
|
private final PacketMappings serverboundMappings = PacketMappings.arrayMappings();
|
||||||
|
private final PacketMappings clientboundMappings = PacketMappings.arrayMappings();
|
||||||
|
private final Map<Class<?>, Object> storedObjects = new HashMap<>();
|
||||||
private boolean initialized;
|
private boolean initialized;
|
||||||
|
|
||||||
protected AbstractProtocol() {
|
protected AbstractProtocol() {
|
||||||
@ -65,11 +82,12 @@ public abstract class AbstractProtocol<C1 extends ClientboundPacketType, C2 exte
|
|||||||
this.mappedClientboundPacketType = mappedClientboundPacketType;
|
this.mappedClientboundPacketType = mappedClientboundPacketType;
|
||||||
this.mappedServerboundPacketType = mappedServerboundPacketType;
|
this.mappedServerboundPacketType = mappedServerboundPacketType;
|
||||||
this.unmappedServerboundPacketType = unmappedServerboundPacketType;
|
this.unmappedServerboundPacketType = unmappedServerboundPacketType;
|
||||||
|
this.packetTypesProvider = createPacketTypesProvider();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void initialize() {
|
public final void initialize() {
|
||||||
Preconditions.checkArgument(!initialized);
|
Preconditions.checkArgument(!initialized, "Protocol has already been initialized");
|
||||||
initialized = true;
|
initialized = true;
|
||||||
|
|
||||||
registerPackets();
|
registerPackets();
|
||||||
@ -77,62 +95,47 @@ public abstract class AbstractProtocol<C1 extends ClientboundPacketType, C2 exte
|
|||||||
// Register the rest of the ids with no handlers if necessary
|
// Register the rest of the ids with no handlers if necessary
|
||||||
if (unmappedClientboundPacketType != null && mappedClientboundPacketType != null
|
if (unmappedClientboundPacketType != null && mappedClientboundPacketType != null
|
||||||
&& unmappedClientboundPacketType != mappedClientboundPacketType) {
|
&& unmappedClientboundPacketType != mappedClientboundPacketType) {
|
||||||
registerClientboundChannelIdChanges();
|
registerPacketIdChanges(
|
||||||
|
packetTypesProvider.unmappedClientboundPacketTypes(),
|
||||||
|
packetTypesProvider.mappedClientboundPacketTypes(),
|
||||||
|
this::hasRegisteredClientbound,
|
||||||
|
this::registerClientbound
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if (mappedServerboundPacketType != null && unmappedServerboundPacketType != null
|
if (mappedServerboundPacketType != null && unmappedServerboundPacketType != null &&
|
||||||
&& mappedServerboundPacketType != unmappedServerboundPacketType) {
|
mappedServerboundPacketType != unmappedServerboundPacketType) {
|
||||||
registerServerboundChannelIdChanges();
|
registerPacketIdChanges(
|
||||||
|
packetTypesProvider.unmappedServerboundPacketTypes(),
|
||||||
|
packetTypesProvider.mappedServerboundPacketTypes(),
|
||||||
|
this::hasRegisteredServerbound,
|
||||||
|
this::registerServerbound
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void registerClientboundChannelIdChanges() {
|
private <U extends PacketType, M extends PacketType> void registerPacketIdChanges(
|
||||||
C2[] newConstants = mappedClientboundPacketType.getEnumConstants();
|
Map<State, PacketTypeMap<U>> unmappedPacketTypes,
|
||||||
Map<String, C2> newClientboundPackets = new HashMap<>(newConstants.length);
|
Map<State, PacketTypeMap<M>> mappedPacketTypes,
|
||||||
for (C2 newConstant : newConstants) {
|
Predicate<U> registeredPredicate,
|
||||||
newClientboundPackets.put(newConstant.getName(), newConstant);
|
BiConsumer<U, M> registerConsumer
|
||||||
}
|
) {
|
||||||
|
for (Map.Entry<State, PacketTypeMap<M>> entry : mappedPacketTypes.entrySet()) {
|
||||||
for (C1 packet : unmappedClientboundPacketType.getEnumConstants()) {
|
PacketTypeMap<M> mappedTypes = entry.getValue();
|
||||||
C2 mappedPacket = newClientboundPackets.get(packet.getName());
|
for (U unmappedType : unmappedPacketTypes.get(entry.getKey()).types()) {
|
||||||
if (mappedPacket == null) {
|
M mappedType = mappedTypes.typeByName(unmappedType.getName());
|
||||||
// Packet doesn't exist on new client
|
if (mappedType == null) {
|
||||||
Preconditions.checkArgument(hasRegisteredClientbound(packet),
|
// No mapped packet of the same name exists
|
||||||
"Packet " + packet + " in " + getClass().getSimpleName() + " has no mapping - it needs to be manually cancelled or remapped!");
|
Preconditions.checkArgument(registeredPredicate.test(unmappedType),
|
||||||
|
"Packet %s in %s has no mapping - it needs to be manually cancelled or remapped", unmappedType, getClass());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hasRegisteredClientbound(packet)) {
|
// Register if no custom handler exists and ids are different
|
||||||
registerClientbound(packet, mappedPacket);
|
if (unmappedType.getId() != mappedType.getId() && !registeredPredicate.test(unmappedType)) {
|
||||||
|
registerConsumer.accept(unmappedType, mappedType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void registerServerboundChannelIdChanges() {
|
|
||||||
S1[] oldConstants = mappedServerboundPacketType.getEnumConstants();
|
|
||||||
Map<String, S1> oldServerboundConstants = new HashMap<>(oldConstants.length);
|
|
||||||
for (S1 oldConstant : oldConstants) {
|
|
||||||
oldServerboundConstants.put(oldConstant.getName(), oldConstant);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (S2 packet : unmappedServerboundPacketType.getEnumConstants()) {
|
|
||||||
S1 mappedPacket = oldServerboundConstants.get(packet.getName());
|
|
||||||
if (mappedPacket == null) {
|
|
||||||
// Packet doesn't exist on old server
|
|
||||||
Preconditions.checkArgument(hasRegisteredServerbound(packet),
|
|
||||||
"Packet " + packet + " in " + getClass().getSimpleName() + " has no mapping - it needs to be manually cancelled or remapped!");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!hasRegisteredServerbound(packet)) {
|
|
||||||
registerServerbound(packet, mappedPacket);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register the packets for this protocol. To be overriden.
|
|
||||||
*/
|
|
||||||
protected void registerPackets() {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -141,6 +144,12 @@ public abstract class AbstractProtocol<C1 extends ClientboundPacketType, C2 exte
|
|||||||
onMappingDataLoaded();
|
onMappingDataLoaded();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register the packets for this protocol. To be overriden.
|
||||||
|
*/
|
||||||
|
protected void registerPackets() {
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called after {@link #loadMappingData()} is called; load extra mapping data for the protocol.
|
* Called after {@link #loadMappingData()} is called; load extra mapping data for the protocol.
|
||||||
* <p>
|
* <p>
|
||||||
@ -153,65 +162,70 @@ public abstract class AbstractProtocol<C1 extends ClientboundPacketType, C2 exte
|
|||||||
connection.addEntityTracker(this.getClass(), tracker);
|
connection.addEntityTracker(this.getClass(), tracker);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected PacketTypesProvider<C1, C2, S1, S2> createPacketTypesProvider() {
|
||||||
|
return new SimplePacketTypesProvider<>(
|
||||||
|
packetTypeMap(unmappedClientboundPacketType),
|
||||||
|
packetTypeMap(mappedClientboundPacketType),
|
||||||
|
packetTypeMap(mappedServerboundPacketType),
|
||||||
|
packetTypeMap(unmappedServerboundPacketType)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private <P extends PacketType> Map<State, PacketTypeMap<P>> packetTypeMap(Class<P> packetTypeClass) {
|
||||||
|
if (packetTypeClass != null) {
|
||||||
|
Map<State, PacketTypeMap<P>> map = new EnumMap<>(State.class);
|
||||||
|
map.put(State.PLAY, PacketTypeMap.of(packetTypeClass));
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
return Collections.emptyMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void registerServerbound(State state, int unmappedPacketId, int mappedPacketId, PacketHandler handler, boolean override) {
|
public void registerServerbound(State state, int unmappedPacketId, int mappedPacketId, PacketHandler handler, boolean override) {
|
||||||
ProtocolPacket protocolPacket = new ProtocolPacket(state, unmappedPacketId, mappedPacketId, handler);
|
Preconditions.checkArgument(unmappedPacketId != -1, "Unmapped packet id cannot be -1");
|
||||||
Packet packet = new Packet(state, mappedPacketId);
|
PacketMapping packetMapping = PacketMapping.of(mappedPacketId, handler);
|
||||||
if (!override && serverbound.containsKey(packet)) {
|
if (!override && serverboundMappings.hasMapping(state, unmappedPacketId)) {
|
||||||
Via.getPlatform().getLogger().log(Level.WARNING, packet + " already registered!" +
|
Via.getPlatform().getLogger().log(Level.WARNING, unmappedPacketId + " already registered!" +
|
||||||
" If this override is intentional, set override to true. Stacktrace: ", new Exception());
|
" If this override is intentional, set override to true. Stacktrace: ", new Exception());
|
||||||
}
|
}
|
||||||
serverbound.put(packet, protocolPacket);
|
serverboundMappings.addMapping(state, unmappedPacketId, packetMapping);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void cancelServerbound(State state, int unmappedPacketId, int mappedPacketId) {
|
public void cancelServerbound(State state, int unmappedPacketId) {
|
||||||
registerServerbound(state, unmappedPacketId, mappedPacketId, PacketWrapper::cancel);
|
registerServerbound(state, unmappedPacketId, unmappedPacketId, PacketWrapper::cancel);
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void cancelServerbound(State state, int mappedPacketId) {
|
|
||||||
cancelServerbound(state, -1, mappedPacketId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void cancelClientbound(State state, int unmappedPacketId, int mappedPacketId) {
|
|
||||||
registerClientbound(state, unmappedPacketId, mappedPacketId, PacketWrapper::cancel);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void cancelClientbound(State state, int unmappedPacketId) {
|
|
||||||
cancelClientbound(state, unmappedPacketId, -1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void registerClientbound(State state, int unmappedPacketId, int mappedPacketId, PacketHandler handler, boolean override) {
|
public void registerClientbound(State state, int unmappedPacketId, int mappedPacketId, PacketHandler handler, boolean override) {
|
||||||
ProtocolPacket protocolPacket = new ProtocolPacket(state, unmappedPacketId, mappedPacketId, handler);
|
Preconditions.checkArgument(unmappedPacketId != -1, "Unmapped packet id cannot be -1");
|
||||||
Packet packet = new Packet(state, unmappedPacketId);
|
PacketMapping packetMapping = PacketMapping.of(mappedPacketId, handler);
|
||||||
if (!override && clientbound.containsKey(packet)) {
|
if (!override && clientboundMappings.hasMapping(state, unmappedPacketId)) {
|
||||||
Via.getPlatform().getLogger().log(Level.WARNING, packet + " already registered!" +
|
Via.getPlatform().getLogger().log(Level.WARNING, unmappedPacketId + " already registered!" +
|
||||||
" If override is intentional, set override to true. Stacktrace: ", new Exception());
|
" If override is intentional, set override to true. Stacktrace: ", new Exception());
|
||||||
}
|
}
|
||||||
clientbound.put(packet, protocolPacket);
|
clientboundMappings.addMapping(state, unmappedPacketId, packetMapping);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cancelClientbound(State state, int unmappedPacketId) {
|
||||||
|
registerClientbound(state, unmappedPacketId, unmappedPacketId, PacketWrapper::cancel);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void registerClientbound(C1 packetType, @Nullable PacketHandler handler) {
|
public void registerClientbound(C1 packetType, @Nullable PacketHandler handler) {
|
||||||
checkPacketType(packetType, unmappedClientboundPacketType == null || packetType.getClass() == unmappedClientboundPacketType);
|
PacketTypeMap<C2> mappedPacketTypes = packetTypesProvider.mappedClientboundPacketTypes().get(packetType.state());
|
||||||
|
C2 mappedPacketType = mappedPacketType(packetType, mappedPacketTypes, unmappedClientboundPacketType, mappedClientboundPacketType);
|
||||||
//noinspection unchecked
|
registerClientbound(packetType, mappedPacketType, handler);
|
||||||
C2 mappedPacket = unmappedClientboundPacketType == mappedClientboundPacketType ? (C2) packetType
|
|
||||||
: Arrays.stream(mappedClientboundPacketType.getEnumConstants()).filter(en -> en.getName().equals(packetType.getName())).findAny().orElse(null);
|
|
||||||
Preconditions.checkNotNull(mappedPacket, "Packet type " + packetType + " in " + packetType.getClass().getSimpleName() + " could not be automatically mapped!");
|
|
||||||
|
|
||||||
registerClientbound(packetType, mappedPacket, handler);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void registerClientbound(C1 packetType, @Nullable C2 mappedPacketType, @Nullable PacketHandler handler, boolean override) {
|
public void registerClientbound(C1 packetType, @Nullable C2 mappedPacketType, @Nullable PacketHandler handler, boolean override) {
|
||||||
register(clientbound, packetType, mappedPacketType, unmappedClientboundPacketType, mappedClientboundPacketType, handler, override);
|
register(clientboundMappings, packetType, mappedPacketType, unmappedClientboundPacketType, mappedClientboundPacketType, handler, override);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -221,19 +235,14 @@ public abstract class AbstractProtocol<C1 extends ClientboundPacketType, C2 exte
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void registerServerbound(S2 packetType, @Nullable PacketHandler handler) {
|
public void registerServerbound(S2 packetType, @Nullable PacketHandler handler) {
|
||||||
checkPacketType(packetType, unmappedServerboundPacketType == null || packetType.getClass() == unmappedServerboundPacketType);
|
PacketTypeMap<S1> mappedPacketTypes = packetTypesProvider.mappedServerboundPacketTypes().get(packetType.state());
|
||||||
|
S1 mappedPacketType = mappedPacketType(packetType, mappedPacketTypes, unmappedServerboundPacketType, mappedServerboundPacketType);
|
||||||
//noinspection unchecked
|
registerServerbound(packetType, mappedPacketType, handler);
|
||||||
S1 mappedPacket = mappedServerboundPacketType == unmappedServerboundPacketType ? (S1) packetType
|
|
||||||
: Arrays.stream(mappedServerboundPacketType.getEnumConstants()).filter(en -> en.getName().equals(packetType.getName())).findAny().orElse(null);
|
|
||||||
Preconditions.checkNotNull(mappedPacket, "Packet type " + packetType + " in " + packetType.getClass().getSimpleName() + " could not be automatically mapped!");
|
|
||||||
|
|
||||||
registerServerbound(packetType, mappedPacket, handler);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void registerServerbound(S2 packetType, @Nullable S1 mappedPacketType, @Nullable PacketHandler handler, boolean override) {
|
public void registerServerbound(S2 packetType, @Nullable S1 mappedPacketType, @Nullable PacketHandler handler, boolean override) {
|
||||||
register(serverbound, packetType, mappedPacketType, unmappedServerboundPacketType, mappedServerboundPacketType, handler, override);
|
register(serverboundMappings, packetType, mappedPacketType, unmappedServerboundPacketType, mappedServerboundPacketType, handler, override);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -241,66 +250,64 @@ public abstract class AbstractProtocol<C1 extends ClientboundPacketType, C2 exte
|
|||||||
registerServerbound(packetType, null, PacketWrapper::cancel);
|
registerServerbound(packetType, null, PacketWrapper::cancel);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void register(Map<Packet, ProtocolPacket> packetMap, PacketType packetType, @Nullable PacketType mappedPacketType,
|
private void register(PacketMappings packetMappings, PacketType packetType, @Nullable PacketType mappedPacketType,
|
||||||
Class<? extends PacketType> unmappedPacketEnum, Class<? extends PacketType> mappedPacketEnum,
|
Class<? extends PacketType> unmappedPacketClass, Class<? extends PacketType> mappedPacketClass,
|
||||||
@Nullable PacketHandler handler, boolean override) {
|
@Nullable PacketHandler handler, boolean override) {
|
||||||
checkPacketType(packetType, unmappedPacketEnum == null || packetType.getClass() == unmappedPacketEnum);
|
checkPacketType(packetType, unmappedPacketClass == null || unmappedPacketClass.isInstance(packetType));
|
||||||
checkPacketType(mappedPacketType, mappedPacketType == null || mappedPacketEnum == null || mappedPacketType.getClass() == mappedPacketEnum);
|
if (mappedPacketType != null) {
|
||||||
Preconditions.checkArgument(mappedPacketType == null || packetType.state() == mappedPacketType.state(), "Packet type state does not match mapped packet type state");
|
checkPacketType(mappedPacketType, mappedPacketClass == null || mappedPacketClass.isInstance(mappedPacketType));
|
||||||
|
Preconditions.checkArgument(packetType.state() == mappedPacketType.state(),
|
||||||
|
"Packet type state does not match mapped packet type state");
|
||||||
|
Preconditions.checkArgument(packetType.direction() == mappedPacketType.direction(),
|
||||||
|
"Packet type direction does not match mapped packet type state");
|
||||||
|
}
|
||||||
|
|
||||||
ProtocolPacket protocolPacket = new ProtocolPacket(packetType.state(), packetType, mappedPacketType, handler);
|
PacketMapping packetMapping = PacketMapping.of(mappedPacketType, handler);
|
||||||
Packet packet = new Packet(packetType.state(), packetType.getId());
|
if (!override && packetMappings.hasMapping(packetType)) {
|
||||||
if (!override && packetMap.containsKey(packet)) {
|
Via.getPlatform().getLogger().log(Level.WARNING, packetType + " already registered!" +
|
||||||
Via.getPlatform().getLogger().log(Level.WARNING, packet + " already registered!" +
|
|
||||||
" If override is intentional, set override to true. Stacktrace: ", new Exception());
|
" If override is intentional, set override to true. Stacktrace: ", new Exception());
|
||||||
}
|
}
|
||||||
packetMap.put(packet, protocolPacket);
|
packetMappings.addMapping(packetType, packetMapping);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private static <U extends PacketType, M extends PacketType> M mappedPacketType(U packetType, PacketTypeMap<M> mappedTypes, Class<U> unmappedPacketTypeClass, Class<M> mappedPacketTypeClass) {
|
||||||
public boolean hasRegisteredClientbound(C1 packetType) {
|
Preconditions.checkNotNull(packetType);
|
||||||
return hasRegisteredClientbound(packetType.state(), packetType.getId());
|
checkPacketType(packetType, unmappedPacketTypeClass == null || unmappedPacketTypeClass.isInstance(packetType));
|
||||||
|
if (unmappedPacketTypeClass == mappedPacketTypeClass) {
|
||||||
|
//noinspection unchecked
|
||||||
|
return (M) packetType;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
Preconditions.checkNotNull(mappedTypes, "Mapped packet types not provided for state %s of type class %s", packetType.state(), mappedPacketTypeClass);
|
||||||
public boolean hasRegisteredServerbound(S2 packetType) {
|
M mappedType = mappedTypes.typeByName(packetType.getName());
|
||||||
return hasRegisteredServerbound(packetType.state(), packetType.getId());
|
if (mappedType != null) {
|
||||||
|
return mappedType;
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException("Packet type " + packetType + " in " + packetType.getClass().getSimpleName() + " could not be automatically mapped!");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasRegisteredClientbound(State state, int unmappedPacketId) {
|
public boolean hasRegisteredClientbound(State state, int unmappedPacketId) {
|
||||||
Packet packet = new Packet(state, unmappedPacketId);
|
return clientboundMappings.hasMapping(state, unmappedPacketId);
|
||||||
return clientbound.containsKey(packet);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasRegisteredServerbound(State state, int unmappedPacketId) {
|
public boolean hasRegisteredServerbound(State state, int unmappedPacketId) {
|
||||||
Packet packet = new Packet(state, unmappedPacketId);
|
return serverboundMappings.hasMapping(state, unmappedPacketId);
|
||||||
return serverbound.containsKey(packet);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void transform(Direction direction, State state, PacketWrapper packetWrapper) throws Exception {
|
public void transform(Direction direction, State state, PacketWrapper packetWrapper) throws Exception {
|
||||||
Packet statePacket = new Packet(state, packetWrapper.getId());
|
PacketMappings mappings = direction == Direction.CLIENTBOUND ? clientboundMappings : serverboundMappings;
|
||||||
Map<Packet, ProtocolPacket> packetMap = direction == Direction.CLIENTBOUND ? clientbound : serverbound;
|
int unmappedId = packetWrapper.getId();
|
||||||
ProtocolPacket protocolPacket = packetMap.get(statePacket);
|
PacketMapping packetMapping = mappings.mappedPacket(state, unmappedId);
|
||||||
if (protocolPacket == null) {
|
if (packetMapping == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write packet id
|
// Change packet id and apply remapping
|
||||||
int unmappedId = packetWrapper.getId();
|
packetMapping.applyType(packetWrapper);
|
||||||
if (protocolPacket.isMappedOverTypes()) {
|
PacketHandler handler = packetMapping.handler();
|
||||||
packetWrapper.setPacketType(protocolPacket.getMappedPacketType());
|
|
||||||
} else {
|
|
||||||
int mappedId = direction == Direction.CLIENTBOUND ? protocolPacket.getNewId() : protocolPacket.getOldId();
|
|
||||||
if (unmappedId != mappedId) {
|
|
||||||
//noinspection deprecation
|
|
||||||
packetWrapper.setId(mappedId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PacketHandler handler = protocolPacket.getRemapper();
|
|
||||||
if (handler != null) {
|
if (handler != null) {
|
||||||
try {
|
try {
|
||||||
handler.handle(packetWrapper);
|
handler.handle(packetWrapper);
|
||||||
@ -333,10 +340,8 @@ public abstract class AbstractProtocol<C1 extends ClientboundPacketType, C2 exte
|
|||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
|
|
||||||
Class<? extends PacketType> packetTypeClass = state == State.PLAY ? (direction == Direction.CLIENTBOUND ? unmappedClientboundPacketType : unmappedServerboundPacketType) : null;
|
PacketType packetType = direction == Direction.CLIENTBOUND ? unmappedClientboundPacketType(state, unmappedPacketId) : unmappedServerboundPacketType(state, unmappedPacketId);
|
||||||
if (packetTypeClass != null) {
|
if (packetType != null) {
|
||||||
PacketType[] enumConstants = packetTypeClass.getEnumConstants();
|
|
||||||
PacketType packetType = unmappedPacketId < enumConstants.length && unmappedPacketId >= 0 ? enumConstants[unmappedPacketId] : null;
|
|
||||||
Via.getPlatform().getLogger().warning("ERROR IN " + getClass().getSimpleName() + " IN REMAP OF " + packetType + " (" + toNiceHex(unmappedPacketId) + ")");
|
Via.getPlatform().getLogger().warning("ERROR IN " + getClass().getSimpleName() + " IN REMAP OF " + packetType + " (" + toNiceHex(unmappedPacketId) + ")");
|
||||||
} else {
|
} else {
|
||||||
Via.getPlatform().getLogger().warning("ERROR IN " + getClass().getSimpleName()
|
Via.getPlatform().getLogger().warning("ERROR IN " + getClass().getSimpleName()
|
||||||
@ -345,6 +350,16 @@ public abstract class AbstractProtocol<C1 extends ClientboundPacketType, C2 exte
|
|||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private @Nullable C1 unmappedClientboundPacketType(final State state, final int packetId) {
|
||||||
|
PacketTypeMap<C1> map = packetTypesProvider.unmappedClientboundPacketTypes().get(state);
|
||||||
|
return map != null ? map.typeById(packetId) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private @Nullable S2 unmappedServerboundPacketType(final State state, final int packetId) {
|
||||||
|
PacketTypeMap<S2> map = packetTypesProvider.unmappedServerboundPacketTypes().get(state);
|
||||||
|
return map != null ? map.typeById(packetId) : null;
|
||||||
|
}
|
||||||
|
|
||||||
public static String toNiceHex(int id) {
|
public static String toNiceHex(int id) {
|
||||||
String hex = Integer.toHexString(id).toUpperCase();
|
String hex = Integer.toHexString(id).toUpperCase();
|
||||||
return (hex.length() == 1 ? "0x0" : "0x") + hex;
|
return (hex.length() == 1 ? "0x0" : "0x") + hex;
|
||||||
@ -355,9 +370,9 @@ public abstract class AbstractProtocol<C1 extends ClientboundPacketType, C2 exte
|
|||||||
* @param isValid expression to check the packet's validity
|
* @param isValid expression to check the packet's validity
|
||||||
* @throws IllegalArgumentException if the given expression is not met
|
* @throws IllegalArgumentException if the given expression is not met
|
||||||
*/
|
*/
|
||||||
private void checkPacketType(PacketType packetType, boolean isValid) {
|
private static void checkPacketType(PacketType packetType, boolean isValid) {
|
||||||
if (!isValid) {
|
if (!isValid) {
|
||||||
throw new IllegalArgumentException("Packet type " + packetType + " in " + packetType.getClass().getSimpleName() + " is taken from the wrong packet type class");
|
throw new IllegalArgumentException("Packet type " + packetType + " in " + packetType.getClass().getSimpleName() + " is taken from the wrong packet types class");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -372,145 +387,12 @@ public abstract class AbstractProtocol<C1 extends ClientboundPacketType, C2 exte
|
|||||||
storedObjects.put(object.getClass(), object);
|
storedObjects.put(object.getClass(), object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PacketTypesProvider<C1, C2, S1, S2> packetTypesProvider() {
|
||||||
|
return packetTypesProvider;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "Protocol:" + getClass().getSimpleName();
|
return "Protocol:" + getClass().getSimpleName();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class Packet {
|
|
||||||
private final State state;
|
|
||||||
private final int packetId;
|
|
||||||
|
|
||||||
public Packet(State state, int packetId) {
|
|
||||||
this.state = state;
|
|
||||||
this.packetId = packetId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public State getState() {
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getPacketId() {
|
|
||||||
return packetId;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "Packet{" + "state=" + state + ", packetId=" + packetId + '}';
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) return true;
|
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
|
||||||
Packet that = (Packet) o;
|
|
||||||
return packetId == that.packetId && state == that.state;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
int result = state != null ? state.hashCode() : 0;
|
|
||||||
result = 31 * result + packetId;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final class ProtocolPacket {
|
|
||||||
private final State state;
|
|
||||||
private final int oldId;
|
|
||||||
private final int newId;
|
|
||||||
private final PacketType unmappedPacketType;
|
|
||||||
private final PacketType mappedPacketType;
|
|
||||||
private final PacketHandler handler;
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
public ProtocolPacket(State state, int oldId, int newId, @Nullable PacketHandler handler) {
|
|
||||||
this.state = state;
|
|
||||||
this.oldId = oldId;
|
|
||||||
this.newId = newId;
|
|
||||||
this.handler = handler;
|
|
||||||
this.unmappedPacketType = null;
|
|
||||||
this.mappedPacketType = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ProtocolPacket(State state, PacketType unmappedPacketType, @Nullable PacketType mappedPacketType, @Nullable PacketHandler handler) {
|
|
||||||
this.state = state;
|
|
||||||
this.unmappedPacketType = unmappedPacketType;
|
|
||||||
if (unmappedPacketType.direction() == Direction.CLIENTBOUND) {
|
|
||||||
this.oldId = unmappedPacketType.getId();
|
|
||||||
this.newId = mappedPacketType != null ? mappedPacketType.getId() : -1;
|
|
||||||
} else {
|
|
||||||
// Serverbound switcheroo in old vs. new id caused issues and was counterintuitive
|
|
||||||
this.oldId = mappedPacketType != null ? mappedPacketType.getId() : -1;
|
|
||||||
this.newId = unmappedPacketType.getId();
|
|
||||||
}
|
|
||||||
this.mappedPacketType = mappedPacketType;
|
|
||||||
this.handler = handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
public State getState() {
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
public int getOldId() {
|
|
||||||
return oldId;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
public int getNewId() {
|
|
||||||
return newId;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the unmapped packet type, or null if mapped over ids.
|
|
||||||
* This is NOT the same as calling {@link #getOldId()} (think of unmapped vs. old in 1.17→1.16).
|
|
||||||
*
|
|
||||||
* @return unmapped packet type, or null if mapped over ids
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
public PacketType getUnmappedPacketType() {
|
|
||||||
return unmappedPacketType;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the mapped packet type, or null if mapped over ids or mapped to no packet type.
|
|
||||||
* This is NOT the same as calling {@link #getNewId()} (think of mapped vs. new in 1.17→1.16).
|
|
||||||
*
|
|
||||||
* @return new packet type, or null if mapped over ids or mapped to no packet type
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
public PacketType getMappedPacketType() {
|
|
||||||
return mappedPacketType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isMappedOverTypes() {
|
|
||||||
return unmappedPacketType != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public PacketHandler getRemapper() {
|
|
||||||
return handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "ProtocolPacket{" +
|
|
||||||
"state=" + state +
|
|
||||||
", oldId=" + oldId +
|
|
||||||
", newId=" + newId +
|
|
||||||
", unmappedPacketType=" + unmappedPacketType +
|
|
||||||
", mappedPacketType=" + mappedPacketType +
|
|
||||||
", handler=" + handler +
|
|
||||||
'}';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<Packet, ProtocolPacket> getClientbound() {
|
|
||||||
return clientbound;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<Packet, ProtocolPacket> getServerbound() {
|
|
||||||
return serverbound;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -195,7 +195,9 @@ public interface Protocol<C1 extends ClientboundPacketType, C2 extends Clientbou
|
|||||||
* @param packetType clientbound packet type
|
* @param packetType clientbound packet type
|
||||||
* @return true if already registered
|
* @return true if already registered
|
||||||
*/
|
*/
|
||||||
boolean hasRegisteredClientbound(C1 packetType);
|
default boolean hasRegisteredClientbound(C1 packetType) {
|
||||||
|
return hasRegisteredClientbound(packetType.state(), packetType.getId());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if a serverbound packet has already been registered.
|
* Checks if a serverbound packet has already been registered.
|
||||||
@ -203,7 +205,9 @@ public interface Protocol<C1 extends ClientboundPacketType, C2 extends Clientbou
|
|||||||
* @param packetType serverbound packet type
|
* @param packetType serverbound packet type
|
||||||
* @return true if already registered
|
* @return true if already registered
|
||||||
*/
|
*/
|
||||||
boolean hasRegisteredServerbound(S2 packetType);
|
default boolean hasRegisteredServerbound(S2 packetType) {
|
||||||
|
return hasRegisteredServerbound(packetType.state(), packetType.getId());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if a clientbound packet has already been registered.
|
* Checks if a clientbound packet has already been registered.
|
||||||
@ -338,13 +342,17 @@ public interface Protocol<C1 extends ClientboundPacketType, C2 extends Clientbou
|
|||||||
* @deprecated use {@link #cancelServerbound(State, int)}
|
* @deprecated use {@link #cancelServerbound(State, int)}
|
||||||
*/
|
*/
|
||||||
@Deprecated/*(forRemoval = true)*/
|
@Deprecated/*(forRemoval = true)*/
|
||||||
void cancelServerbound(State state, int unmappedPacketId, int mappedPacketId);
|
default void cancelServerbound(State state, int unmappedPacketId, int mappedPacketId) {
|
||||||
|
cancelServerbound(state, unmappedPacketId);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated use {@link #cancelClientbound(State, int)}
|
* @deprecated use {@link #cancelClientbound(State, int)}
|
||||||
*/
|
*/
|
||||||
@Deprecated/*(forRemoval = true)*/
|
@Deprecated/*(forRemoval = true)*/
|
||||||
void cancelClientbound(State state, int unmappedPacketId, int mappedPacketId);
|
default void cancelClientbound(State state, int unmappedPacketId, int mappedPacketId) {
|
||||||
|
cancelClientbound(state, unmappedPacketId);
|
||||||
|
}
|
||||||
|
|
||||||
@Deprecated/*(forRemoval = true)*/
|
@Deprecated/*(forRemoval = true)*/
|
||||||
default void registerClientbound(State state, int unmappedPacketId, int mappedPacketId, PacketRemapper packetRemapper) {
|
default void registerClientbound(State state, int unmappedPacketId, int mappedPacketId, PacketRemapper packetRemapper) {
|
||||||
|
@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
|
||||||
|
* Copyright (C) 2023 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.packet.mapping;
|
||||||
|
|
||||||
|
import com.viaversion.viaversion.api.protocol.packet.State;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
|
final class PacketArrayMappings implements PacketMappings {
|
||||||
|
private final PacketMapping[][] packets = new PacketMapping[State.values().length][];
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable PacketMapping mappedPacket(final State state, final int unmappedId) {
|
||||||
|
final PacketMapping[] packets = this.packets[state.ordinal()];
|
||||||
|
if (packets != null && unmappedId >= 0 && unmappedId < packets.length) {
|
||||||
|
return packets[unmappedId];
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addMapping(final State state, final int unmappedId, final PacketMapping mapping) {
|
||||||
|
final int ordinal = state.ordinal();
|
||||||
|
PacketMapping[] packets = this.packets[ordinal];
|
||||||
|
if (packets == null) {
|
||||||
|
packets = new PacketMapping[unmappedId + 8];
|
||||||
|
this.packets[ordinal] = packets;
|
||||||
|
} else if (unmappedId >= packets.length) {
|
||||||
|
packets = Arrays.copyOf(packets, unmappedId + 32);
|
||||||
|
this.packets[ordinal] = packets;
|
||||||
|
}
|
||||||
|
|
||||||
|
packets[unmappedId] = mapping;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
|
||||||
|
* Copyright (C) 2023 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.packet.mapping;
|
||||||
|
|
||||||
|
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
||||||
|
import com.viaversion.viaversion.api.protocol.remapper.PacketHandler;
|
||||||
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
|
final class PacketIdMapping implements PacketMapping {
|
||||||
|
private final int mappedPacketId;
|
||||||
|
private final PacketHandler handler;
|
||||||
|
|
||||||
|
PacketIdMapping(int mappedPacketId, @Nullable PacketHandler handler) {
|
||||||
|
this.mappedPacketId = mappedPacketId;
|
||||||
|
this.handler = handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void applyType(final PacketWrapper wrapper) {
|
||||||
|
//noinspection deprecation
|
||||||
|
wrapper.setId(mappedPacketId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable PacketHandler handler() {
|
||||||
|
return handler;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
|
||||||
|
* Copyright (C) 2016-2023 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.packet.mapping;
|
||||||
|
|
||||||
|
import com.viaversion.viaversion.api.protocol.packet.PacketType;
|
||||||
|
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
||||||
|
import com.viaversion.viaversion.api.protocol.remapper.PacketHandler;
|
||||||
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Packet mapping over packet types or ids containing a packet transformer.
|
||||||
|
*/
|
||||||
|
public interface PacketMapping {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies the changed packet type or id to the given packet wrapper.
|
||||||
|
*
|
||||||
|
* @param wrapper packet wrapper
|
||||||
|
*/
|
||||||
|
void applyType(PacketWrapper wrapper);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a packet transformer to transform a packet from one protocol version to another.
|
||||||
|
*
|
||||||
|
* @return packet transformer, or null if no action has to be taken
|
||||||
|
*/
|
||||||
|
@Nullable PacketHandler handler();
|
||||||
|
|
||||||
|
static PacketMapping of(final int mappedPacketId, @Nullable final PacketHandler handler) {
|
||||||
|
return new PacketIdMapping(mappedPacketId, handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
static PacketMapping of(@Nullable final PacketType mappedPacketType, @Nullable final PacketHandler handler) {
|
||||||
|
return new PacketTypeMapping(mappedPacketType, handler);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
|
||||||
|
* Copyright (C) 2016-2023 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.packet.mapping;
|
||||||
|
|
||||||
|
import com.viaversion.viaversion.api.protocol.packet.PacketType;
|
||||||
|
import com.viaversion.viaversion.api.protocol.packet.State;
|
||||||
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mappings to transform packets between two protocol versions.
|
||||||
|
*/
|
||||||
|
public interface PacketMappings {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a packet mapping for the given packet.
|
||||||
|
*
|
||||||
|
* @param state protocol stae
|
||||||
|
* @param unmappedId unmapped packet id
|
||||||
|
* @return packet mapping if present
|
||||||
|
*/
|
||||||
|
@Nullable PacketMapping mappedPacket(State state, int unmappedId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the given packet type has a mapping.
|
||||||
|
*
|
||||||
|
* @param packetType unmapped packet type
|
||||||
|
* @return whether the given packet type has a mapping
|
||||||
|
*/
|
||||||
|
default boolean hasMapping(PacketType packetType) {
|
||||||
|
return mappedPacket(packetType.state(), packetType.getId()) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the given packet type has a mapping.
|
||||||
|
*
|
||||||
|
* @param state protocol state
|
||||||
|
* @param unmappedId unmapped packet id
|
||||||
|
* @return whether the given packet type has a mapping
|
||||||
|
*/
|
||||||
|
default boolean hasMapping(State state, int unmappedId) {
|
||||||
|
return mappedPacket(state, unmappedId) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a packet mapping.
|
||||||
|
*
|
||||||
|
* @param packetType unmapped packet type
|
||||||
|
* @param mapping packet mapping
|
||||||
|
*/
|
||||||
|
default void addMapping(PacketType packetType, PacketMapping mapping) {
|
||||||
|
addMapping(packetType.state(), packetType.getId(), mapping);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a packet mapping.
|
||||||
|
*
|
||||||
|
* @param state protocol state
|
||||||
|
* @param unmappedId unmapped packet id
|
||||||
|
* @param mapping packet mapping
|
||||||
|
*/
|
||||||
|
void addMapping(State state, int unmappedId, PacketMapping mapping);
|
||||||
|
|
||||||
|
static PacketMappings arrayMappings() {
|
||||||
|
return new PacketArrayMappings();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
|
||||||
|
* Copyright (C) 2023 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.packet.mapping;
|
||||||
|
|
||||||
|
import com.viaversion.viaversion.api.protocol.packet.PacketType;
|
||||||
|
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
||||||
|
import com.viaversion.viaversion.api.protocol.remapper.PacketHandler;
|
||||||
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
|
final class PacketTypeMapping implements PacketMapping {
|
||||||
|
private final PacketType mappedPacketType;
|
||||||
|
private final PacketHandler handler;
|
||||||
|
|
||||||
|
PacketTypeMapping(@Nullable PacketType mappedPacketType, @Nullable PacketHandler handler) {
|
||||||
|
this.mappedPacketType = mappedPacketType;
|
||||||
|
this.handler = handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void applyType(PacketWrapper wrapper) {
|
||||||
|
if (mappedPacketType != null) {
|
||||||
|
wrapper.setPacketType(mappedPacketType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable PacketHandler handler() {
|
||||||
|
return handler;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
|
||||||
|
* Copyright (C) 2023 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.packet.provider;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Map;
|
||||||
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
|
final class PacketTypeArrayMap<P> implements PacketTypeMap<P> {
|
||||||
|
private final Map<String, P> packetsByName;
|
||||||
|
private final P[] packets;
|
||||||
|
|
||||||
|
PacketTypeArrayMap(Map<String, P> packetsByName, P[] packets) {
|
||||||
|
this.packetsByName = packetsByName;
|
||||||
|
this.packets = packets;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable P typeByName(String packetTypeName) {
|
||||||
|
return packetsByName.get(packetTypeName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable P typeById(int packetTypeId) {
|
||||||
|
return packetTypeId >= 0 && packetTypeId < packets.length ? packets[packetTypeId] : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<P> types() {
|
||||||
|
return Arrays.asList(packets);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
|
||||||
|
* Copyright (C) 2023 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.packet.provider;
|
||||||
|
|
||||||
|
import com.viaversion.viaversion.api.protocol.packet.PacketType;
|
||||||
|
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
|
public interface PacketTypeMap<P> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the packet type by the given name.
|
||||||
|
*
|
||||||
|
* @param packetTypeName packet type name
|
||||||
|
* @return packet type if present
|
||||||
|
*/
|
||||||
|
@Nullable P typeByName(String packetTypeName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the packet type by the given id.
|
||||||
|
*
|
||||||
|
* @param packetTypeId packet type id
|
||||||
|
* @return packet type if present
|
||||||
|
*/
|
||||||
|
@Nullable P typeById(int packetTypeId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a collection of all contained packet types.
|
||||||
|
*
|
||||||
|
* @return collection of all packet types
|
||||||
|
*/
|
||||||
|
Collection<P> types();
|
||||||
|
|
||||||
|
static <S extends PacketType, T extends S> PacketTypeMap<S> of(final Class<T> enumClass) {
|
||||||
|
if (!enumClass.isEnum()) {
|
||||||
|
throw new IllegalArgumentException("Given class is not an enum");
|
||||||
|
}
|
||||||
|
|
||||||
|
final S[] types = enumClass.getEnumConstants();
|
||||||
|
final Map<String, S> byName = new HashMap<>(types.length);
|
||||||
|
for (final S type : types) {
|
||||||
|
byName.put(type.getName(), type);
|
||||||
|
}
|
||||||
|
return of(byName, types);
|
||||||
|
}
|
||||||
|
|
||||||
|
static <T> PacketTypeMap<T> of(final Map<String, T> packetsByName, final Int2ObjectMap<T> packetsById) {
|
||||||
|
return new PacketTypeMapMap<>(packetsByName, packetsById);
|
||||||
|
}
|
||||||
|
|
||||||
|
static <T> PacketTypeMap<T> of(final Map<String, T> packetsByName, final T[] packets) {
|
||||||
|
return new PacketTypeArrayMap<>(packetsByName, packets);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
|
||||||
|
* Copyright (C) 2023 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.packet.provider;
|
||||||
|
|
||||||
|
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Map;
|
||||||
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
|
final class PacketTypeMapMap<P> implements PacketTypeMap<P> {
|
||||||
|
private final Map<String, P> packetsByName;
|
||||||
|
private final Int2ObjectMap<P> packetsById;
|
||||||
|
|
||||||
|
PacketTypeMapMap(Map<String, P> packetsByName,
|
||||||
|
Int2ObjectMap<P> packetsById) {
|
||||||
|
this.packetsByName = packetsByName;
|
||||||
|
this.packetsById = packetsById;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable P typeByName(String packetTypeName) {
|
||||||
|
return packetsByName.get(packetTypeName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable P typeById(int packetTypeId) {
|
||||||
|
return packetsById.get(packetTypeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<P> types() {
|
||||||
|
return packetsById.values();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
|
||||||
|
* Copyright (C) 2016-2023 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.packet.provider;
|
||||||
|
|
||||||
|
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
|
||||||
|
import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType;
|
||||||
|
import com.viaversion.viaversion.api.protocol.packet.State;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public interface PacketTypesProvider<CU extends ClientboundPacketType, CM extends ClientboundPacketType, SM extends ServerboundPacketType, SU extends ServerboundPacketType> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a map of all unmapped clientbound packet types that are expected to be used within a protocol.
|
||||||
|
* This means that if {@code C1} encompasses more than just {@link State#PLAY} packets, the other types are included as well.
|
||||||
|
*
|
||||||
|
* @return map of unmapped clientbound packet types
|
||||||
|
*/
|
||||||
|
Map<State, PacketTypeMap<CU>> unmappedClientboundPacketTypes();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a map of all unmapped serverbound packet types that are expected to be used within the protocol.
|
||||||
|
* This means that if {@code S2} encompasses more than just {@link State#PLAY} packets, the other types have to be included as well.
|
||||||
|
*
|
||||||
|
* @return map of unmapped serverbound packet types
|
||||||
|
*/
|
||||||
|
Map<State, PacketTypeMap<SU>> unmappedServerboundPacketTypes();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a map of all mapped clientbound packet types that are expected to be used within the protocol.
|
||||||
|
*
|
||||||
|
* @return map of mapped clientbound packet types
|
||||||
|
*/
|
||||||
|
Map<State, PacketTypeMap<CM>> mappedClientboundPacketTypes();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a map of all mapped serverbound packet types that are expected to be used within the protocol.
|
||||||
|
*
|
||||||
|
* @return map of mapped serverbound packet types
|
||||||
|
*/
|
||||||
|
Map<State, PacketTypeMap<SM>> mappedServerboundPacketTypes();
|
||||||
|
}
|
@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
|
||||||
|
* Copyright (C) 2023 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.packet.provider;
|
||||||
|
|
||||||
|
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
|
||||||
|
import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType;
|
||||||
|
import com.viaversion.viaversion.api.protocol.packet.State;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public final class SimplePacketTypesProvider<CU extends ClientboundPacketType, CM extends ClientboundPacketType, SM extends ServerboundPacketType, SU extends ServerboundPacketType> implements PacketTypesProvider<CU, CM, SM, SU> {
|
||||||
|
private final Map<State, PacketTypeMap<CU>> unmappedClientboundPacketTypes;
|
||||||
|
private final Map<State, PacketTypeMap<CM>> mappedClientboundPacketTypes;
|
||||||
|
private final Map<State, PacketTypeMap<SM>> mappedServerboundPacketTypes;
|
||||||
|
private final Map<State, PacketTypeMap<SU>> unmappedServerboundPacketTypes;
|
||||||
|
|
||||||
|
public SimplePacketTypesProvider(
|
||||||
|
Map<State, PacketTypeMap<CU>> unmappedClientboundPacketTypes,
|
||||||
|
Map<State, PacketTypeMap<CM>> mappedClientboundPacketTypes,
|
||||||
|
Map<State, PacketTypeMap<SM>> mappedServerboundPacketTypes,
|
||||||
|
Map<State, PacketTypeMap<SU>> unmappedServerboundPacketTypes
|
||||||
|
) {
|
||||||
|
this.unmappedClientboundPacketTypes = unmappedClientboundPacketTypes;
|
||||||
|
this.mappedClientboundPacketTypes = mappedClientboundPacketTypes;
|
||||||
|
this.mappedServerboundPacketTypes = mappedServerboundPacketTypes;
|
||||||
|
this.unmappedServerboundPacketTypes = unmappedServerboundPacketTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<State, PacketTypeMap<CU>> unmappedClientboundPacketTypes() {
|
||||||
|
return unmappedClientboundPacketTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<State, PacketTypeMap<CM>> mappedClientboundPacketTypes() {
|
||||||
|
return mappedClientboundPacketTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<State, PacketTypeMap<SM>> mappedServerboundPacketTypes() {
|
||||||
|
return mappedServerboundPacketTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<State, PacketTypeMap<SU>> unmappedServerboundPacketTypes() {
|
||||||
|
return unmappedServerboundPacketTypes;
|
||||||
|
}
|
||||||
|
}
|
@ -1,72 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
|
|
||||||
* Copyright (C) 2023 ViaVersion and contributors
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package com.viaversion.viaversion.common.protocol.remapper;
|
|
||||||
|
|
||||||
import com.viaversion.viaversion.api.Via;
|
|
||||||
import com.viaversion.viaversion.api.protocol.AbstractProtocol;
|
|
||||||
import com.viaversion.viaversion.api.protocol.AbstractProtocol.ProtocolPacket;
|
|
||||||
import com.viaversion.viaversion.api.protocol.Protocol;
|
|
||||||
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
|
|
||||||
import com.viaversion.viaversion.common.dummy.DummyInitializer;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
public class ProtocolHandlersTest {
|
|
||||||
|
|
||||||
private static final Logger LOGGER = Logger.getGlobal();
|
|
||||||
private static final boolean WARN = false;
|
|
||||||
|
|
||||||
@BeforeAll
|
|
||||||
static void init() {
|
|
||||||
DummyInitializer.init();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testHandlersSize() {
|
|
||||||
if (!WARN) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (final Protocol<?, ?, ?, ?> protocol : Via.getManager().getProtocolManager().getProtocols()) {
|
|
||||||
if (!(protocol instanceof AbstractProtocol)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
final AbstractProtocol<?, ?, ?, ?> abstractProtocol = (AbstractProtocol<?, ?, ?, ?>) protocol;
|
|
||||||
final List<ProtocolPacket> protocolMappings = new ArrayList<>(abstractProtocol.getClientbound().values());
|
|
||||||
protocolMappings.addAll(abstractProtocol.getServerbound().values());
|
|
||||||
|
|
||||||
for (final ProtocolPacket protocolMapping : protocolMappings) {
|
|
||||||
if (!(protocolMapping.getRemapper() instanceof PacketHandlers)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
final PacketHandlers packetHandlers = (PacketHandlers) protocolMapping.getRemapper();
|
|
||||||
if (packetHandlers.handlersSize() == 0) {
|
|
||||||
LOGGER.warning("PacketHandlers instance has no handlers: " + protocolMapping + " in " + protocol.getClass().getSimpleName());
|
|
||||||
} else if (packetHandlers.handlersSize() == 1) {
|
|
||||||
LOGGER.warning("PacketHandlers instance only has a single handler; consider using a PacketHandler lambda instead of extending PacketHandlers: "
|
|
||||||
+ protocolMapping + " in " + protocol.getClass().getSimpleName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user