Reduce boxing in protocol path getting

More of its implementation should probably be cleaned up later
This commit is contained in:
KennyTV 2021-03-25 22:34:30 +01:00
parent 63356207a3
commit d918fd27b6
No known key found for this signature in database
GPG Key ID: 6BE3B555EBC5982B
10 changed files with 235 additions and 41 deletions

View File

@ -24,7 +24,6 @@ package us.myles.ViaVersion.api.protocol;
import com.google.common.collect.Range; import com.google.common.collect.Range;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import us.myles.ViaVersion.api.Pair;
import java.util.List; import java.util.List;
import java.util.SortedSet; import java.util.SortedSet;
@ -87,10 +86,10 @@ public interface ProtocolManager {
* *
* @param clientVersion input client version * @param clientVersion input client version
* @param serverVersion desired output server version * @param serverVersion desired output server version
* @return path it generated, null if it failed * @return path it generated, null if not supported
*/ */
@Nullable @Nullable
List<Pair<Integer, Protocol>> getProtocolPath(int clientVersion, int serverVersion); List<ProtocolPathEntry> getProtocolPath(int clientVersion, int serverVersion);
/** /**
* Returns the maximum protocol path size applied to {@link #getProtocolPath(int, int)}. * Returns the maximum protocol path size applied to {@link #getProtocolPath(int, int)}.

View File

@ -0,0 +1,41 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2021 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package us.myles.ViaVersion.api.protocol;
public interface ProtocolPathEntry {
/**
* Returns the resulting protocol after transformation using
* the {@link #getProtocol()} protocol handlers.
*
* @return output protocol version after transformation
*/
int getOutputProtocolVersion();
/**
* Returns the protocol to be applied with this entry.
*
* @return protocol to be applied with this entry
*/
Protocol getProtocol();
}

View File

@ -0,0 +1,36 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2021 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package us.myles.ViaVersion.api.protocol;
public interface ProtocolPathKey {
/**
* @return client protocol version
*/
int getClientProtocolVersion();
/**
* @return server protocol version
*/
int getServerProtocolVersion();
}

View File

