// Path: src/main/java/net/techcable/spudcompat/ProtocolVersion.java
// @RequiredArgsConstructor
// public enum ProtocolVersion {
//     v1_7_10(5),
//     v1_8(47);
// 
//     public boolean isBefore(ProtocolVersion other) {
//         return this.getId() < other.getId();
//     }
// 
//     private final int versionNumber;
// 
//     public int getId() {
//         return versionNumber;
//     }
// 
//     public static final int MAX_ID;
//     private static final ProtocolVersion[] BY_ID;
// 
//     static {
//         int maxId = 0;
//         for (ProtocolVersion version : values()) {
//             if (version.getId() > maxId) {
//                 maxId = version.getId();
//             }
//         }
//         MAX_ID = maxId;
//         BY_ID = new ProtocolVersion[MAX_ID + 1];
//         for (ProtocolVersion version : values()) {
//             int id = version.getId();
//             if (BY_ID[id] != null) throw new AssertionError("Already a version with id: " + id);
//             BY_ID[id] = version;
//         }
//     }
// 
//     public static ProtocolVersion getById(int id) {
//         if (id < 0) {
//             throw new IllegalArgumentException("Negative id: " + id);
//         } else if (id < BY_ID.length) {
//             return BY_ID[id];
//         } else {
//             return null;
//         }
//     }
// }


import java.util.Arrays;
import java.util.Map;
import java.util.Optional;
import java.util.OptionalInt;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import net.techcable.spudcompat.ProtocolVersion;
                        throw new IllegalArgumentException("Can't convert between type " + firstType + " for version " + firstVersion + " and type " + secondType + " for version " + secondVersion);
                    }
                }
            }
        }
        indexes.forEach((version, index) -> Preconditions.checkArgument(types.containsKey(version), "Type for version %s not specified, but index (%s) is", version, index));
        MetadataDataType[] typesArray = new MetadataDataType[ProtocolVersion.values().length];
        int[] indexesArray = new int[ProtocolVersion.values().length];
        Arrays.fill(indexesArray, -1);
        types.forEach((version, dataType) -> {
            Preconditions.checkArgument(indexes.containsKey(version), "Index for version %s not specified, byt type (%s) was", version, dataType);
            indexesArray[version.ordinal()] = indexes.get(version);
            typesArray[version.ordinal()] = dataType;
        });
        return new BasicMetadataTransformer(indexesArray, typesArray);
    }

    public static MetadataDataValue convert(MetadataDataValue value, MetadataDataType newType) {
        Preconditions.checkNotNull(value, "Null value");
        if (!canConvertBetween(value.getDataType(), newType)) {
            throw new IllegalArgumentException("Can't convert from " + value.getDataType() + " to " + newType);
        }
        Number num = ((Number) value.getValue());
        switch (newType) {
            case BYTE:
                return MetadataDataValue.ofByte(num.byteValue());
            case SHORT:
                return MetadataDataValue.ofShort(num.shortValue());
            case INT:
                return MetadataDataValue.ofInt(num.intValue());
// Path: src/main/java/net/techcable/spudcompat/ProtocolVersion.java
// @RequiredArgsConstructor
// public enum ProtocolVersion {
//     v1_7_10(5),
//     v1_8(47);
// 
//     public boolean isBefore(ProtocolVersion other) {
//         return this.getId() < other.getId();
//     }
// 
//     private final int versionNumber;
// 
//     public int getId() {
//         return versionNumber;
//     }
// 
//     public static final int MAX_ID;
//     private static final ProtocolVersion[] BY_ID;
// 
//     static {
//         int maxId = 0;
//         for (ProtocolVersion version : values()) {
//             if (version.getId() > maxId) {
//                 maxId = version.getId();
//             }
//         }
//         MAX_ID = maxId;
//         BY_ID = new ProtocolVersion[MAX_ID + 1];
//         for (ProtocolVersion version : values()) {
//             int id = version.getId();
//             if (BY_ID[id] != null) throw new AssertionError("Already a version with id: " + id);
//             BY_ID[id] = version;
//         }
//     }
// 
//     public static ProtocolVersion getById(int id) {
//         if (id < 0) {
//             throw new IllegalArgumentException("Negative id: " + id);
//         } else if (id < BY_ID.length) {
//             return BY_ID[id];
//         } else {
//             return null;
//         }
//     }
// }


// Path: src/main/java/net/techcable/spudcompat/metadata/BasicMetadataTransformer.java
import java.util.Arrays;
import java.util.Map;
import java.util.Optional;
import java.util.OptionalInt;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import net.techcable.spudcompat.ProtocolVersion;

                        throw new IllegalArgumentException("Can't convert between type " + firstType + " for version " + firstVersion + " and type " + secondType + " for version " + secondVersion);
                    }
                }
            }
        }
        indexes.forEach((version, index) -> Preconditions.checkArgument(types.containsKey(version), "Type for version %s not specified, but index (%s) is", version, index));
        MetadataDataType[] typesArray = new MetadataDataType[ProtocolVersion.values().length];
        int[] indexesArray = new int[ProtocolVersion.values().length];
        Arrays.fill(indexesArray, -1);
        types.forEach((version, dataType) -> {
            Preconditions.checkArgument(indexes.containsKey(version), "Index for version %s not specified, byt type (%s) was", version, dataType);
            indexesArray[version.ordinal()] = indexes.get(version);
            typesArray[version.ordinal()] = dataType;
        });
        return new BasicMetadataTransformer(indexesArray, typesArray);
    }

    public static MetadataDataValue convert(MetadataDataValue value, MetadataDataType newType) {
        Preconditions.checkNotNull(value, "Null value");
        if (!canConvertBetween(value.getDataType(), newType)) {
            throw new IllegalArgumentException("Can't convert from " + value.getDataType() + " to " + newType);
        }
        Number num = ((Number) value.getValue());
        switch (newType) {
            case BYTE:
                return MetadataDataValue.ofByte(num.byteValue());
            case SHORT:
                return MetadataDataValue.ofShort(num.shortValue());
            case INT:
                return MetadataDataValue.ofInt(num.intValue());
            case FLOAT: