2021-03-22 23:06:40 +01:00
|
|
|
/*
|
|
|
|
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
|
2024-01-01 12:39:45 +01:00
|
|
|
* Copyright (C) 2016-2024 ViaVersion and contributors
|
2021-03-22 23:06:40 +01:00
|
|
|
*
|
|
|
|
* 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/>.
|
|
|
|
*/
|
2021-04-26 21:16:10 +02:00
|
|
|
package com.viaversion.viaversion.protocol;
|
2016-03-17 22:24:25 +01:00
|
|
|
|
2021-03-21 20:25:52 +01:00
|
|
|
import com.google.common.base.Preconditions;
|
2016-05-19 19:56:42 +02:00
|
|
|
import com.google.common.collect.Lists;
|
2018-07-03 14:58:00 +02:00
|
|
|
import com.google.common.collect.Range;
|
2020-07-21 09:10:16 +02:00
|
|
|
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
2021-04-26 22:54:43 +02:00
|
|
|
import com.viaversion.viaversion.api.Via;
|
|
|
|
import com.viaversion.viaversion.api.connection.UserConnection;
|
2023-03-05 14:45:58 +01:00
|
|
|
import com.viaversion.viaversion.api.data.MappingDataLoader;
|
2021-04-28 12:59:37 +02:00
|
|
|
import com.viaversion.viaversion.api.protocol.Protocol;
|
2021-04-26 21:16:10 +02:00
|
|
|
import com.viaversion.viaversion.api.protocol.ProtocolManager;
|
|
|
|
import com.viaversion.viaversion.api.protocol.ProtocolPathEntry;
|
|
|
|
import com.viaversion.viaversion.api.protocol.ProtocolPathKey;
|
2021-07-27 17:23:55 +02:00
|
|
|
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
|
2021-07-31 12:43:07 +02:00
|
|
|
import com.viaversion.viaversion.api.protocol.packet.PacketType;
|
2021-04-27 13:41:39 +02:00
|
|
|
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
2021-07-27 17:23:55 +02:00
|
|
|
import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType;
|
2021-07-31 23:17:52 +02:00
|
|
|
import com.viaversion.viaversion.api.protocol.packet.VersionedPacketTransformer;
|
2021-04-26 21:16:10 +02:00
|
|
|
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
|
|
|
|
import com.viaversion.viaversion.api.protocol.version.ServerProtocolVersion;
|
2021-04-26 22:54:43 +02:00
|
|
|
import com.viaversion.viaversion.protocol.packet.PacketWrapperImpl;
|
2021-07-31 23:17:52 +02:00
|
|
|
import com.viaversion.viaversion.protocol.packet.VersionedPacketTransformerImpl;
|
2021-04-26 20:52:34 +02:00
|
|
|
import com.viaversion.viaversion.protocols.base.BaseProtocol;
|
|
|
|
import com.viaversion.viaversion.protocols.base.BaseProtocol1_16;
|
|
|
|
import com.viaversion.viaversion.protocols.base.BaseProtocol1_7;
|
|
|
|
import com.viaversion.viaversion.protocols.protocol1_10to1_9_3.Protocol1_10To1_9_3_4;
|
|
|
|
import com.viaversion.viaversion.protocols.protocol1_11_1to1_11.Protocol1_11_1To1_11;
|
|
|
|
import com.viaversion.viaversion.protocols.protocol1_11to1_10.Protocol1_11To1_10;
|
|
|
|
import com.viaversion.viaversion.protocols.protocol1_12_1to1_12.Protocol1_12_1To1_12;
|
|
|
|
import com.viaversion.viaversion.protocols.protocol1_12_2to1_12_1.Protocol1_12_2To1_12_1;
|
|
|
|
import com.viaversion.viaversion.protocols.protocol1_12to1_11_1.Protocol1_12To1_11_1;
|
|
|
|
import com.viaversion.viaversion.protocols.protocol1_13_1to1_13.Protocol1_13_1To1_13;
|
|
|
|
import com.viaversion.viaversion.protocols.protocol1_13_2to1_13_1.Protocol1_13_2To1_13_1;
|
|
|
|
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.Protocol1_13To1_12_2;
|
|
|
|
import com.viaversion.viaversion.protocols.protocol1_14_1to1_14.Protocol1_14_1To1_14;
|
|
|
|
import com.viaversion.viaversion.protocols.protocol1_14_2to1_14_1.Protocol1_14_2To1_14_1;
|
|
|
|
import com.viaversion.viaversion.protocols.protocol1_14_3to1_14_2.Protocol1_14_3To1_14_2;
|
|
|
|
import com.viaversion.viaversion.protocols.protocol1_14_4to1_14_3.Protocol1_14_4To1_14_3;
|
|
|
|
import com.viaversion.viaversion.protocols.protocol1_14to1_13_2.Protocol1_14To1_13_2;
|
|
|
|
import com.viaversion.viaversion.protocols.protocol1_15_1to1_15.Protocol1_15_1To1_15;
|
|
|
|
import com.viaversion.viaversion.protocols.protocol1_15_2to1_15_1.Protocol1_15_2To1_15_1;
|
|
|
|
import com.viaversion.viaversion.protocols.protocol1_15to1_14_4.Protocol1_15To1_14_4;
|
|
|
|
import com.viaversion.viaversion.protocols.protocol1_16_1to1_16.Protocol1_16_1To1_16;
|
|
|
|
import com.viaversion.viaversion.protocols.protocol1_16_2to1_16_1.Protocol1_16_2To1_16_1;
|
|
|
|
import com.viaversion.viaversion.protocols.protocol1_16_3to1_16_2.Protocol1_16_3To1_16_2;
|
|
|
|
import com.viaversion.viaversion.protocols.protocol1_16_4to1_16_3.Protocol1_16_4To1_16_3;
|
|
|
|
import com.viaversion.viaversion.protocols.protocol1_16to1_15_2.Protocol1_16To1_15_2;
|
2021-06-10 17:43:07 +02:00
|
|
|
import com.viaversion.viaversion.protocols.protocol1_17_1to1_17.Protocol1_17_1To1_17;
|
2021-04-26 20:52:34 +02:00
|
|
|
import com.viaversion.viaversion.protocols.protocol1_17to1_16_4.Protocol1_17To1_16_4;
|
2022-01-19 18:05:36 +01:00
|
|
|
import com.viaversion.viaversion.protocols.protocol1_18_2to1_18.Protocol1_18_2To1_18;
|
2021-09-14 17:38:52 +02:00
|
|
|
import com.viaversion.viaversion.protocols.protocol1_18to1_17_1.Protocol1_18To1_17_1;
|
2022-06-21 21:01:24 +02:00
|
|
|
import com.viaversion.viaversion.protocols.protocol1_19_1to1_19.Protocol1_19_1To1_19;
|
2022-10-16 10:13:05 +02:00
|
|
|
import com.viaversion.viaversion.protocols.protocol1_19_3to1_19_1.Protocol1_19_3To1_19_1;
|
2023-01-18 15:20:23 +01:00
|
|
|
import com.viaversion.viaversion.protocols.protocol1_19_4to1_19_3.Protocol1_19_4To1_19_3;
|
2023-02-12 11:44:25 +01:00
|
|
|
import com.viaversion.viaversion.protocols.protocol1_19to1_18_2.Protocol1_19To1_18_2;
|
2023-08-03 05:58:22 +02:00
|
|
|
import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.Protocol1_20_2To1_20;
|
2023-10-05 10:22:13 +02:00
|
|
|
import com.viaversion.viaversion.protocols.protocol1_20_3to1_20_2.Protocol1_20_3To1_20_2;
|
2023-03-22 18:49:18 +01:00
|
|
|
import com.viaversion.viaversion.protocols.protocol1_20to1_19_4.Protocol1_20To1_19_4;
|
2023-12-18 15:28:58 +01:00
|
|
|
import com.viaversion.viaversion.protocols.protocol1_20_5to1_20_3.Protocol1_20_5To1_20_3;
|
2021-04-26 20:52:34 +02:00
|
|
|
import com.viaversion.viaversion.protocols.protocol1_9_1to1_9.Protocol1_9_1To1_9;
|
|
|
|
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.Protocol1_9_3To1_9_1_2;
|
|
|
|
import com.viaversion.viaversion.protocols.protocol1_9to1_8.Protocol1_9To1_8;
|
2021-04-26 22:54:43 +02:00
|
|
|
import com.viaversion.viaversion.util.Pair;
|
|
|
|
import io.netty.buffer.ByteBuf;
|
2020-04-03 00:05:44 +02:00
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.Arrays;
|
2023-02-12 11:44:25 +01:00
|
|
|
import java.util.Collection;
|
2020-04-03 00:05:44 +02:00
|
|
|
import java.util.Collections;
|
|
|
|
import java.util.HashMap;
|
|
|
|
import java.util.HashSet;
|
|
|
|
import java.util.List;
|
|
|
|
import java.util.Map;
|
|
|
|
import java.util.Set;
|
|
|
|
import java.util.SortedSet;
|
|
|
|
import java.util.TreeSet;
|
|
|
|
import java.util.concurrent.CompletableFuture;
|
|
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
|
|
import java.util.concurrent.SynchronousQueue;
|
2020-07-21 09:10:16 +02:00
|
|
|
import java.util.concurrent.ThreadFactory;
|
2020-04-03 00:05:44 +02:00
|
|
|
import java.util.concurrent.ThreadPoolExecutor;
|
|
|
|
import java.util.concurrent.TimeUnit;
|
2021-03-21 20:25:52 +01:00
|
|
|
import java.util.concurrent.locks.ReadWriteLock;
|
|
|
|
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
|
|
|
import java.util.function.Function;
|
2023-12-18 15:28:58 +01:00
|
|
|
import java.util.logging.Level;
|
2024-02-14 17:56:28 +01:00
|
|
|
import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap;
|
|
|
|
import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
|
|
|
|
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
|
|
|
import it.unimi.dsi.fastutil.objects.Object2ObjectSortedMap;
|
2023-12-18 15:28:58 +01:00
|
|
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
|
|
|
import us.myles.ViaVersion.api.protocol.ProtocolRegistry;
|
2016-03-17 22:24:25 +01:00
|
|
|
|
2021-03-24 15:21:18 +01:00
|
|
|
public class ProtocolManagerImpl implements ProtocolManager {
|
2021-04-21 11:58:19 +02:00
|
|
|
private static final Protocol BASE_PROTOCOL = new BaseProtocol();
|
2021-03-24 15:21:18 +01:00
|
|
|
|
2016-03-17 22:24:25 +01:00
|
|
|
// Input Version -> Output Version & Protocol (Allows fast lookup)
|
2024-02-14 17:56:28 +01:00
|
|
|
private final Object2ObjectMap<ProtocolVersion, Object2ObjectMap<ProtocolVersion, Protocol>> registryMap = new Object2ObjectOpenHashMap<>(32);
|
2023-03-16 11:21:47 +01:00
|
|
|
private final Map<Class<? extends Protocol>, Protocol<?, ?, ?, ?>> protocols = new HashMap<>(64);
|
2021-03-25 22:34:30 +01:00
|
|
|
private final Map<ProtocolPathKey, List<ProtocolPathEntry>> pathCache = new ConcurrentHashMap<>();
|
2024-02-14 17:56:28 +01:00
|
|
|
private final Set<ProtocolVersion> supportedVersions = new HashSet<>();
|
|
|
|
private final List<Pair<Range<ProtocolVersion>, Protocol>> baseProtocols = Lists.newCopyOnWriteArrayList();
|
2021-03-24 15:21:18 +01:00
|
|
|
|
|
|
|
private final ReadWriteLock mappingLoaderLock = new ReentrantReadWriteLock();
|
|
|
|
private Map<Class<? extends Protocol>, CompletableFuture<Void>> mappingLoaderFutures = new HashMap<>();
|
|
|
|
private ThreadPoolExecutor mappingLoaderExecutor;
|
|
|
|
private boolean mappingsLoaded;
|
|
|
|
|
2024-02-13 22:48:08 +01:00
|
|
|
private ServerProtocolVersion serverProtocolVersion = new ServerProtocolVersionSingleton(ProtocolVersion.unknown);
|
2022-07-28 11:29:02 +02:00
|
|
|
private int maxPathDeltaIncrease; // Only allow lowering path entries by default
|
2021-03-24 15:21:18 +01:00
|
|
|
private int maxProtocolPathSize = 50;
|
|
|
|
|
|
|
|
public ProtocolManagerImpl() {
|
2020-07-21 09:10:16 +02:00
|
|
|
ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("Via-Mappingloader-%d").build();
|
2023-02-20 17:30:56 +01:00
|
|
|
mappingLoaderExecutor = new ThreadPoolExecutor(12, Integer.MAX_VALUE, 30L, TimeUnit.SECONDS, new SynchronousQueue<>(), threadFactory);
|
2020-03-23 01:23:17 +01:00
|
|
|
mappingLoaderExecutor.allowCoreThreadTimeOut(true);
|
2021-03-24 15:21:18 +01:00
|
|
|
}
|
2020-03-23 01:23:17 +01:00
|
|
|
|
2021-03-24 15:21:18 +01:00
|
|
|
public void registerProtocols() {
|
2016-04-22 14:28:54 +02:00
|
|
|
// Base Protocol
|
2024-02-14 17:56:28 +01:00
|
|
|
BASE_PROTOCOL.initialize();
|
2024-02-14 17:57:00 +01:00
|
|
|
BASE_PROTOCOL.register(Via.getManager().getProviders());
|
2024-02-14 20:14:17 +01:00
|
|
|
registerBaseProtocol(new BaseProtocol1_7(), Range.closedOpen(ProtocolVersion.v1_7_2, ProtocolVersion.v1_16));
|
2024-02-14 17:56:28 +01:00
|
|
|
registerBaseProtocol(new BaseProtocol1_16(), Range.atLeast(ProtocolVersion.v1_16));
|
2018-07-03 14:58:00 +02:00
|
|
|
|
2019-08-23 22:14:32 +02:00
|
|
|
registerProtocol(new Protocol1_9To1_8(), ProtocolVersion.v1_9, ProtocolVersion.v1_8);
|
2024-02-14 17:56:28 +01:00
|
|
|
registerProtocol(new Protocol1_9_1To1_9(), Arrays.asList(ProtocolVersion.v1_9_1, ProtocolVersion.v1_9_2), ProtocolVersion.v1_9);
|
2019-08-23 22:14:32 +02:00
|
|
|
registerProtocol(new Protocol1_9_3To1_9_1_2(), ProtocolVersion.v1_9_3, ProtocolVersion.v1_9_2);
|
2020-04-24 13:27:29 +02:00
|
|
|
|
2019-08-23 22:14:32 +02:00
|
|
|
registerProtocol(new Protocol1_10To1_9_3_4(), ProtocolVersion.v1_10, ProtocolVersion.v1_9_3);
|
2016-05-17 23:48:56 +02:00
|
|
|
|
2019-08-23 22:14:32 +02:00
|
|
|
registerProtocol(new Protocol1_11To1_10(), ProtocolVersion.v1_11, ProtocolVersion.v1_10);
|
|
|
|
registerProtocol(new Protocol1_11_1To1_11(), ProtocolVersion.v1_11_1, ProtocolVersion.v1_11);
|
2017-06-07 17:50:22 +02:00
|
|
|
|
2019-08-23 22:14:32 +02:00
|
|
|
registerProtocol(new Protocol1_12To1_11_1(), ProtocolVersion.v1_12, ProtocolVersion.v1_11_1);
|
|
|
|
registerProtocol(new Protocol1_12_1To1_12(), ProtocolVersion.v1_12_1, ProtocolVersion.v1_12);
|
|
|
|
registerProtocol(new Protocol1_12_2To1_12_1(), ProtocolVersion.v1_12_2, ProtocolVersion.v1_12_1);
|
2017-10-26 15:39:57 +02:00
|
|
|
|
2019-08-23 22:14:32 +02:00
|
|
|
registerProtocol(new Protocol1_13To1_12_2(), ProtocolVersion.v1_13, ProtocolVersion.v1_12_2);
|
|
|
|
registerProtocol(new Protocol1_13_1To1_13(), ProtocolVersion.v1_13_1, ProtocolVersion.v1_13);
|
|
|
|
registerProtocol(new Protocol1_13_2To1_13_1(), ProtocolVersion.v1_13_2, ProtocolVersion.v1_13_1);
|
2019-04-23 17:02:18 +02:00
|
|
|
|
2019-08-23 22:14:32 +02:00
|
|
|
registerProtocol(new Protocol1_14To1_13_2(), ProtocolVersion.v1_14, ProtocolVersion.v1_13_2);
|
|
|
|
registerProtocol(new Protocol1_14_1To1_14(), ProtocolVersion.v1_14_1, ProtocolVersion.v1_14);
|
|
|
|
registerProtocol(new Protocol1_14_2To1_14_1(), ProtocolVersion.v1_14_2, ProtocolVersion.v1_14_1);
|
|
|
|
registerProtocol(new Protocol1_14_3To1_14_2(), ProtocolVersion.v1_14_3, ProtocolVersion.v1_14_2);
|
|
|
|
registerProtocol(new Protocol1_14_4To1_14_3(), ProtocolVersion.v1_14_4, ProtocolVersion.v1_14_3);
|
2019-09-19 10:27:48 +02:00
|
|
|
|
|
|
|
registerProtocol(new Protocol1_15To1_14_4(), ProtocolVersion.v1_15, ProtocolVersion.v1_14_4);
|
2019-12-17 16:28:43 +01:00
|
|
|
registerProtocol(new Protocol1_15_1To1_15(), ProtocolVersion.v1_15_1, ProtocolVersion.v1_15);
|
2020-01-19 19:09:57 +01:00
|
|
|
registerProtocol(new Protocol1_15_2To1_15_1(), ProtocolVersion.v1_15_2, ProtocolVersion.v1_15_1);
|
2020-02-05 20:09:06 +01:00
|
|
|
|
|
|
|
registerProtocol(new Protocol1_16To1_15_2(), ProtocolVersion.v1_16, ProtocolVersion.v1_15_2);
|
2020-06-24 14:10:33 +02:00
|
|
|
registerProtocol(new Protocol1_16_1To1_16(), ProtocolVersion.v1_16_1, ProtocolVersion.v1_16);
|
2020-07-01 17:20:59 +02:00
|
|
|
registerProtocol(new Protocol1_16_2To1_16_1(), ProtocolVersion.v1_16_2, ProtocolVersion.v1_16_1);
|
2020-09-07 15:11:11 +02:00
|
|
|
registerProtocol(new Protocol1_16_3To1_16_2(), ProtocolVersion.v1_16_3, ProtocolVersion.v1_16_2);
|
2020-10-07 12:32:52 +02:00
|
|
|
registerProtocol(new Protocol1_16_4To1_16_3(), ProtocolVersion.v1_16_4, ProtocolVersion.v1_16_3);
|
2020-11-04 21:52:38 +01:00
|
|
|
|
|
|
|
registerProtocol(new Protocol1_17To1_16_4(), ProtocolVersion.v1_17, ProtocolVersion.v1_16_4);
|
2021-06-10 17:43:07 +02:00
|
|
|
registerProtocol(new Protocol1_17_1To1_17(), ProtocolVersion.v1_17_1, ProtocolVersion.v1_17);
|
2023-01-18 15:20:23 +01:00
|
|
|
|
2021-09-14 17:38:52 +02:00
|
|
|
registerProtocol(new Protocol1_18To1_17_1(), ProtocolVersion.v1_18, ProtocolVersion.v1_17_1);
|
2022-03-16 19:09:39 +01:00
|
|
|
registerProtocol(new Protocol1_18_2To1_18(), ProtocolVersion.v1_18_2, ProtocolVersion.v1_18);
|
2022-02-17 20:24:18 +01:00
|
|
|
|
2022-03-16 19:09:39 +01:00
|
|
|
registerProtocol(new Protocol1_19To1_18_2(), ProtocolVersion.v1_19, ProtocolVersion.v1_18_2);
|
2022-06-21 21:01:24 +02:00
|
|
|
registerProtocol(new Protocol1_19_1To1_19(), ProtocolVersion.v1_19_1, ProtocolVersion.v1_19);
|
2022-10-16 10:13:05 +02:00
|
|
|
registerProtocol(new Protocol1_19_3To1_19_1(), ProtocolVersion.v1_19_3, ProtocolVersion.v1_19_1);
|
2023-01-18 15:20:23 +01:00
|
|
|
registerProtocol(new Protocol1_19_4To1_19_3(), ProtocolVersion.v1_19_4, ProtocolVersion.v1_19_3);
|
2023-03-22 18:49:18 +01:00
|
|
|
|
|
|
|
registerProtocol(new Protocol1_20To1_19_4(), ProtocolVersion.v1_20, ProtocolVersion.v1_19_4);
|
2023-08-03 05:58:22 +02:00
|
|
|
registerProtocol(new Protocol1_20_2To1_20(), ProtocolVersion.v1_20_2, ProtocolVersion.v1_20);
|
2023-10-05 10:22:13 +02:00
|
|
|
registerProtocol(new Protocol1_20_3To1_20_2(), ProtocolVersion.v1_20_3, ProtocolVersion.v1_20_2);
|
2023-12-18 15:28:58 +01:00
|
|
|
registerProtocol(new Protocol1_20_5To1_20_3(), ProtocolVersion.v1_20_5, ProtocolVersion.v1_20_3);
|
2019-08-23 22:14:32 +02:00
|
|
|
}
|
|
|
|
|
2021-03-24 15:21:18 +01:00
|
|
|
@Override
|
2021-05-29 20:53:47 +02:00
|
|
|
public void registerProtocol(Protocol protocol, ProtocolVersion clientVersion, ProtocolVersion serverVersion) {
|
2024-02-14 17:56:28 +01:00
|
|
|
registerProtocol(protocol, Collections.singletonList(clientVersion), serverVersion);
|
2016-03-17 22:24:25 +01:00
|
|
|
}
|
|
|
|
|
2021-03-24 15:21:18 +01:00
|
|
|
@Override
|
2024-02-14 17:56:28 +01:00
|
|
|
public void registerProtocol(Protocol protocol, List<ProtocolVersion> supportedClientVersion, ProtocolVersion serverVersion) {
|
2021-06-03 17:15:24 +02:00
|
|
|
// Register the protocol's handlers
|
|
|
|
protocol.initialize();
|
|
|
|
|
2016-03-23 15:00:48 +01:00
|
|
|
// Clear cache as this may make new routes.
|
2020-03-23 01:23:17 +01:00
|
|
|
if (!pathCache.isEmpty()) {
|
2016-03-23 15:00:48 +01:00
|
|
|
pathCache.clear();
|
2020-03-23 01:23:17 +01:00
|
|
|
}
|
2016-03-23 15:00:48 +01:00
|
|
|
|
2020-06-07 10:14:18 +02:00
|
|
|
protocols.put(protocol.getClass(), protocol);
|
|
|
|
|
2024-02-14 17:56:28 +01:00
|
|
|
for (ProtocolVersion clientVersion : supportedClientVersion) {
|
2021-06-01 17:52:48 +02:00
|
|
|
// Throw an error if supported client version = server version
|
2024-02-14 17:56:28 +01:00
|
|
|
Preconditions.checkArgument(!clientVersion.equals(serverVersion));
|
2021-06-01 17:52:48 +02:00
|
|
|
|
2024-02-14 17:56:28 +01:00
|
|
|
Object2ObjectMap<ProtocolVersion, Protocol> protocolMap = registryMap.computeIfAbsent(clientVersion, s -> new Object2ObjectOpenHashMap<>(2));
|
2021-05-29 20:53:47 +02:00
|
|
|
protocolMap.put(serverVersion, protocol);
|
2016-03-17 22:24:25 +01:00
|
|
|
}
|
2016-04-04 00:30:10 +02:00
|
|
|
|
2023-03-16 11:21:47 +01:00
|
|
|
protocol.register(Via.getManager().getProviders());
|
|
|
|
if (Via.getManager().isInitialized()) {
|
2016-05-19 19:56:42 +02:00
|
|
|
refreshVersions();
|
2016-04-04 00:30:10 +02:00
|
|
|
}
|
2020-03-23 01:23:17 +01:00
|
|
|
|
|
|
|
if (protocol.hasMappingDataToLoad()) {
|
|
|
|
if (mappingLoaderExecutor != null) {
|
|
|
|
// Submit mapping data loading
|
2020-03-23 12:22:34 +01:00
|
|
|
addMappingLoaderFuture(protocol.getClass(), protocol::loadMappingData);
|
2020-03-23 01:23:17 +01:00
|
|
|
} else {
|
|
|
|
// Late protocol adding - just do it on the current thread
|
|
|
|
protocol.loadMappingData();
|
|
|
|
}
|
|
|
|
}
|
2016-03-17 22:24:25 +01:00
|
|
|
}
|
|
|
|
|
2021-03-24 15:21:18 +01:00
|
|
|
@Override
|
2024-02-14 17:56:28 +01:00
|
|
|
public void registerBaseProtocol(Protocol baseProtocol, Range<ProtocolVersion> supportedProtocols) {
|
2021-04-21 11:58:19 +02:00
|
|
|
Preconditions.checkArgument(baseProtocol.isBaseProtocol(), "Protocol is not a base protocol");
|
2021-06-03 17:15:24 +02:00
|
|
|
baseProtocol.initialize();
|
|
|
|
|
2018-07-03 14:58:00 +02:00
|
|
|
baseProtocols.add(new Pair<>(supportedProtocols, baseProtocol));
|
2023-03-16 11:21:47 +01:00
|
|
|
baseProtocol.register(Via.getManager().getProviders());
|
|
|
|
if (Via.getManager().isInitialized()) {
|
2018-07-03 14:58:00 +02:00
|
|
|
refreshVersions();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-24 15:21:18 +01:00
|
|
|
public void refreshVersions() {
|
2016-05-19 19:56:42 +02:00
|
|
|
supportedVersions.clear();
|
|
|
|
|
2024-02-14 17:56:28 +01:00
|
|
|
supportedVersions.add(serverProtocolVersion.lowestSupportedProtocolVersion());
|
2021-06-01 17:52:48 +02:00
|
|
|
for (ProtocolVersion version : ProtocolVersion.getProtocols()) {
|
2024-02-14 17:56:28 +01:00
|
|
|
List<ProtocolPathEntry> protocolPath = getProtocolPath(version, serverProtocolVersion.lowestSupportedProtocolVersion());
|
2021-06-01 17:52:48 +02:00
|
|
|
if (protocolPath == null) continue;
|
|
|
|
|
2024-02-14 17:56:28 +01:00
|
|
|
supportedVersions.add(version);
|
2021-06-01 17:52:48 +02:00
|
|
|
for (ProtocolPathEntry pathEntry : protocolPath) {
|
2021-08-28 22:15:28 +02:00
|
|
|
supportedVersions.add(pathEntry.outputProtocolVersion());
|
2020-04-03 00:05:44 +02:00
|
|
|
}
|
2016-05-19 19:56:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-24 15:21:18 +01:00
|
|
|
@Override
|
2024-02-14 17:56:28 +01:00
|
|
|
public @Nullable List<ProtocolPathEntry> getProtocolPath(ProtocolVersion clientVersion, ProtocolVersion serverVersion) {
|
2021-06-01 17:52:48 +02:00
|
|
|
if (clientVersion == serverVersion) return null; // Nothing to do!
|
|
|
|
|
2021-03-24 15:21:18 +01:00
|
|
|
// Check cache
|
2021-06-01 17:52:48 +02:00
|
|
|
ProtocolPathKey protocolKey = new ProtocolPathKeyImpl(clientVersion, serverVersion);
|
2021-03-25 22:34:30 +01:00
|
|
|
List<ProtocolPathEntry> protocolList = pathCache.get(protocolKey);
|
2021-03-24 15:21:18 +01:00
|
|
|
if (protocolList != null) {
|
|
|
|
return protocolList;
|
2016-03-17 22:24:25 +01:00
|
|
|
}
|
2021-03-25 22:34:30 +01:00
|
|
|
|
2021-06-01 17:52:48 +02:00
|
|
|
// Calculate path
|
2024-02-14 17:56:28 +01:00
|
|
|
Object2ObjectSortedMap<ProtocolVersion, Protocol> outputPath = getProtocolPath(new Object2ObjectLinkedOpenHashMap<>(), clientVersion, serverVersion);
|
2021-06-01 17:52:48 +02:00
|
|
|
if (outputPath == null) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
List<ProtocolPathEntry> path = new ArrayList<>(outputPath.size());
|
2024-02-14 17:56:28 +01:00
|
|
|
for (Map.Entry<ProtocolVersion, Protocol> entry : outputPath.entrySet()) {
|
|
|
|
path.add(new ProtocolPathEntryImpl(entry.getKey(), entry.getValue()));
|
2016-04-04 00:30:10 +02:00
|
|
|
}
|
2021-06-01 17:52:48 +02:00
|
|
|
pathCache.put(protocolKey, path);
|
|
|
|
return path;
|
2016-04-04 00:30:10 +02:00
|
|
|
}
|
|
|
|
|
2021-07-27 17:23:55 +02:00
|
|
|
@Override
|
2021-07-31 23:17:52 +02:00
|
|
|
public <C extends ClientboundPacketType,
|
|
|
|
S extends ServerboundPacketType
|
|
|
|
> VersionedPacketTransformer<C, S> createPacketTransformer(ProtocolVersion inputVersion,
|
|
|
|
@Nullable Class<C> clientboundPacketsClass,
|
|
|
|
@Nullable Class<S> serverboundPacketsClass) {
|
2021-07-27 17:23:55 +02:00
|
|
|
Preconditions.checkArgument(clientboundPacketsClass != ClientboundPacketType.class && serverboundPacketsClass != ServerboundPacketType.class);
|
2021-07-31 23:17:52 +02:00
|
|
|
return new VersionedPacketTransformerImpl<>(inputVersion, clientboundPacketsClass, serverboundPacketsClass);
|
2021-07-27 17:23:55 +02:00
|
|
|
}
|
|
|
|
|
2016-03-22 19:02:46 +01:00
|
|
|
/**
|
2021-03-24 15:21:18 +01:00
|
|
|
* Calculates a path to get from an input protocol to the server's protocol.
|
2016-03-22 19:02:46 +01:00
|
|
|
*
|
2021-03-24 15:21:18 +01:00
|
|
|
* @param current current items in the path
|
|
|
|
* @param clientVersion current input version
|
|
|
|
* @param serverVersion desired output version
|
|
|
|
* @return path that has been generated, null if failed
|
2016-03-22 19:02:46 +01:00
|
|
|
*/
|
2024-02-14 17:56:28 +01:00
|
|
|
private @Nullable Object2ObjectSortedMap<ProtocolVersion, Protocol> getProtocolPath(Object2ObjectSortedMap<ProtocolVersion, Protocol> current, ProtocolVersion clientVersion, ProtocolVersion serverVersion) {
|
2021-07-27 17:23:55 +02:00
|
|
|
if (current.size() > maxProtocolPathSize) return null; // Fail-safe, protocol too complicated.
|
2016-03-17 22:24:25 +01:00
|
|
|
|
2021-06-01 17:52:48 +02:00
|
|
|
// First, check if there is any protocols for this
|
2024-02-14 17:56:28 +01:00
|
|
|
Object2ObjectMap<ProtocolVersion, Protocol> toServerProtocolMap = registryMap.get(clientVersion);
|
2021-06-01 17:52:48 +02:00
|
|
|
if (toServerProtocolMap == null) {
|
2016-03-17 22:24:25 +01:00
|
|
|
return null; // Not supported
|
|
|
|
}
|
2020-06-08 13:49:26 +02:00
|
|
|
|
2021-06-01 17:52:48 +02:00
|
|
|
// Next, check if there is a direct, single Protocol path
|
|
|
|
Protocol protocol = toServerProtocolMap.get(serverVersion);
|
2018-09-30 20:48:23 +02:00
|
|
|
if (protocol != null) {
|
2021-06-01 17:52:48 +02:00
|
|
|
current.put(serverVersion, protocol);
|
2016-03-17 22:24:25 +01:00
|
|
|
return current; // Easy solution
|
|
|
|
}
|
2020-06-08 13:49:26 +02:00
|
|
|
|
2016-03-17 22:24:25 +01:00
|
|
|
// There might be a more advanced solution... So we'll see if any of the others can get us there
|
2024-02-14 17:56:28 +01:00
|
|
|
Object2ObjectSortedMap<ProtocolVersion, Protocol> shortest = null;
|
|
|
|
for (Map.Entry<ProtocolVersion, Protocol> entry : toServerProtocolMap.entrySet()) {
|
2021-06-01 17:52:48 +02:00
|
|
|
// Ensure we don't go back to already contained versions
|
2024-02-14 17:56:28 +01:00
|
|
|
ProtocolVersion translatedToVersion = entry.getKey();
|
2021-06-01 17:52:48 +02:00
|
|
|
if (current.containsKey(translatedToVersion)) continue;
|
|
|
|
|
|
|
|
// Check if the new version is farther away than the current client version
|
2024-02-14 17:56:28 +01:00
|
|
|
if (maxPathDeltaIncrease != -1 && translatedToVersion.getVersionType() == clientVersion.getVersionType()) {
|
|
|
|
final int delta = Math.abs(serverVersion.getVersion() - translatedToVersion.getVersion()) - Math.abs(serverVersion.getVersion() - clientVersion.getVersion());
|
|
|
|
if (delta > maxPathDeltaIncrease) {
|
|
|
|
continue;
|
|
|
|
}
|
2021-06-01 17:52:48 +02:00
|
|
|
}
|
2020-06-08 22:23:24 +02:00
|
|
|
|
|
|
|
// Create a copy
|
2024-02-14 17:56:28 +01:00
|
|
|
Object2ObjectSortedMap<ProtocolVersion, Protocol> newCurrent = new Object2ObjectLinkedOpenHashMap<>(current);
|
2021-06-01 17:52:48 +02:00
|
|
|
newCurrent.put(translatedToVersion, entry.getValue());
|
2021-03-25 22:34:30 +01:00
|
|
|
|
2021-06-01 17:52:48 +02:00
|
|
|
// Calculate the rest of the protocol starting from translatedToVersion and take the shortest
|
|
|
|
newCurrent = getProtocolPath(newCurrent, translatedToVersion, serverVersion);
|
|
|
|
if (newCurrent != null && (shortest == null || newCurrent.size() < shortest.size())) {
|
2021-03-25 22:34:30 +01:00
|
|
|
shortest = newCurrent;
|
2016-03-17 22:24:25 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-17 23:48:56 +02:00
|
|
|
return shortest; // null if none found
|
2016-03-17 22:24:25 +01:00
|
|
|
}
|
|
|
|
|
2021-03-24 15:21:18 +01:00
|
|
|
@Override
|
2021-04-26 22:54:43 +02:00
|
|
|
public @Nullable <T extends Protocol> T getProtocol(Class<T> protocolClass) {
|
|
|
|
return (T) protocols.get(protocolClass);
|
2020-06-07 10:14:18 +02:00
|
|
|
}
|
|
|
|
|
2021-05-29 20:53:47 +02:00
|
|
|
@Override
|
2024-02-14 17:56:28 +01:00
|
|
|
public @Nullable Protocol getProtocol(ProtocolVersion clientVersion, ProtocolVersion serverVersion) {
|
|
|
|
Object2ObjectMap<ProtocolVersion, Protocol> map = registryMap.get(clientVersion);
|
2021-05-29 20:53:47 +02:00
|
|
|
return map != null ? map.get(serverVersion) : null;
|
|
|
|
}
|
|
|
|
|
2021-03-24 15:21:18 +01:00
|
|
|
@Override
|
2024-02-14 17:56:28 +01:00
|
|
|
public Protocol getBaseProtocol(ProtocolVersion serverVersion) {
|
|
|
|
for (Pair<Range<ProtocolVersion>, Protocol> rangeProtocol : Lists.reverse(baseProtocols)) {
|
2021-09-14 11:13:39 +02:00
|
|
|
if (rangeProtocol.key().contains(serverVersion)) {
|
|
|
|
return rangeProtocol.value();
|
2018-07-03 16:26:00 +02:00
|
|
|
}
|
|
|
|
}
|
2018-07-03 14:58:00 +02:00
|
|
|
throw new IllegalStateException("No Base Protocol for " + serverVersion);
|
|
|
|
}
|
2018-07-03 16:19:32 +02:00
|
|
|
|
2023-02-12 11:44:25 +01:00
|
|
|
@Override
|
|
|
|
public Collection<Protocol<?, ?, ?, ?>> getProtocols() {
|
|
|
|
return Collections.unmodifiableCollection(protocols.values());
|
|
|
|
}
|
|
|
|
|
2021-03-24 15:21:18 +01:00
|
|
|
@Override
|
2021-03-26 12:51:38 +01:00
|
|
|
public ServerProtocolVersion getServerProtocolVersion() {
|
|
|
|
return serverProtocolVersion;
|
2021-03-24 15:21:18 +01:00
|
|
|
}
|
|
|
|
|
2021-03-26 12:51:38 +01:00
|
|
|
public void setServerProtocol(ServerProtocolVersion serverProtocolVersion) {
|
|
|
|
this.serverProtocolVersion = serverProtocolVersion;
|
2021-04-27 13:25:18 +02:00
|
|
|
//noinspection deprecation
|
|
|
|
ProtocolRegistry.SERVER_PROTOCOL = serverProtocolVersion.lowestSupportedVersion();
|
2021-03-24 15:21:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean isWorkingPipe() {
|
2024-02-14 17:56:28 +01:00
|
|
|
for (Object2ObjectMap<ProtocolVersion, Protocol> map : registryMap.values()) {
|
2024-02-13 22:48:08 +01:00
|
|
|
for (ProtocolVersion protocolVersion : serverProtocolVersion.supportedProtocolVersions()) {
|
2024-02-14 22:45:34 +01:00
|
|
|
if (map.containsKey(protocolVersion)) {
|
2021-03-26 12:51:38 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
2021-03-24 15:21:18 +01:00
|
|
|
}
|
|
|
|
return false; // No destination for protocol
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2024-02-14 17:56:28 +01:00
|
|
|
public SortedSet<ProtocolVersion> getSupportedVersions() {
|
2021-03-24 15:21:18 +01:00
|
|
|
return Collections.unmodifiableSortedSet(new TreeSet<>(supportedVersions));
|
|
|
|
}
|
|
|
|
|
2021-06-01 17:52:48 +02:00
|
|
|
@Override
|
2022-07-28 11:29:02 +02:00
|
|
|
public void setMaxPathDeltaIncrease(final int maxPathDeltaIncrease) {
|
|
|
|
this.maxPathDeltaIncrease = Math.max(-1, maxPathDeltaIncrease);
|
2021-06-01 17:52:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2022-07-28 11:29:02 +02:00
|
|
|
public int getMaxPathDeltaIncrease() {
|
|
|
|
return maxPathDeltaIncrease;
|
2021-06-01 17:52:48 +02:00
|
|
|
}
|
|
|
|
|
2021-03-24 15:21:18 +01:00
|
|
|
@Override
|
|
|
|
public int getMaxProtocolPathSize() {
|
|
|
|
return maxProtocolPathSize;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void setMaxProtocolPathSize(int maxProtocolPathSize) {
|
|
|
|
this.maxProtocolPathSize = maxProtocolPathSize;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public Protocol getBaseProtocol() {
|
|
|
|
return BASE_PROTOCOL;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void completeMappingDataLoading(Class<? extends Protocol> protocolClass) throws Exception {
|
2020-04-03 00:05:44 +02:00
|
|
|
if (mappingsLoaded) return;
|
2020-03-23 01:23:17 +01:00
|
|
|
|
2020-04-03 00:05:44 +02:00
|
|
|
CompletableFuture<Void> future = getMappingLoaderFuture(protocolClass);
|
2021-03-21 20:25:52 +01:00
|
|
|
if (future != null) {
|
|
|
|
// Wait for completion
|
|
|
|
future.get();
|
|
|
|
}
|
2020-04-24 13:27:29 +02:00
|
|
|
}
|
2020-03-23 01:23:17 +01:00
|
|
|
|
2021-03-24 15:21:18 +01:00
|
|
|
@Override
|
|
|
|
public boolean checkForMappingCompletion() {
|
|
|
|
mappingLoaderLock.readLock().lock();
|
2021-03-21 20:25:52 +01:00
|
|
|
try {
|
2023-02-20 17:30:56 +01:00
|
|
|
if (mappingsLoaded) {
|
|
|
|
return false;
|
|
|
|
}
|
2020-03-23 01:23:17 +01:00
|
|
|
|
2020-04-24 13:27:29 +02:00
|
|
|
for (CompletableFuture<Void> future : mappingLoaderFutures.values()) {
|
|
|
|
// Return if any future hasn't completed yet
|
|
|
|
if (!future.isDone()) {
|
|
|
|
return false;
|
|
|
|
}
|
2020-04-03 00:05:44 +02:00
|
|
|
}
|
2020-04-24 13:27:29 +02:00
|
|
|
|
|
|
|
shutdownLoaderExecutor();
|
|
|
|
return true;
|
2021-03-21 20:25:52 +01:00
|
|
|
} finally {
|
2021-03-24 15:21:18 +01:00
|
|
|
mappingLoaderLock.readLock().unlock();
|
2020-03-23 01:23:17 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-24 15:21:18 +01:00
|
|
|
@Override
|
|
|
|
public void addMappingLoaderFuture(Class<? extends Protocol> protocolClass, Runnable runnable) {
|
2021-03-21 20:25:52 +01:00
|
|
|
CompletableFuture<Void> future = CompletableFuture.runAsync(runnable, mappingLoaderExecutor).exceptionally(mappingLoaderThrowable(protocolClass));
|
|
|
|
|
2021-03-24 15:21:18 +01:00
|
|
|
mappingLoaderLock.writeLock().lock();
|
2021-03-21 20:25:52 +01:00
|
|
|
try {
|
2020-04-03 00:05:44 +02:00
|
|
|
mappingLoaderFutures.put(protocolClass, future);
|
2021-03-21 20:25:52 +01:00
|
|
|
} finally {
|
2021-03-24 15:21:18 +01:00
|
|
|
mappingLoaderLock.writeLock().unlock();
|
2020-04-03 00:05:44 +02:00
|
|
|
}
|
2020-03-23 10:40:57 +01:00
|
|
|
}
|
|
|
|
|
2021-03-24 15:21:18 +01:00
|
|
|
@Override
|
|
|
|
public void addMappingLoaderFuture(Class<? extends Protocol> protocolClass, Class<? extends Protocol> dependsOn, Runnable runnable) {
|
2021-03-21 20:25:52 +01:00
|
|
|
CompletableFuture<Void> future = getMappingLoaderFuture(dependsOn)
|
|
|
|
.whenCompleteAsync((v, throwable) -> runnable.run(), mappingLoaderExecutor).exceptionally(mappingLoaderThrowable(protocolClass));
|
|
|
|
|
2021-03-24 15:21:18 +01:00
|
|
|
mappingLoaderLock.writeLock().lock();
|
2021-03-21 20:25:52 +01:00
|
|
|
try {
|
2020-04-24 13:48:22 +02:00
|
|
|
mappingLoaderFutures.put(protocolClass, future);
|
2021-03-21 20:25:52 +01:00
|
|
|
} finally {
|
2021-03-24 15:21:18 +01:00
|
|
|
mappingLoaderLock.writeLock().unlock();
|
2020-04-24 13:48:22 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-24 15:21:18 +01:00
|
|
|
@Override
|
2021-04-02 14:15:30 +02:00
|
|
|
public @Nullable CompletableFuture<Void> getMappingLoaderFuture(Class<? extends Protocol> protocolClass) {
|
2021-03-24 15:21:18 +01:00
|
|
|
mappingLoaderLock.readLock().lock();
|
2021-03-21 20:25:52 +01:00
|
|
|
try {
|
|
|
|
return mappingsLoaded ? null : mappingLoaderFutures.get(protocolClass);
|
|
|
|
} finally {
|
2021-03-24 15:21:18 +01:00
|
|
|
mappingLoaderLock.readLock().unlock();
|
2020-04-03 00:05:44 +02:00
|
|
|
}
|
2020-03-23 01:23:17 +01:00
|
|
|
}
|
2021-03-21 20:25:52 +01:00
|
|
|
|
2021-04-26 22:54:43 +02:00
|
|
|
@Override
|
2021-07-31 12:43:07 +02:00
|
|
|
public PacketWrapper createPacketWrapper(@Nullable PacketType packetType, @Nullable ByteBuf buf, UserConnection connection) {
|
|
|
|
return new PacketWrapperImpl(packetType, buf, connection);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
@Deprecated
|
2021-05-14 16:59:12 +02:00
|
|
|
public PacketWrapper createPacketWrapper(int packetId, @Nullable ByteBuf buf, UserConnection connection) {
|
2021-04-26 22:54:43 +02:00
|
|
|
return new PacketWrapperImpl(packetId, buf, connection);
|
|
|
|
}
|
|
|
|
|
2024-02-15 18:27:52 +01:00
|
|
|
@Override
|
|
|
|
public boolean hasLoadedMappings() {
|
|
|
|
return mappingsLoaded;
|
|
|
|
}
|
|
|
|
|
2023-03-10 12:20:02 +01:00
|
|
|
public void shutdownLoaderExecutor() {
|
2021-03-21 20:25:52 +01:00
|
|
|
Preconditions.checkArgument(!mappingsLoaded);
|
|
|
|
|
2021-06-06 16:18:15 +02:00
|
|
|
// If this log message is missing, something is wrong
|
2021-03-21 20:25:52 +01:00
|
|
|
Via.getPlatform().getLogger().info("Finished mapping loading, shutting down loader executor!");
|
|
|
|
mappingsLoaded = true;
|
|
|
|
mappingLoaderExecutor.shutdown();
|
|
|
|
mappingLoaderExecutor = null;
|
|
|
|
mappingLoaderFutures.clear();
|
|
|
|
mappingLoaderFutures = null;
|
2023-03-05 14:45:58 +01:00
|
|
|
|
|
|
|
// Clear cached mapping files
|
|
|
|
MappingDataLoader.clearCache();
|
2021-03-21 20:25:52 +01:00
|
|
|
}
|
|
|
|
|
2021-03-24 15:21:18 +01:00
|
|
|
private Function<Throwable, Void> mappingLoaderThrowable(Class<? extends Protocol> protocolClass) {
|
2021-03-21 20:25:52 +01:00
|
|
|
return throwable -> {
|
2023-11-20 19:56:48 +01:00
|
|
|
Via.getPlatform().getLogger().log(Level.SEVERE, "Error during mapping loading of " + protocolClass.getSimpleName(), throwable);
|
2021-03-21 20:25:52 +01:00
|
|
|
return null;
|
|
|
|
};
|
|
|
|
}
|
2016-03-17 22:24:25 +01:00
|
|
|
}
|