@ -28,6 +28,7 @@ import us.myles.ViaVersion.ViaManager;
import us.myles.ViaVersion.api.Pair; import us.myles.ViaVersion.api.Pair;
import us.myles.ViaVersion.api.Via; import us.myles.ViaVersion.api.Via;
import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.SortedSet; import java.util.SortedSet;
@ -104,7 +105,16 @@ public class ProtocolRegistry {
*/ */
@Nullable @Nullable
public static List<Pair<Integer, Protocol>> getProtocolPath(int clientVersion, int serverVersion) { public static List<Pair<Integer, Protocol>> getProtocolPath(int clientVersion, int serverVersion) {
return Via.getManager().getProtocolManager().getProtocolPath(clientVersion, serverVersion); List<ProtocolPathEntry> pathList = Via.getManager().getProtocolManager().getProtocolPath(clientVersion, serverVersion);
if (pathList == null) {
return null;
}
List<Pair<Integer, Protocol>> list = new ArrayList<>();
for (ProtocolPathEntry entry : pathList) {
list.add(new Pair<>(entry.getOutputProtocolVersion(), entry.getProtocol()));
}
return list;
} }
/** /**

View File

@ -26,12 +26,12 @@ import net.md_5.bungee.api.score.Team;
import net.md_5.bungee.event.EventHandler; import net.md_5.bungee.event.EventHandler;
import net.md_5.bungee.protocol.packet.PluginMessage; import net.md_5.bungee.protocol.packet.PluginMessage;
import us.myles.ViaVersion.api.PacketWrapper; import us.myles.ViaVersion.api.PacketWrapper;
import us.myles.ViaVersion.api.Pair;
import us.myles.ViaVersion.api.Via; import us.myles.ViaVersion.api.Via;
import us.myles.ViaVersion.api.data.ExternalJoinGameListener; import us.myles.ViaVersion.api.data.ExternalJoinGameListener;
import us.myles.ViaVersion.api.data.StoredObject; import us.myles.ViaVersion.api.data.StoredObject;
import us.myles.ViaVersion.api.data.UserConnection; import us.myles.ViaVersion.api.data.UserConnection;
import us.myles.ViaVersion.api.protocol.Protocol; import us.myles.ViaVersion.api.protocol.Protocol;
import us.myles.ViaVersion.api.protocol.ProtocolPathEntry;
import us.myles.ViaVersion.api.protocol.ProtocolPipeline; import us.myles.ViaVersion.api.protocol.ProtocolPipeline;
import us.myles.ViaVersion.api.protocol.ProtocolVersion; import us.myles.ViaVersion.api.protocol.ProtocolVersion;
import us.myles.ViaVersion.api.type.Type; import us.myles.ViaVersion.api.type.Type;
@ -92,7 +92,7 @@ public class BungeeServerHandler implements Listener {
} }
int protocolId = ProtocolDetectorService.getProtocolId(e.getTarget().getName()); int protocolId = ProtocolDetectorService.getProtocolId(e.getTarget().getName());
List<Pair<Integer, Protocol>> protocols = Via.getManager().getProtocolManager().getProtocolPath(user.getProtocolInfo().getProtocolVersion(), protocolId); List<ProtocolPathEntry> protocols = Via.getManager().getProtocolManager().getProtocolPath(user.getProtocolInfo().getProtocolVersion(), protocolId);
// Check if ViaVersion can support that version // Check if ViaVersion can support that version
try { try {
@ -175,7 +175,7 @@ public class BungeeServerHandler implements Listener {
int previousServerProtocol = info.getServerProtocolVersion(); int previousServerProtocol = info.getServerProtocolVersion();
// Refresh the pipes // Refresh the pipes
List<Pair<Integer, Protocol>> protocols = Via.getManager().getProtocolManager().getProtocolPath(info.getProtocolVersion(), protocolId); List<ProtocolPathEntry> protocols = Via.getManager().getProtocolManager().getProtocolPath(info.getProtocolVersion(), protocolId);
ProtocolPipeline pipeline = user.getProtocolInfo().getPipeline(); ProtocolPipeline pipeline = user.getProtocolInfo().getPipeline();
user.clearStoredObjects(); user.clearStoredObjects();
pipeline.cleanPipes(); pipeline.cleanPipes();
@ -183,8 +183,8 @@ public class BungeeServerHandler implements Listener {
// TODO Check Bungee Supported Protocols? *shrugs* // TODO Check Bungee Supported Protocols? *shrugs*
protocolId = info.getProtocolVersion(); protocolId = info.getProtocolVersion();
} else { } else {
for (Pair<Integer, Protocol> prot : protocols) { for (ProtocolPathEntry prot : protocols) {
pipeline.add(prot.getValue()); pipeline.add(prot.getProtocol());
} }
} }

View File

@ -85,7 +85,7 @@ public class ProtocolManagerImpl implements ProtocolManager {
// Input Version -> Output Version & Protocol (Allows fast lookup) // Input Version -> Output Version & Protocol (Allows fast lookup)
private final Int2ObjectMap<Int2ObjectMap<Protocol>> registryMap = new Int2ObjectOpenHashMap<>(32); private final Int2ObjectMap<Int2ObjectMap<Protocol>> registryMap = new Int2ObjectOpenHashMap<>(32);
private final Map<Class<? extends Protocol>, Protocol> protocols = new HashMap<>(); private final Map<Class<? extends Protocol>, Protocol> protocols = new HashMap<>();
private final Map<Pair<Integer, Integer>, List<Pair<Integer, Protocol>>> pathCache = new ConcurrentHashMap<>(); private final Map<ProtocolPathKey, List<ProtocolPathEntry>> pathCache = new ConcurrentHashMap<>();
private final Set<Integer> supportedVersions = new HashSet<>(); private final Set<Integer> supportedVersions = new HashSet<>();
private final List<Pair<Range<Integer>, Protocol>> baseProtocols = Lists.newCopyOnWriteArrayList(); private final List<Pair<Range<Integer>, Protocol>> baseProtocols = Lists.newCopyOnWriteArrayList();
private final List<Protocol> registerList = new ArrayList<>(); private final List<Protocol> registerList = new ArrayList<>();
@ -201,26 +201,27 @@ public class ProtocolManagerImpl implements ProtocolManager {
supportedVersions.add(serverProtocol); supportedVersions.add(serverProtocol);
for (ProtocolVersion versions : ProtocolVersion.getProtocols()) { for (ProtocolVersion versions : ProtocolVersion.getProtocols()) {
List<Pair<Integer, Protocol>> paths = getProtocolPath(versions.getVersion(), serverProtocol); List<ProtocolPathEntry> paths = getProtocolPath(versions.getVersion(), serverProtocol);
if (paths == null) continue; if (paths == null) continue;
supportedVersions.add(versions.getVersion()); supportedVersions.add(versions.getVersion());
for (Pair<Integer, Protocol> path : paths) { for (ProtocolPathEntry path : paths) {
supportedVersions.add(path.getKey()); supportedVersions.add(path.getOutputProtocolVersion());
} }
} }
} }
@Nullable @Nullable
@Override @Override
public List<Pair<Integer, Protocol>> getProtocolPath(int clientVersion, int serverVersion) { public List<ProtocolPathEntry> getProtocolPath(int clientVersion, int serverVersion) {
Pair<Integer, Integer> protocolKey = new Pair<>(clientVersion, serverVersion); ProtocolPathKey protocolKey = new ProtocolPathKeyImpl(clientVersion, serverVersion);
// Check cache // Check cache
List<Pair<Integer, Protocol>> protocolList = pathCache.get(protocolKey); List<ProtocolPathEntry> protocolList = pathCache.get(protocolKey);
if (protocolList != null) { if (protocolList != null) {
return protocolList; return protocolList;
} }
// Generate path // Generate path
List<Pair<Integer, Protocol>> outputPath = getProtocolPath(new ArrayList<>(), clientVersion, serverVersion); List<ProtocolPathEntry> outputPath = getProtocolPath(new ArrayList<>(), clientVersion, serverVersion);
// If it found a path, cache it. // If it found a path, cache it.
if (outputPath != null) { if (outputPath != null) {
pathCache.put(protocolKey, outputPath); pathCache.put(protocolKey, outputPath);
@ -237,7 +238,7 @@ public class ProtocolManagerImpl implements ProtocolManager {
* @return path that has been generated, null if failed * @return path that has been generated, null if failed
*/ */
@Nullable @Nullable
private List<Pair<Integer, Protocol>> getProtocolPath(List<Pair<Integer, Protocol>> current, int clientVersion, int serverVersion) { private List<ProtocolPathEntry> getProtocolPath(List<ProtocolPathEntry> current, int clientVersion, int serverVersion) {
if (clientVersion == serverVersion) return null; // We're already there if (clientVersion == serverVersion) return null; // We're already there
if (current.size() > maxProtocolPathSize) return null; // Fail safe, protocol too complicated. if (current.size() > maxProtocolPathSize) return null; // Fail safe, protocol too complicated.
@ -250,32 +251,33 @@ public class ProtocolManagerImpl implements ProtocolManager {
// Next check there isn't an obvious path // Next check there isn't an obvious path
Protocol protocol = inputMap.get(serverVersion); Protocol protocol = inputMap.get(serverVersion);
if (protocol != null) { if (protocol != null) {
current.add(new Pair<>(serverVersion, protocol)); current.add(new ProtocolPathEntryImpl(serverVersion, protocol));
return current; // Easy solution return current; // Easy solution
} }
// There might be a more advanced solution... So we'll see if any of the others can get us there // There might be a more advanced solution... So we'll see if any of the others can get us there
List<Pair<Integer, Protocol>> shortest = null; List<ProtocolPathEntry> shortest = null;
for (Int2ObjectMap.Entry<Protocol> entry : inputMap.int2ObjectEntrySet()) { for (Int2ObjectMap.Entry<Protocol> entry : inputMap.int2ObjectEntrySet()) {
// Ensure it wasn't caught by the other loop // Ensure it wasn't caught by the other loop
if (entry.getIntKey() == (serverVersion)) continue; if (entry.getIntKey() == serverVersion) continue;
Pair<Integer, Protocol> pair = new Pair<>(entry.getIntKey(), entry.getValue()); ProtocolPathEntry pathEntry = new ProtocolPathEntryImpl(entry.getIntKey(), entry.getValue());
// Ensure no recursion // Ensure no recursion
if (current.contains(pair)) continue; if (current.contains(pathEntry)) continue;
// Create a copy // Create a copy
List<Pair<Integer, Protocol>> newCurrent = new ArrayList<>(current); List<ProtocolPathEntry> newCurrent = new ArrayList<>(current);
newCurrent.add(pair); newCurrent.add(pathEntry);
// Calculate the rest of the protocol using the current
newCurrent = getProtocolPath(newCurrent, entry.getKey(), serverVersion); // Calculate the rest of the protocol using the current path entry
if (newCurrent != null) { newCurrent = getProtocolPath(newCurrent, entry.getIntKey(), serverVersion);
// If it's shorter then choose it // If it's shorter then choose it
if (shortest == null || shortest.size() > newCurrent.size()) { if (newCurrent != null
&& (shortest == null || shortest.size() > newCurrent.size())) {
shortest = newCurrent; shortest = newCurrent;
} }
} }
}
return shortest; // null if none found return shortest; // null if none found
} }

View File

@ -0,0 +1,54 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2021 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 us.myles.ViaVersion.api.protocol;
public class ProtocolPathEntryImpl implements ProtocolPathEntry {
private final int outputProtocolVersion;
private final Protocol protocol;
public ProtocolPathEntryImpl(int outputProtocolVersion, Protocol protocol) {
this.outputProtocolVersion = outputProtocolVersion;
this.protocol = protocol;
}
@Override
public int getOutputProtocolVersion() {
return outputProtocolVersion;
}
@Override
public Protocol getProtocol() {
return protocol;
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final ProtocolPathEntryImpl that = (ProtocolPathEntryImpl) o;
if (outputProtocolVersion != that.outputProtocolVersion) return false;
return protocol.equals(that.protocol);
}
@Override
public int hashCode() {
int result = outputProtocolVersion;
result = 31 * result + protocol.hashCode();
return result;
}
}

View File

@ -0,0 +1,54 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2021 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 us.myles.ViaVersion.api.protocol;
public class ProtocolPathKeyImpl implements ProtocolPathKey {
private final int clientProtocolVersion;
private final int serverProtocolVersion;
public ProtocolPathKeyImpl(int clientProtocolVersion, int serverProtocolVersion) {
this.clientProtocolVersion = clientProtocolVersion;
this.serverProtocolVersion = serverProtocolVersion;
}
@Override
public int getClientProtocolVersion() {
return clientProtocolVersion;
}
@Override
public int getServerProtocolVersion() {
return serverProtocolVersion;
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final ProtocolPathKeyImpl that = (ProtocolPathKeyImpl) o;
if (clientProtocolVersion != that.clientProtocolVersion) return false;
return serverProtocolVersion == that.serverProtocolVersion;
}
@Override
public int hashCode() {
int result = clientProtocolVersion;
result = 31 * result + serverProtocolVersion;
return result;
}
}

View File

@ -18,11 +18,10 @@
package us.myles.ViaVersion.protocols.base; package us.myles.ViaVersion.protocols.base;
import us.myles.ViaVersion.api.PacketWrapper; import us.myles.ViaVersion.api.PacketWrapper;
import us.myles.ViaVersion.api.Pair;
import us.myles.ViaVersion.api.Via; import us.myles.ViaVersion.api.Via;
import us.myles.ViaVersion.api.data.UserConnection; import us.myles.ViaVersion.api.data.UserConnection;
import us.myles.ViaVersion.api.platform.providers.ViaProviders; import us.myles.ViaVersion.api.platform.providers.ViaProviders;
import us.myles.ViaVersion.api.protocol.Protocol; import us.myles.ViaVersion.api.protocol.ProtocolPathEntry;
import us.myles.ViaVersion.api.protocol.ProtocolPipeline; import us.myles.ViaVersion.api.protocol.ProtocolPipeline;
import us.myles.ViaVersion.api.protocol.ProtocolVersion; import us.myles.ViaVersion.api.protocol.ProtocolVersion;
import us.myles.ViaVersion.api.protocol.SimpleProtocol; import us.myles.ViaVersion.api.protocol.SimpleProtocol;
@ -60,7 +59,7 @@ public class BaseProtocol extends SimpleProtocol {
// Choose the pipe // Choose the pipe
int serverProtocol = Via.getManager().getProviders().get(VersionProvider.class).getServerProtocol(wrapper.user()); int serverProtocol = Via.getManager().getProviders().get(VersionProvider.class).getServerProtocol(wrapper.user());
info.setServerProtocolVersion(serverProtocol); info.setServerProtocolVersion(serverProtocol);
List<Pair<Integer, Protocol>> protocols = null; List<ProtocolPathEntry> protocols = null;
// Only allow newer clients or (1.9.2 on 1.9.4 server if the server supports it) // Only allow newer clients or (1.9.2 on 1.9.4 server if the server supports it)
if (info.getProtocolVersion() >= serverProtocol || Via.getPlatform().isOldClientsAllowed()) { if (info.getProtocolVersion() >= serverProtocol || Via.getPlatform().isOldClientsAllowed()) {
@ -69,10 +68,10 @@ public class BaseProtocol extends SimpleProtocol {
ProtocolPipeline pipeline = wrapper.user().getProtocolInfo().getPipeline(); ProtocolPipeline pipeline = wrapper.user().getProtocolInfo().getPipeline();
if (protocols != null) { if (protocols != null) {
for (Pair<Integer, Protocol> prot : protocols) { for (ProtocolPathEntry prot : protocols) {
pipeline.add(prot.getValue()); pipeline.add(prot.getProtocol());
// Ensure mapping data has already been loaded // Ensure mapping data has already been loaded
Via.getManager().getProtocolManager().completeMappingDataLoading(prot.getValue().getClass()); Via.getManager().getProtocolManager().completeMappingDataLoading(prot.getProtocol().getClass());
} }
// Set the original snapshot version if present // Set the original snapshot version if present

View File

@ -23,10 +23,9 @@ import com.google.gson.JsonObject;
import com.google.gson.JsonParseException; import com.google.gson.JsonParseException;
import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelFuture;
import us.myles.ViaVersion.api.PacketWrapper; import us.myles.ViaVersion.api.PacketWrapper;
import us.myles.ViaVersion.api.Pair;
import us.myles.ViaVersion.api.Via; import us.myles.ViaVersion.api.Via;
import us.myles.ViaVersion.api.protocol.Protocol;
import us.myles.ViaVersion.api.protocol.ProtocolManagerImpl; import us.myles.ViaVersion.api.protocol.ProtocolManagerImpl;
import us.myles.ViaVersion.api.protocol.ProtocolPathEntry;
import us.myles.ViaVersion.api.protocol.ProtocolVersion; import us.myles.ViaVersion.api.protocol.ProtocolVersion;
import us.myles.ViaVersion.api.protocol.SimpleProtocol; import us.myles.ViaVersion.api.protocol.SimpleProtocol;
import us.myles.ViaVersion.api.remapper.PacketHandler; import us.myles.ViaVersion.api.remapper.PacketHandler;
@ -94,7 +93,7 @@ public class BaseProtocol1_7 extends SimpleProtocol {
} }
int protocol = versionProvider.getServerProtocol(wrapper.user()); int protocol = versionProvider.getServerProtocol(wrapper.user());
List<Pair<Integer, Protocol>> protocols = null; List<ProtocolPathEntry> protocols = null;
// Only allow newer clients or (1.9.2 on 1.9.4 server if the server supports it) // Only allow newer clients or (1.9.2 on 1.9.4 server if the server supports it)
if (info.getProtocolVersion() >= protocol || Via.getPlatform().isOldClientsAllowed()) { if (info.getProtocolVersion() >= protocol || Via.getPlatform().isOldClientsAllowed()) {