Handle invalid command argument types

The client ignores these presumably for modded servers
Fixes #3806
This commit is contained in:
Nassim Jahnke 2024-04-27 11:25:37 +02:00
parent c9733948b3
commit 7ec6888a30
No known key found for this signature in database
GPG Key ID: EF6771C01F6EF02F
3 changed files with 42 additions and 11 deletions

View File

@ -49,17 +49,17 @@ public interface FullMappings extends BiMappings {
* Returns the unmapped string identifier for the given mapped id.
*
* @param id unmapped id
* @return unmapped string identifier
* @return unmapped string identifier, or null if out of bounds
*/
String identifier(int id);
@Nullable String identifier(int id);
/**
* Returns the mapped string identifier for the given mapped id.
*
* @param mappedId mapped id
* @return mapped string identifier
* @return mapped string identifier, or null if out of bounds
*/
String mappedIdentifier(int mappedId);
@Nullable String mappedIdentifier(int mappedId);
/**
* Returns the mapped string identifier for the given unmapped identifier.

View File

@ -66,12 +66,20 @@ public class FullMappingsBase implements FullMappings {
@Override
public String identifier(final int id) {
if (id < 0 || id >= idToString.length) {
return null;
}
final String identifier = idToString[id];
return Key.namespaced(identifier);
}
@Override
public String mappedIdentifier(final int mappedId) {
if (mappedId < 0 || mappedId >= mappedIdToString.length) {
return null;
}
final String identifier = mappedIdToString[mappedId];
return Key.namespaced(identifier);
}

View File

@ -18,12 +18,14 @@
package com.viaversion.viaversion.rewriter;
import com.google.common.base.Preconditions;
import com.viaversion.viaversion.api.data.FullMappings;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Type;
import java.util.HashMap;
import java.util.Map;
import org.checkerframework.checker.nullness.qual.Nullable;
/**
* Abstract rewriter for the declare commands packet to handle argument type name and content changes.
@ -118,16 +120,23 @@ public class CommandRewriter<C extends ClientboundPacketType> {
if (nodeType == 2) { // Argument node
int argumentTypeId = wrapper.read(Type.VAR_INT);
String argumentType = argumentType(argumentTypeId);
if (argumentType == null) {
// Modded servers may send unknown argument types that are ignored by the client
// Adjust the id to the hopefully still assumed out-of-bounds pos...
wrapper.write(Type.VAR_INT, mapInvalidArgumentType(argumentTypeId));
continue;
}
String newArgumentType = handleArgumentType(argumentType);
Preconditions.checkNotNull(newArgumentType, "No mapping for argument type %s", argumentType);
wrapper.write(Type.VAR_INT, mappedArgumentTypeId(newArgumentType));
// Always call the handler using the previous name
handleArgument(wrapper, argumentType);
}
if ((flags & 0x10) != 0) {
wrapper.passthrough(Type.STRING); // Suggestion type
if ((flags & 0x10) != 0) {
wrapper.passthrough(Type.STRING); // Suggestion type
}
}
}
@ -148,21 +157,35 @@ public class CommandRewriter<C extends ClientboundPacketType> {
* @param argumentType argument type
* @return mapped argument type
*/
public String handleArgumentType(String argumentType) {
public String handleArgumentType(final String argumentType) {
if (protocol.getMappingData() != null && protocol.getMappingData().getArgumentTypeMappings() != null) {
return protocol.getMappingData().getArgumentTypeMappings().mappedIdentifier(argumentType);
}
return argumentType;
}
protected String argumentType(int argumentTypeId) {
return protocol.getMappingData().getArgumentTypeMappings().identifier(argumentTypeId);
protected @Nullable String argumentType(final int argumentTypeId) {
final FullMappings mappings = protocol.getMappingData().getArgumentTypeMappings();
final String identifier = mappings.identifier(argumentTypeId);
// Allow unknown argument types to be passed through as long as they are actually out of bounds
Preconditions.checkArgument(identifier != null || argumentTypeId >= mappings.size(), "Unknown argument type id %s", argumentTypeId);
return identifier;
}
protected int mappedArgumentTypeId(String mappedArgumentType) {
protected int mappedArgumentTypeId(final String mappedArgumentType) {
return protocol.getMappingData().getArgumentTypeMappings().mappedId(mappedArgumentType);
}
private int mapInvalidArgumentType(final int id) {
if (id < 0) {
return id;
}
final FullMappings mappings = protocol.getMappingData().getArgumentTypeMappings();
final int idx = id - mappings.size();
return mappings.mappedSize() + idx;
}
@FunctionalInterface
public interface CommandArgumentConsumer {