Merge pull request #1799 from KennyTV/abstraction

Use FastUtil collections for frequently called code
This commit is contained in:
Myles 2020-06-09 15:50:23 +01:00 committed by GitHub
commit 7be8c9d8aa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 357 additions and 269 deletions

View File

@ -19,5 +19,13 @@
<version>1.18</version> <version>1.18</version>
<scope>compile</scope> <!-- Velocity doesn't have snakeyaml --> <scope>compile</scope> <!-- Velocity doesn't have snakeyaml -->
</dependency> </dependency>
<!-- FastUtil for performance increases -->
<dependency>
<groupId>it.unimi.dsi</groupId>
<artifactId>fastutil</artifactId>
<version>8.3.1</version>
<scope>compile</scope>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -91,12 +91,11 @@ public class Entity1_13Types {
// Fish // Fish
ABSTRACT_FISHES(-1, ABSTRACT_CREATURE), // agb ABSTRACT_FISHES(-1, ABSTRACT_CREATURE), // agb
COD_MOB(8, ABSTRACT_FISHES), // agf COD(8, ABSTRACT_FISHES), // agf
PUFFERFISH(52, ABSTRACT_FISHES), // agn PUFFERFISH(52, ABSTRACT_FISHES), // agn
SALMON(57, ABSTRACT_FISHES), // agp SALMON(57, ABSTRACT_FISHES), // agp
TROPICAL_FISH(72, ABSTRACT_FISHES), // agu TROPICAL_FISH(72, ABSTRACT_FISHES), // agu
// Monsters // Monsters
ABSTRACT_MONSTER(-1, ABSTRACT_CREATURE), // ajs ABSTRACT_MONSTER(-1, ABSTRACT_CREATURE), // ajs
BLAZE(4, ABSTRACT_MONSTER), // ajd BLAZE(4, ABSTRACT_MONSTER), // ajd
@ -248,7 +247,7 @@ public class Entity1_13Types {
ENDER_PEARL(65, EntityType.ENDER_PEARL), ENDER_PEARL(65, EntityType.ENDER_PEARL),
WITHER_SKULL(66, EntityType.WITHER_SKULL), WITHER_SKULL(66, EntityType.WITHER_SKULL),
SHULKER_BULLET(67, EntityType.SHULKER_BULLET), SHULKER_BULLET(67, EntityType.SHULKER_BULLET),
LIAMA_SPIT(68, EntityType.LLAMA_SPIT), LLAMA_SPIT(68, EntityType.LLAMA_SPIT),
FALLING_BLOCK(70, EntityType.FALLING_BLOCK), FALLING_BLOCK(70, EntityType.FALLING_BLOCK),
ITEM_FRAME(71, EntityType.ITEM_FRAME), ITEM_FRAME(71, EntityType.ITEM_FRAME),
EYE_OF_ENDER(72, EntityType.EYE_OF_ENDER), EYE_OF_ENDER(72, EntityType.EYE_OF_ENDER),

View File

@ -2,6 +2,8 @@ package us.myles.ViaVersion.api.protocol;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Range; import com.google.common.collect.Range;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import us.myles.ViaVersion.api.Pair; import us.myles.ViaVersion.api.Pair;
import us.myles.ViaVersion.api.Via; import us.myles.ViaVersion.api.Via;
@ -52,7 +54,7 @@ public class ProtocolRegistry {
public static final Protocol BASE_PROTOCOL = new BaseProtocol(); public static final Protocol BASE_PROTOCOL = new BaseProtocol();
public static int SERVER_PROTOCOL = -1; public static int SERVER_PROTOCOL = -1;
// Input Version -> Output Version & Protocol (Allows fast lookup) // Input Version -> Output Version & Protocol (Allows fast lookup)
private static final Map<Integer, Map<Integer, Protocol>> registryMap = new ConcurrentHashMap<>(); private static final Int2ObjectMap<Int2ObjectMap<Protocol>> registryMap = new Int2ObjectOpenHashMap<>(32);
private static final Map<Class<? extends Protocol>, Protocol> protocols = new HashMap<>(); private static final Map<Class<? extends Protocol>, Protocol> protocols = new HashMap<>();
private static final Map<Pair<Integer, Integer>, List<Pair<Integer, Protocol>>> pathCache = new ConcurrentHashMap<>(); private static final Map<Pair<Integer, Integer>, List<Pair<Integer, Protocol>>> pathCache = new ConcurrentHashMap<>();
private static final Set<Integer> supportedVersions = new HashSet<>(); private static final Set<Integer> supportedVersions = new HashSet<>();
@ -126,7 +128,7 @@ public class ProtocolRegistry {
* @param supported Supported client versions. * @param supported Supported client versions.
* @param output The output server version it converts to. * @param output The output server version it converts to.
*/ */
public static void registerProtocol(Protocol protocol, List<Integer> supported, Integer output) { public static void registerProtocol(Protocol protocol, List<Integer> supported, int output) {
// Clear cache as this may make new routes. // Clear cache as this may make new routes.
if (!pathCache.isEmpty()) { if (!pathCache.isEmpty()) {
pathCache.clear(); pathCache.clear();
@ -135,7 +137,7 @@ public class ProtocolRegistry {
protocols.put(protocol.getClass(), protocol); protocols.put(protocol.getClass(), protocol);
for (int version : supported) { for (int version : supported) {
Map<Integer, Protocol> protocolMap = registryMap.computeIfAbsent(version, k -> new HashMap<>()); Int2ObjectMap<Protocol> protocolMap = registryMap.computeIfAbsent(version, s -> new Int2ObjectOpenHashMap<>(2));
protocolMap.put(output, protocol); protocolMap.put(output, protocol);
} }
@ -204,8 +206,8 @@ public class ProtocolRegistry {
* @return True if there is a useful pipe * @return True if there is a useful pipe
*/ */
public static boolean isWorkingPipe() { public static boolean isWorkingPipe() {
for (Map<Integer, Protocol> maps : registryMap.values()) { for (Int2ObjectMap<Protocol> map : registryMap.values()) {
if (maps.containsKey(SERVER_PROTOCOL)) return true; if (map.containsKey(SERVER_PROTOCOL)) return true;
} }
return false; // No destination for protocol return false; // No destination for protocol
} }
@ -234,25 +236,28 @@ public class ProtocolRegistry {
if (current.size() > 50) return null; // Fail safe, protocol too complicated. if (current.size() > 50) return null; // Fail safe, protocol too complicated.
// First check if there is any protocols for this // First check if there is any protocols for this
Map<Integer, Protocol> inputMap = registryMap.get(clientVersion); Int2ObjectMap<Protocol> inputMap = registryMap.get(clientVersion);
if (inputMap == null) { if (inputMap == null) {
return null; // Not supported return null; // Not supported
} }
// 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 Pair<>(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<Pair<Integer, Protocol>> shortest = null;
for (Int2ObjectMap.Entry<Protocol> entry : inputMap.int2ObjectEntrySet()) {
for (Map.Entry<Integer, Protocol> entry : inputMap.entrySet()) {
// Ensure it wasn't caught by the other loop // Ensure it wasn't caught by the other loop
if (!entry.getKey().equals(serverVersion)) { if (entry.getIntKey() == (serverVersion)) continue;
Pair<Integer, Protocol> pair = new Pair<>(entry.getKey(), entry.getValue());
Pair<Integer, Protocol> pair = new Pair<>(entry.getIntKey(), entry.getValue());
// Ensure no recursion // Ensure no recursion
if (!current.contains(pair)) { if (current.contains(pair)) continue;
// Create a copy // Create a copy
List<Pair<Integer, Protocol>> newCurrent = new ArrayList<>(current); List<Pair<Integer, Protocol>> newCurrent = new ArrayList<>(current);
newCurrent.add(pair); newCurrent.add(pair);
@ -265,8 +270,6 @@ public class ProtocolRegistry {
} }
} }
} }
}
}
return shortest; // null if none found return shortest; // null if none found
} }

View File

@ -1,5 +1,7 @@
package us.myles.ViaVersion.api.rewriters; package us.myles.ViaVersion.api.rewriters;
import it.unimi.dsi.fastutil.ints.Int2IntMap;
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
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;
@ -23,7 +25,7 @@ import java.util.logging.Logger;
public abstract class MetadataRewriter { public abstract class MetadataRewriter {
private final Class<? extends EntityTracker> entityTrackerClass; private final Class<? extends EntityTracker> entityTrackerClass;
private final Protocol protocol; private final Protocol protocol;
private Map<Integer, Integer> typeMapping; private Int2IntMap typeMapping;
protected MetadataRewriter(Protocol protocol, Class<? extends EntityTracker> entityTrackerClass) { protected MetadataRewriter(Protocol protocol, Class<? extends EntityTracker> entityTrackerClass) {
this.protocol = protocol; this.protocol = protocol;
@ -182,7 +184,10 @@ public abstract class MetadataRewriter {
} }
public <T extends Enum<T> & EntityType> void mapTypes(EntityType[] oldTypes, Class<T> newTypeClass) { public <T extends Enum<T> & EntityType> void mapTypes(EntityType[] oldTypes, Class<T> newTypeClass) {
if (typeMapping == null) typeMapping = new HashMap<>(oldTypes.length); if (typeMapping == null) {
typeMapping = new Int2IntOpenHashMap(oldTypes.length, 1F);
typeMapping.defaultReturnValue(-1);
}
for (EntityType oldType : oldTypes) { for (EntityType oldType : oldTypes) {
try { try {
T newType = Enum.valueOf(newTypeClass, oldType.name()); T newType = Enum.valueOf(newTypeClass, oldType.name());
@ -190,14 +195,17 @@ public abstract class MetadataRewriter {
} catch (IllegalArgumentException notFound) { } catch (IllegalArgumentException notFound) {
if (!typeMapping.containsKey(oldType.getId())) { if (!typeMapping.containsKey(oldType.getId())) {
Via.getPlatform().getLogger().warning("Could not find new entity type for " + oldType + "! " + Via.getPlatform().getLogger().warning("Could not find new entity type for " + oldType + "! " +
"Old type: " + oldType.getClass().getSimpleName() + " New type: " + newTypeClass.getSimpleName()); "Old type: " + oldType.getClass().getEnclosingClass().getSimpleName() + ", new type: " + newTypeClass.getEnclosingClass().getSimpleName());
} }
} }
} }
} }
public void mapType(EntityType oldType, EntityType newType) { public void mapType(EntityType oldType, EntityType newType) {
if (typeMapping == null) typeMapping = new HashMap<>(); if (typeMapping == null) {
typeMapping = new Int2IntOpenHashMap();
typeMapping.defaultReturnValue(-1);
}
typeMapping.put(oldType.getId(), newType.getId()); typeMapping.put(oldType.getId(), newType.getId());
} }

View File

@ -346,8 +346,8 @@ public class Protocol1_13To1_12_2 extends Protocol<ClientboundPackets1_12_1, Cli
} }
} else { } else {
for (int i = 0; i < 16; i++) { for (int i = 0; i < 16; i++) {
Integer newItem = MappingData.oldToNewItems.get(item << 4 | i); int newItem = MappingData.oldToNewItems.get(item << 4 | i);
if (newItem != null) { if (newItem != -1) {
PacketWrapper packet = wrapper.create(0x18); PacketWrapper packet = wrapper.create(0x18);
packet.write(Type.VAR_INT, newItem); packet.write(Type.VAR_INT, newItem);
packet.write(Type.VAR_INT, ticks); packet.write(Type.VAR_INT, ticks);

View File

@ -3,6 +3,10 @@ package us.myles.ViaVersion.protocols.protocol1_13to1_12_2.blockconnections;
import com.google.gson.JsonArray; import com.google.gson.JsonArray;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet;
import us.myles.ViaVersion.api.PacketWrapper; import us.myles.ViaVersion.api.PacketWrapper;
import us.myles.ViaVersion.api.Via; import us.myles.ViaVersion.api.Via;
import us.myles.ViaVersion.api.data.MappingDataLoader; import us.myles.ViaVersion.api.data.MappingDataLoader;
@ -17,17 +21,21 @@ import us.myles.ViaVersion.protocols.protocol1_13to1_12_2.Protocol1_13To1_12_2;
import us.myles.ViaVersion.protocols.protocol1_13to1_12_2.blockconnections.providers.BlockConnectionProvider; import us.myles.ViaVersion.protocols.protocol1_13to1_12_2.blockconnections.providers.BlockConnectionProvider;
import us.myles.ViaVersion.protocols.protocol1_13to1_12_2.blockconnections.providers.PacketBlockConnectionProvider; import us.myles.ViaVersion.protocols.protocol1_13to1_12_2.blockconnections.providers.PacketBlockConnectionProvider;
import java.util.*; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
public class ConnectionData { public class ConnectionData {
private static final BlockChangeRecord[] A = new BlockChangeRecord[0]; private static final BlockChangeRecord[] A = new BlockChangeRecord[0];
public static BlockConnectionProvider blockConnectionProvider; public static BlockConnectionProvider blockConnectionProvider;
static Map<Integer, String> idToKey = new HashMap<>(); static Int2ObjectMap<String> idToKey = new Int2ObjectOpenHashMap<>(8582, 1F);
static Map<String, Integer> keyToId = new HashMap<>(); static Map<String, Integer> keyToId = new HashMap<>(8582, 1F);
static Map<Integer, ConnectionHandler> connectionHandlerMap = new HashMap<>(); static Int2ObjectMap<ConnectionHandler> connectionHandlerMap = new Int2ObjectOpenHashMap<>(1);
static Map<Integer, BlockData> blockConnectionData = new HashMap<>(); static Int2ObjectMap<BlockData> blockConnectionData = new Int2ObjectOpenHashMap<>(1);
static Set<Integer> occludingStates = new HashSet<>(); static IntSet occludingStates = new IntOpenHashSet(377, 1F);
public static void update(UserConnection user, Position position) { public static void update(UserConnection user, Position position) {
for (BlockFace face : BlockFace.values()) { for (BlockFace face : BlockFace.values()) {
@ -194,17 +202,21 @@ public class ConnectionData {
public static void init() { public static void init() {
if (!Via.getConfig().isServersideBlockConnections()) return; if (!Via.getConfig().isServersideBlockConnections()) return;
Via.getPlatform().getLogger().info("Loading block connection mappings ..."); Via.getPlatform().getLogger().info("Loading block connection mappings ...");
JsonObject mapping1_13 = MappingDataLoader.loadData("mapping-1.13.json", true); JsonObject mapping1_13 = MappingDataLoader.loadData("mapping-1.13.json", true);
JsonObject blocks1_13 = mapping1_13.getAsJsonObject("blocks"); JsonObject blocks1_13 = mapping1_13.getAsJsonObject("blocks");
for (Entry<String, JsonElement> blockState : blocks1_13.entrySet()) { for (Entry<String, JsonElement> blockState : blocks1_13.entrySet()) {
Integer id = Integer.parseInt(blockState.getKey()); int id = Integer.parseInt(blockState.getKey());
String key = blockState.getValue().getAsString(); String key = blockState.getValue().getAsString();
idToKey.put(id, key); idToKey.put(id, key);
keyToId.put(key, id); keyToId.put(key, id);
} }
connectionHandlerMap = new Int2ObjectOpenHashMap<>(3650, 1F);
if (!Via.getConfig().isReduceBlockStorageMemory()) { if (!Via.getConfig().isReduceBlockStorageMemory()) {
blockConnectionData = new Int2ObjectOpenHashMap<>(1146, 1F);
JsonObject mappingBlockConnections = MappingDataLoader.loadData("blockConnections.json"); JsonObject mappingBlockConnections = MappingDataLoader.loadData("blockConnections.json");
for (Entry<String, JsonElement> entry : mappingBlockConnections.entrySet()) { for (Entry<String, JsonElement> entry : mappingBlockConnections.entrySet()) {
int id = keyToId.get(entry.getKey()); int id = keyToId.get(entry.getKey());
@ -231,7 +243,7 @@ public class ConnectionData {
JsonObject blockData = MappingDataLoader.loadData("blockData.json"); JsonObject blockData = MappingDataLoader.loadData("blockData.json");
JsonArray occluding = blockData.getAsJsonArray("occluding"); JsonArray occluding = blockData.getAsJsonArray("occluding");
for (JsonElement jsonElement : occluding) { for (JsonElement jsonElement : occluding) {
occludingStates.add(keyToId.get(jsonElement.getAsString())); occludingStates.add(keyToId.get(jsonElement.getAsString()).intValue());
} }
List<ConnectorInitAction> initActions = new ArrayList<>(); List<ConnectorInitAction> initActions = new ArrayList<>();

View File

@ -1,18 +1,18 @@
package us.myles.ViaVersion.protocols.protocol1_13to1_12_2.blockconnections; package us.myles.ViaVersion.protocols.protocol1_13to1_12_2.blockconnections;
import it.unimi.dsi.fastutil.ints.Int2IntMap;
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
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.minecraft.BlockFace; import us.myles.ViaVersion.api.minecraft.BlockFace;
import us.myles.ViaVersion.api.minecraft.Position; import us.myles.ViaVersion.api.minecraft.Position;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map;
import java.util.Set; import java.util.Set;
public class FlowerConnectionHandler extends ConnectionHandler { public class FlowerConnectionHandler extends ConnectionHandler {
private static final Map<Integer, Integer> flowers = new HashMap<>(); private static final Int2IntMap flowers = new Int2IntOpenHashMap();
static ConnectionData.ConnectorInitAction init() { static ConnectionData.ConnectorInitAction init() {
final Set<String> baseFlower = new HashSet<>(); final Set<String> baseFlower = new HashSet<>();
@ -38,8 +38,8 @@ public class FlowerConnectionHandler extends ConnectionHandler {
@Override @Override
public int connect(UserConnection user, Position position, int blockState) { public int connect(UserConnection user, Position position, int blockState) {
int blockBelowId = getBlockData(user, position.getRelative(BlockFace.BOTTOM)); int blockBelowId = getBlockData(user, position.getRelative(BlockFace.BOTTOM));
Integer connectBelow = flowers.get(blockBelowId); int connectBelow = flowers.get(blockBelowId);
if (connectBelow != null) { if (connectBelow != 0) {
int blockAboveId = getBlockData(user, position.getRelative(BlockFace.TOP)); int blockAboveId = getBlockData(user, position.getRelative(BlockFace.TOP));
if (Via.getConfig().isStemWhenBlockAbove()) { if (Via.getConfig().isStemWhenBlockAbove()) {
if (blockAboveId == 0) { if (blockAboveId == 0) {

View File

@ -1,18 +1,18 @@
package us.myles.ViaVersion.protocols.protocol1_13to1_12_2.blockconnections; package us.myles.ViaVersion.protocols.protocol1_13to1_12_2.blockconnections;
import it.unimi.dsi.fastutil.ints.Int2IntMap;
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
import us.myles.ViaVersion.api.data.UserConnection; import us.myles.ViaVersion.api.data.UserConnection;
import us.myles.ViaVersion.api.minecraft.BlockFace; import us.myles.ViaVersion.api.minecraft.BlockFace;
import us.myles.ViaVersion.api.minecraft.Position; import us.myles.ViaVersion.api.minecraft.Position;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map;
import java.util.Set; import java.util.Set;
public class RedstoneConnectionHandler extends ConnectionHandler { public class RedstoneConnectionHandler extends ConnectionHandler {
private static final Set<Integer> redstone = new HashSet<>(); private static final Set<Integer> redstone = new HashSet<>();
private static final Map<Short, Integer> connectedBlockStates = new HashMap<>(); private static final Int2IntMap connectedBlockStates = new Int2IntOpenHashMap(1296);
private static final Map<Integer, Integer> powerMappings = new HashMap<>(); private static final Int2IntMap powerMappings = new Int2IntOpenHashMap(1296);
static ConnectionData.ConnectorInitAction init() { static ConnectionData.ConnectorInitAction init() {
final RedstoneConnectionHandler connectionHandler = new RedstoneConnectionHandler(); final RedstoneConnectionHandler connectionHandler = new RedstoneConnectionHandler();
@ -22,7 +22,7 @@ public class RedstoneConnectionHandler extends ConnectionHandler {
redstone.add(blockData.getSavedBlockStateId()); redstone.add(blockData.getSavedBlockStateId());
ConnectionData.connectionHandlerMap.put(blockData.getSavedBlockStateId(), connectionHandler); ConnectionData.connectionHandlerMap.put(blockData.getSavedBlockStateId(), connectionHandler);
connectedBlockStates.put(getStates(blockData), blockData.getSavedBlockStateId()); connectedBlockStates.put(getStates(blockData), blockData.getSavedBlockStateId());
powerMappings.put(blockData.getSavedBlockStateId(), Integer.valueOf(blockData.getValue("power"))); powerMappings.put(blockData.getSavedBlockStateId(), Integer.parseInt(blockData.getValue("power")));
}; };
} }
@ -57,8 +57,7 @@ public class RedstoneConnectionHandler extends ConnectionHandler {
b |= connects(user, position, BlockFace.SOUTH) << 4; b |= connects(user, position, BlockFace.SOUTH) << 4;
b |= connects(user, position, BlockFace.WEST) << 6; b |= connects(user, position, BlockFace.WEST) << 6;
b |= powerMappings.get(blockState) << 8; b |= powerMappings.get(blockState) << 8;
final Integer newBlockState = connectedBlockStates.get(b); return connectedBlockStates.getOrDefault(b, blockState);
return newBlockState == null ? blockState : newBlockState;
} }
private int connects(UserConnection user, Position position, BlockFace side) { private int connects(UserConnection user, Position position, BlockFace side) {

View File

@ -2,6 +2,8 @@ package us.myles.ViaVersion.protocols.protocol1_13to1_12_2.data;
import com.google.common.collect.ObjectArrays; import com.google.common.collect.ObjectArrays;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import us.myles.ViaVersion.util.GsonUtil; import us.myles.ViaVersion.util.GsonUtil;
import java.io.IOException; import java.io.IOException;
@ -13,18 +15,18 @@ import java.util.Map;
public class BlockIdData { public class BlockIdData {
public static Map<String, String[]> blockIdMapping; public static Map<String, String[]> blockIdMapping;
public static Map<String, String[]> fallbackReverseMapping; public static Map<String, String[]> fallbackReverseMapping;
public static Map<Integer, String> numberIdToString; public static Int2ObjectMap<String> numberIdToString;
public static void init() { public static void init() {
InputStream stream = MappingData.class.getClassLoader() InputStream stream = MappingData.class.getClassLoader()
.getResourceAsStream("assets/viaversion/data/blockIds1.12to1.13.json"); .getResourceAsStream("assets/viaversion/data/blockIds1.12to1.13.json");
InputStreamReader reader = new InputStreamReader(stream); InputStreamReader reader = new InputStreamReader(stream);
try { try {
blockIdMapping = new HashMap<>((Map<String, String[]>) GsonUtil.getGson().fromJson( blockIdMapping = new HashMap<>(GsonUtil.getGson().fromJson(
reader, reader,
new TypeToken<Map<String, String[]>>() { new TypeToken<Map<String, String[]>>() {
}.getType() }.getType()
)); ), 1F);
fallbackReverseMapping = new HashMap<>(); fallbackReverseMapping = new HashMap<>();
for (Map.Entry<String, String[]> entry : blockIdMapping.entrySet()) { for (Map.Entry<String, String[]> entry : blockIdMapping.entrySet()) {
for (String val : entry.getValue()) { for (String val : entry.getValue()) {
@ -45,7 +47,7 @@ public class BlockIdData {
.getResourceAsStream("assets/viaversion/data/blockNumberToString1.12.json"); .getResourceAsStream("assets/viaversion/data/blockNumberToString1.12.json");
InputStreamReader blockR = new InputStreamReader(blockS); InputStreamReader blockR = new InputStreamReader(blockS);
try { try {
numberIdToString = new HashMap<>((Map<Integer, String>) GsonUtil.getGson().fromJson( numberIdToString = new Int2ObjectOpenHashMap<>(GsonUtil.getGson().fromJson(
blockR, blockR,
new TypeToken<Map<Integer, String>>() { new TypeToken<Map<Integer, String>>() {
}.getType() }.getType()

View File

@ -1,14 +1,13 @@
package us.myles.ViaVersion.protocols.protocol1_13to1_12_2.data; package us.myles.ViaVersion.protocols.protocol1_13to1_12_2.data;
import it.unimi.dsi.fastutil.ints.Int2IntMap;
import java.util.HashMap; import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
import java.util.Map;
import java.util.Optional;
public class EntityTypeRewriter { public class EntityTypeRewriter {
private static final Map<Integer, Integer> entityTypes = new HashMap<>(); private static final Int2IntMap ENTITY_TYPES = new Int2IntOpenHashMap(83, 1F);
static { static {
ENTITY_TYPES.defaultReturnValue(-1);
registerEntity(1, 32); // item - ajl registerEntity(1, 32); // item - ajl
registerEntity(2, 22); // xp_orb - abx registerEntity(2, 22); // xp_orb - abx
registerEntity(3, 0); // area_effect_cloud - abp registerEntity(3, 0); // area_effect_cloud - abp
@ -92,16 +91,13 @@ public class EntityTypeRewriter {
registerEntity(104, 37); // llama_spit - alr registerEntity(104, 37); // llama_spit - alr
registerEntity(105, 50); // parrot - agx registerEntity(105, 50); // parrot - agx
registerEntity(120, 79); // villager - ala registerEntity(120, 79); // villager - ala
// OBJECTS
// Couldn't find any object id change with mapped values
} }
private static void registerEntity(int type1_12, int type1_13) { private static void registerEntity(int type1_12, int type1_13) {
entityTypes.put(type1_12, type1_13); ENTITY_TYPES.put(type1_12, type1_13);
} }
public static Optional<Integer> getNewId(int type1_12) { public static int getNewId(int type1_12) {
return Optional.ofNullable(entityTypes.get(type1_12)); return ENTITY_TYPES.getOrDefault(type1_12, type1_12);
} }
} }

View File

@ -11,6 +11,7 @@ import us.myles.ViaVersion.api.Via;
import us.myles.ViaVersion.api.data.MappingDataLoader; import us.myles.ViaVersion.api.data.MappingDataLoader;
import us.myles.ViaVersion.api.data.Mappings; import us.myles.ViaVersion.api.data.Mappings;
import us.myles.ViaVersion.util.GsonUtil; import us.myles.ViaVersion.util.GsonUtil;
import us.myles.ViaVersion.util.Int2IntBiMap;
import java.io.IOException; import java.io.IOException;
import java.io.InputStreamReader; import java.io.InputStreamReader;
@ -20,7 +21,7 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
public class MappingData { public class MappingData {
public static final BiMap<Integer, Integer> oldToNewItems = HashBiMap.create(); public static final Int2IntBiMap oldToNewItems = new Int2IntBiMap();
public static final Map<String, Integer[]> blockTags = new HashMap<>(); public static final Map<String, Integer[]> blockTags = new HashMap<>();
public static final Map<String, Integer[]> itemTags = new HashMap<>(); public static final Map<String, Integer[]> itemTags = new HashMap<>();
public static final Map<String, Integer[]> fluidTags = new HashMap<>(); public static final Map<String, Integer[]> fluidTags = new HashMap<>();
@ -37,6 +38,7 @@ public class MappingData {
JsonObject mapping1_12 = MappingDataLoader.loadData("mapping-1.12.json", true); JsonObject mapping1_12 = MappingDataLoader.loadData("mapping-1.12.json", true);
JsonObject mapping1_13 = MappingDataLoader.loadData("mapping-1.13.json", true); JsonObject mapping1_13 = MappingDataLoader.loadData("mapping-1.13.json", true);
oldToNewItems.defaultReturnValue(-1);
blockMappings = new BlockMappingsShortArray(mapping1_12.getAsJsonObject("blocks"), mapping1_13.getAsJsonObject("blocks")); blockMappings = new BlockMappingsShortArray(mapping1_12.getAsJsonObject("blocks"), mapping1_13.getAsJsonObject("blocks"));
MappingDataLoader.mapIdentifiers(oldToNewItems, mapping1_12.getAsJsonObject("items"), mapping1_13.getAsJsonObject("items")); MappingDataLoader.mapIdentifiers(oldToNewItems, mapping1_12.getAsJsonObject("items"), mapping1_13.getAsJsonObject("items"));
loadTags(blockTags, mapping1_13.getAsJsonObject("block_tags")); loadTags(blockTags, mapping1_13.getAsJsonObject("block_tags"));

View File

@ -102,7 +102,7 @@ public class MetadataRewriter1_13To1_12_2 extends MetadataRewriter {
@Override @Override
public int getNewEntityId(final int oldId) { public int getNewEntityId(final int oldId) {
return EntityTypeRewriter.getNewId(oldId).orElse(oldId); return EntityTypeRewriter.getNewId(oldId);
} }
@Override @Override

View File

@ -435,7 +435,7 @@ public class InventoryPackets {
} }
} }
item.setIdentifier(MappingData.oldToNewItems.get(rawId).shortValue()); item.setIdentifier(MappingData.oldToNewItems.get(rawId));
item.setData((short) 0); item.setData((short) 0);
} }
@ -487,8 +487,8 @@ public class InventoryPackets {
} }
if (rawId == null) { if (rawId == null) {
Integer oldId = MappingData.oldToNewItems.inverse().get(item.getIdentifier()); int oldId = MappingData.oldToNewItems.inverse().get(item.getIdentifier());
if (oldId != null) { if (oldId != -1) {
// Handle spawn eggs // Handle spawn eggs
Optional<String> eggEntityId = SpawnEggRewriter.getEntityId(oldId); Optional<String> eggEntityId = SpawnEggRewriter.getEntityId(oldId);
if (eggEntityId.isPresent()) { if (eggEntityId.isPresent()) {

View File

@ -1,6 +1,8 @@
package us.myles.ViaVersion.protocols.protocol1_13to1_12_2.packets; package us.myles.ViaVersion.protocols.protocol1_13to1_12_2.packets;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet;
import us.myles.ViaVersion.api.PacketWrapper; import us.myles.ViaVersion.api.PacketWrapper;
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;
@ -27,31 +29,29 @@ import us.myles.ViaVersion.protocols.protocol1_13to1_12_2.types.Chunk1_13Type;
import us.myles.ViaVersion.protocols.protocol1_9_1_2to1_9_3_4.types.Chunk1_9_3_4Type; import us.myles.ViaVersion.protocols.protocol1_9_1_2to1_9_3_4.types.Chunk1_9_3_4Type;
import us.myles.ViaVersion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld; import us.myles.ViaVersion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.Set;
public class WorldPackets { public class WorldPackets {
private static final Set<Integer> validBiomes = new HashSet<>(); private static final IntSet VALID_BIOMES = new IntOpenHashSet(70, 1F);
static { static {
// Client will crash if it receives a invalid biome id // Client will crash if it receives a invalid biome id
for (int i = 0; i < 50; i++) { for (int i = 0; i < 50; i++) {
validBiomes.add(i); VALID_BIOMES.add(i);
} }
validBiomes.add(127); VALID_BIOMES.add(127);
for (int i = 129; i <= 134; i++) { for (int i = 129; i <= 134; i++) {
validBiomes.add(i); VALID_BIOMES.add(i);
} }
validBiomes.add(140); VALID_BIOMES.add(140);
validBiomes.add(149); VALID_BIOMES.add(149);
validBiomes.add(151); VALID_BIOMES.add(151);
for (int i = 155; i <= 158; i++) { for (int i = 155; i <= 158; i++) {
validBiomes.add(i); VALID_BIOMES.add(i);
} }
for (int i = 160; i <= 167; i++) { for (int i = 160; i <= 167; i++) {
validBiomes.add(i); VALID_BIOMES.add(i);
} }
} }
@ -407,7 +407,7 @@ public class WorldPackets {
int latestBiomeWarn = Integer.MIN_VALUE; int latestBiomeWarn = Integer.MIN_VALUE;
for (int i = 0; i < 256; i++) { for (int i = 0; i < 256; i++) {
int biome = chunk.getBiomeData()[i]; int biome = chunk.getBiomeData()[i];
if (!validBiomes.contains(biome)) { if (!VALID_BIOMES.contains(biome)) {
if (biome != 255 // is it generated naturally? *shrug* if (biome != 255 // is it generated naturally? *shrug*
&& latestBiomeWarn != biome) { && latestBiomeWarn != biome) {
if (!Via.getConfig().isSuppressConversionWarnings() || Via.getManager().isDebug()) { if (!Via.getConfig().isSuppressConversionWarnings() || Via.getManager().isDebug()) {

View File

@ -11,25 +11,29 @@ import us.myles.ViaVersion.protocols.protocol1_13to1_12_2.packets.WorldPackets;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
public class BlockConnectionStorage extends StoredObject { public class BlockConnectionStorage extends StoredObject {
private final Map<Long, Pair<byte[], NibbleArray>> blockStorage = createLongObjectMap(); private static final short[] REVERSE_BLOCK_MAPPINGS = new short[8582];
private static final Map<Short, Short> reverseBlockMappings;
private static Constructor<?> fastUtilLongObjectHashMap; private static Constructor<?> fastUtilLongObjectHashMap;
private final Map<Long, Pair<byte[], NibbleArray>> blockStorage = createLongObjectMap();
static { static {
try { try {
fastUtilLongObjectHashMap = Class.forName("it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap").getConstructor(); fastUtilLongObjectHashMap = Class.forName("it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap").getConstructor();
Via.getPlatform().getLogger().info("Using FastUtil Long2ObjectOpenHashMap for block connections"); Via.getPlatform().getLogger().info("Using FastUtil Long2ObjectOpenHashMap for block connections");
} catch (ClassNotFoundException | NoSuchMethodException ignored) { } catch (ClassNotFoundException | NoSuchMethodException ignored) {
} }
reverseBlockMappings = new HashMap<>();
Arrays.fill(REVERSE_BLOCK_MAPPINGS, (short) -1);
for (int i = 0; i < 4096; i++) { for (int i = 0; i < 4096; i++) {
int newBlock = MappingData.blockMappings.getNewId(i); int newBlock = MappingData.blockMappings.getNewId(i);
if (newBlock != -1) reverseBlockMappings.put((short) newBlock, (short) i); if (newBlock != -1) {
REVERSE_BLOCK_MAPPINGS[newBlock] = (short) i;
}
} }
} }
@ -38,15 +42,18 @@ public class BlockConnectionStorage extends StoredObject {
} }
public void store(int x, int y, int z, int blockState) { public void store(int x, int y, int z, int blockState) {
Short mapping = reverseBlockMappings.get((short) blockState); short mapping = REVERSE_BLOCK_MAPPINGS[blockState];
if (mapping == null) return; if (mapping == -1) return;
blockState = mapping; blockState = mapping;
long pair = getChunkSectionIndex(x, y, z); long pair = getChunkSectionIndex(x, y, z);
Pair<byte[], NibbleArray> map = getChunkSection(pair, (blockState & 0xF) != 0); Pair<byte[], NibbleArray> map = getChunkSection(pair, (blockState & 0xF) != 0);
int blockIndex = encodeBlockPos(x, y, z); int blockIndex = encodeBlockPos(x, y, z);
map.getKey()[blockIndex] = (byte) (blockState >> 4); map.getKey()[blockIndex] = (byte) (blockState >> 4);
NibbleArray nibbleArray = map.getValue(); NibbleArray nibbleArray = map.getValue();
if (nibbleArray != null) nibbleArray.set(blockIndex, blockState); if (nibbleArray != null) {
nibbleArray.set(blockIndex, blockState);
}
} }
public int get(int x, int y, int z) { public int get(int x, int y, int z) {

View File

@ -1,38 +1,41 @@
package us.myles.ViaVersion.protocols.protocol1_13to1_12_2.storage; package us.myles.ViaVersion.protocols.protocol1_13to1_12_2.storage;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet;
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.minecraft.Position; import us.myles.ViaVersion.api.minecraft.Position;
import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
public class BlockStorage extends StoredObject { public class BlockStorage extends StoredObject {
private static final Set<Integer> whitelist = new HashSet<>(); private static final IntSet WHITELIST = new IntOpenHashSet(46, 1F);
private final Map<Position, ReplacementData> blocks = new ConcurrentHashMap<>(); private final Map<Position, ReplacementData> blocks = new ConcurrentHashMap<>();
static { static {
// Flower pots // Flower pots
whitelist.add(5266); WHITELIST.add(5266);
// Add those red beds // Add those red beds
for (int i = 0; i < 16; i++) for (int i = 0; i < 16; i++) {
whitelist.add(972 + i); WHITELIST.add(972 + i);
}
// Add the white banners // Add the white banners
for (int i = 0; i < 20; i++) for (int i = 0; i < 20; i++) {
whitelist.add(6854 + i); WHITELIST.add(6854 + i);
}
// Add the white wall banners // Add the white wall banners
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
whitelist.add(7110 + i); WHITELIST.add(7110 + i);
} }
// Skeleton skulls // Skeleton skulls
for (int i = 0; i < 5; i++) for (int i = 0; i < 5; i++) {
whitelist.add(5447 + i); WHITELIST.add(5447 + i);
}
} }
public BlockStorage(UserConnection user) { public BlockStorage(UserConnection user) {
@ -44,14 +47,14 @@ public class BlockStorage extends StoredObject {
} }
public void store(Position position, int block, int replacementId) { public void store(Position position, int block, int replacementId) {
if (!whitelist.contains(block)) if (!WHITELIST.contains(block))
return; return;
blocks.put(position, new ReplacementData(block, replacementId)); blocks.put(position, new ReplacementData(block, replacementId));
} }
public boolean isWelcome(int block) { public boolean isWelcome(int block) {
return whitelist.contains(block); return WHITELIST.contains(block);
} }
public boolean contains(Position position) { public boolean contains(Position position) {

View File

@ -1,109 +0,0 @@
package us.myles.ViaVersion.protocols.protocol1_14to1_13_2.data;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
public class EntityTypeRewriter {
private static final Map<Integer, Integer> entityTypes = new HashMap<>();
static {
regEnt(6, 7); // cave_spider
regEnt(7, 8); // chicken
regEnt(8, 9); // cod
regEnt(9, 10); // cow
regEnt(10, 11); // creeper
regEnt(11, 12); // donkey
regEnt(12, 13); // dolphin
regEnt(13, 14); // dragon_fireball
regEnt(14, 15); // drowned
regEnt(15, 16); // elder_guardian
regEnt(16, 17); // end_crystal
regEnt(17, 18); // ender_dragon
regEnt(18, 19); // enderman
regEnt(19, 20); // endermite
regEnt(20, 21); // evoker_fangs
regEnt(21, 22); // evoker
regEnt(22, 23); // experience_orb
regEnt(23, 24); // eye_of_ender
regEnt(24, 25); // falling_block
regEnt(25, 26); // firework_rocket
regEnt(26, 28); // ghast
regEnt(27, 29); // giant
regEnt(28, 30); // guardian
regEnt(29, 31); // horse
regEnt(30, 32); // husk
regEnt(31, 33); // illusioner
regEnt(32, 34); // item
regEnt(33, 35); // item_frame
regEnt(34, 36); // fireball
regEnt(35, 37); // leash_knot
regEnt(36, 38); // llama
regEnt(37, 39); // llama_spit
regEnt(38, 40); // magma_cube
regEnt(39, 41); // minecart
regEnt(40, 42); // chest_minecart
regEnt(41, 43); // command_block_minecart
regEnt(42, 44); // furnace_minecart
regEnt(43, 45); // hopper_minecart
regEnt(44, 46); // spawner_minecart
regEnt(45, 47); // tnt_minecart
regEnt(46, 48); // mule
regEnt(47, 49); // mooshroom
regEnt(48, 6); // ocelot -> cat TODO Remap untamed ocelot to ocelot?
regEnt(49, 51); // painting
regEnt(50, 53); // parrot
regEnt(51, 54); // pig
regEnt(52, 55); // pufferfish
regEnt(53, 56); // zombie_pigman
regEnt(54, 57); // polar_bear
regEnt(55, 58); // tnt
regEnt(56, 59); // rabbit
regEnt(57, 60); // salmon
regEnt(58, 61); // sheep
regEnt(59, 62); // shulker
regEnt(60, 63); // shulker_bullet
regEnt(61, 64); // silverfish
regEnt(62, 65); // skeleton
regEnt(63, 66); // skeleton_horse
regEnt(64, 67); // slime
regEnt(65, 68); // small_fireball
regEnt(66, 69); // snowgolem
regEnt(67, 70); // snowball
regEnt(68, 71); // spectral_arrow
regEnt(69, 72); // spider
regEnt(70, 73); // squid
regEnt(71, 74); // stray
regEnt(72, 76); // tropical_fish
regEnt(73, 77); // turtle
regEnt(74, 78); // egg
regEnt(75, 79); // ender_pearl
regEnt(76, 80); // experience_bottle
regEnt(77, 81); // potion
regEnt(78, 83); // vex
regEnt(79, 84); // villager
regEnt(80, 85); // iron_golem
regEnt(81, 86); // vindicator
regEnt(82, 89); // witch
regEnt(83, 90); // wither
regEnt(84, 91); // wither_skeleton
regEnt(85, 92); // wither_skull
regEnt(86, 93); // wolf
regEnt(87, 94); // zombie
regEnt(88, 95); // zombie_horse
regEnt(89, 96); // zombie_villager
regEnt(90, 97); // phantom
regEnt(91, 99); // lightning_bolt
regEnt(92, 100); // player
regEnt(93, 101); // fishing_bobber
regEnt(94, 82); // trident
}
private static void regEnt(int type1_13, int type1_14) {
entityTypes.put(type1_13, type1_14);
}
public static Optional<Integer> getNewId(int type1_13) {
return Optional.ofNullable(entityTypes.get(type1_13));
}
}

View File

@ -1,32 +1,32 @@
package us.myles.ViaVersion.protocols.protocol1_14to1_13_2.data; package us.myles.ViaVersion.protocols.protocol1_14to1_13_2.data;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.google.gson.JsonArray; import com.google.gson.JsonArray;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet;
import us.myles.ViaVersion.api.Via; import us.myles.ViaVersion.api.Via;
import us.myles.ViaVersion.api.data.MappingDataLoader; import us.myles.ViaVersion.api.data.MappingDataLoader;
import us.myles.ViaVersion.api.data.Mappings; import us.myles.ViaVersion.api.data.Mappings;
import us.myles.ViaVersion.util.Int2IntBiMap;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set;
public class MappingData { public class MappingData {
public static final BiMap<Integer, Integer> oldToNewItems = HashBiMap.create(); public static final Int2IntBiMap oldToNewItems = new Int2IntBiMap();
public static Mappings blockStateMappings; public static Mappings blockStateMappings;
public static Mappings blockMappings; public static Mappings blockMappings;
public static Mappings soundMappings; public static Mappings soundMappings;
public static Set<Integer> motionBlocking; public static IntSet motionBlocking;
public static Set<Integer> nonFullBlocks; public static IntSet nonFullBlocks;
public static void init() { public static void init() {
Via.getPlatform().getLogger().info("Loading 1.13.2 -> 1.14 mappings..."); Via.getPlatform().getLogger().info("Loading 1.13.2 -> 1.14 mappings...");
JsonObject mapping1_13_2 = MappingDataLoader.loadData("mapping-1.13.2.json", true); JsonObject mapping1_13_2 = MappingDataLoader.loadData("mapping-1.13.2.json", true);
JsonObject mapping1_14 = MappingDataLoader.loadData("mapping-1.14.json", true); JsonObject mapping1_14 = MappingDataLoader.loadData("mapping-1.14.json", true);
oldToNewItems.defaultReturnValue(-1);
blockStateMappings = new Mappings(mapping1_13_2.getAsJsonObject("blockstates"), mapping1_14.getAsJsonObject("blockstates")); blockStateMappings = new Mappings(mapping1_13_2.getAsJsonObject("blockstates"), mapping1_14.getAsJsonObject("blockstates"));
blockMappings = new Mappings(mapping1_13_2.getAsJsonObject("blocks"), mapping1_14.getAsJsonObject("blocks")); blockMappings = new Mappings(mapping1_13_2.getAsJsonObject("blocks"), mapping1_14.getAsJsonObject("blocks"));
MappingDataLoader.mapIdentifiers(oldToNewItems, mapping1_13_2.getAsJsonObject("items"), mapping1_14.getAsJsonObject("items")); MappingDataLoader.mapIdentifiers(oldToNewItems, mapping1_13_2.getAsJsonObject("items"), mapping1_14.getAsJsonObject("items"));
@ -40,19 +40,19 @@ public class MappingData {
JsonObject heightMapData = MappingDataLoader.loadData("heightMapData-1.14.json"); JsonObject heightMapData = MappingDataLoader.loadData("heightMapData-1.14.json");
JsonArray motionBlocking = heightMapData.getAsJsonArray("MOTION_BLOCKING"); JsonArray motionBlocking = heightMapData.getAsJsonArray("MOTION_BLOCKING");
us.myles.ViaVersion.protocols.protocol1_14to1_13_2.data.MappingData.motionBlocking = new HashSet<>(motionBlocking.size()); MappingData.motionBlocking = new IntOpenHashSet(motionBlocking.size(), 1F);
for (JsonElement blockState : motionBlocking) { for (JsonElement blockState : motionBlocking) {
String key = blockState.getAsString(); String key = blockState.getAsString();
Integer id = blockStateMap.get(key); Integer id = blockStateMap.get(key);
if (id == null) { if (id == null) {
Via.getPlatform().getLogger().warning("Unknown blockstate " + key + " :("); Via.getPlatform().getLogger().warning("Unknown blockstate " + key + " :(");
} else { } else {
us.myles.ViaVersion.protocols.protocol1_14to1_13_2.data.MappingData.motionBlocking.add(id); MappingData.motionBlocking.add(id.intValue());
} }
} }
if (Via.getConfig().isNonFullBlockLightFix()) { if (Via.getConfig().isNonFullBlockLightFix()) {
nonFullBlocks = new HashSet<>(); nonFullBlocks = new IntOpenHashSet(1611, 1F);
for (Map.Entry<String, JsonElement> blockstates : mapping1_13_2.getAsJsonObject("blockstates").entrySet()) { for (Map.Entry<String, JsonElement> blockstates : mapping1_13_2.getAsJsonObject("blockstates").entrySet()) {
final String state = blockstates.getValue().getAsString(); final String state = blockstates.getValue().getAsString();
if (state.contains("_slab") || state.contains("_stairs") || state.contains("_wall[")) if (state.contains("_slab") || state.contains("_stairs") || state.contains("_wall["))

View File

@ -3,6 +3,7 @@ package us.myles.ViaVersion.protocols.protocol1_14to1_13_2.metadata;
import us.myles.ViaVersion.api.PacketWrapper; import us.myles.ViaVersion.api.PacketWrapper;
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.entities.Entity1_13Types;
import us.myles.ViaVersion.api.entities.Entity1_14Types; import us.myles.ViaVersion.api.entities.Entity1_14Types;
import us.myles.ViaVersion.api.entities.EntityType; import us.myles.ViaVersion.api.entities.EntityType;
import us.myles.ViaVersion.api.minecraft.VillagerData; import us.myles.ViaVersion.api.minecraft.VillagerData;
@ -13,7 +14,6 @@ import us.myles.ViaVersion.api.rewriters.MetadataRewriter;
import us.myles.ViaVersion.api.type.Type; import us.myles.ViaVersion.api.type.Type;
import us.myles.ViaVersion.api.type.types.Particle; import us.myles.ViaVersion.api.type.types.Particle;
import us.myles.ViaVersion.protocols.protocol1_14to1_13_2.Protocol1_14To1_13_2; import us.myles.ViaVersion.protocols.protocol1_14to1_13_2.Protocol1_14To1_13_2;
import us.myles.ViaVersion.protocols.protocol1_14to1_13_2.data.EntityTypeRewriter;
import us.myles.ViaVersion.protocols.protocol1_14to1_13_2.packets.InventoryPackets; import us.myles.ViaVersion.protocols.protocol1_14to1_13_2.packets.InventoryPackets;
import us.myles.ViaVersion.protocols.protocol1_14to1_13_2.storage.EntityTracker1_14; import us.myles.ViaVersion.protocols.protocol1_14to1_13_2.storage.EntityTracker1_14;
@ -23,6 +23,7 @@ public class MetadataRewriter1_14To1_13_2 extends MetadataRewriter {
public MetadataRewriter1_14To1_13_2(Protocol1_14To1_13_2 protocol) { public MetadataRewriter1_14To1_13_2(Protocol1_14To1_13_2 protocol) {
super(protocol, EntityTracker1_14.class); super(protocol, EntityTracker1_14.class);
mapTypes(Entity1_13Types.EntityType.values(), Entity1_14Types.EntityType.class);
} }
@Override @Override
@ -168,11 +169,6 @@ public class MetadataRewriter1_14To1_13_2 extends MetadataRewriter {
} }
} }
@Override
public int getNewEntityId(final int oldId) {
return EntityTypeRewriter.getNewId(oldId).orElse(oldId);
}
@Override @Override
protected EntityType getTypeFromId(int type) { protected EntityType getTypeFromId(int type) {
return Entity1_14Types.getTypeFromId(type); return Entity1_14Types.getTypeFromId(type);

View File

@ -14,7 +14,6 @@ import us.myles.ViaVersion.api.type.types.version.Types1_14;
import us.myles.ViaVersion.protocols.protocol1_13to1_12_2.ClientboundPackets1_13; import us.myles.ViaVersion.protocols.protocol1_13to1_12_2.ClientboundPackets1_13;
import us.myles.ViaVersion.protocols.protocol1_14to1_13_2.ClientboundPackets1_14; import us.myles.ViaVersion.protocols.protocol1_14to1_13_2.ClientboundPackets1_14;
import us.myles.ViaVersion.protocols.protocol1_14to1_13_2.Protocol1_14To1_13_2; import us.myles.ViaVersion.protocols.protocol1_14to1_13_2.Protocol1_14To1_13_2;
import us.myles.ViaVersion.protocols.protocol1_14to1_13_2.data.EntityTypeRewriter;
import us.myles.ViaVersion.protocols.protocol1_14to1_13_2.metadata.MetadataRewriter1_14To1_13_2; import us.myles.ViaVersion.protocols.protocol1_14to1_13_2.metadata.MetadataRewriter1_14To1_13_2;
import us.myles.ViaVersion.protocols.protocol1_14to1_13_2.storage.EntityTracker1_14; import us.myles.ViaVersion.protocols.protocol1_14to1_13_2.storage.EntityTracker1_14;
@ -50,7 +49,7 @@ public class EntityPackets {
int typeId = wrapper.get(Type.VAR_INT, 1); int typeId = wrapper.get(Type.VAR_INT, 1);
Entity1_13Types.EntityType type1_13 = Entity1_13Types.getTypeFromId(typeId, true); Entity1_13Types.EntityType type1_13 = Entity1_13Types.getTypeFromId(typeId, true);
typeId = EntityTypeRewriter.getNewId(type1_13.getId()).orElse(type1_13.getId()); typeId = metadataRewriter.getNewEntityId(type1_13.getId());
Entity1_14Types.EntityType type1_14 = Entity1_14Types.getTypeFromId(typeId); Entity1_14Types.EntityType type1_14 = Entity1_14Types.getTypeFromId(typeId);
if (type1_14 != null) { if (type1_14 != null) {

View File

@ -271,8 +271,8 @@ public class InventoryPackets {
} }
public static int getNewItemId(int id) { public static int getNewItemId(int id) {
Integer newId = MappingData.oldToNewItems.get(id); int newId = MappingData.oldToNewItems.get(id);
if (newId == null) { if (newId == -1) {
Via.getPlatform().getLogger().warning("Missing 1.14 item for 1.13.2 item " + id); Via.getPlatform().getLogger().warning("Missing 1.14 item for 1.13.2 item " + id);
return 1; return 1;
} }
@ -313,7 +313,7 @@ public class InventoryPackets {
} }
public static int getOldItemId(int id) { public static int getOldItemId(int id) {
Integer oldId = MappingData.oldToNewItems.inverse().get(id); int oldId = MappingData.oldToNewItems.inverse().get(id);
return oldId != null ? oldId : 1; return oldId != -1 ? oldId : 1;
} }
} }

View File

@ -1,14 +1,13 @@
package us.myles.ViaVersion.protocols.protocol1_15to1_14_4.data; package us.myles.ViaVersion.protocols.protocol1_15to1_14_4.data;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import us.myles.ViaVersion.api.Via; import us.myles.ViaVersion.api.Via;
import us.myles.ViaVersion.api.data.MappingDataLoader; import us.myles.ViaVersion.api.data.MappingDataLoader;
import us.myles.ViaVersion.api.data.Mappings; import us.myles.ViaVersion.api.data.Mappings;
import us.myles.ViaVersion.util.Int2IntBiMap;
public class MappingData { public class MappingData {
public static BiMap<Integer, Integer> oldToNewItems = HashBiMap.create(); public static Int2IntBiMap oldToNewItems = new Int2IntBiMap();
public static Mappings blockMappings; public static Mappings blockMappings;
public static Mappings blockStateMappings; public static Mappings blockStateMappings;
public static Mappings soundMappings; public static Mappings soundMappings;
@ -19,6 +18,7 @@ public class MappingData {
JsonObject mapping1_14 = MappingDataLoader.loadData("mapping-1.14.json", true); JsonObject mapping1_14 = MappingDataLoader.loadData("mapping-1.14.json", true);
JsonObject mapping1_15 = MappingDataLoader.loadData("mapping-1.15.json", true); JsonObject mapping1_15 = MappingDataLoader.loadData("mapping-1.15.json", true);
oldToNewItems.defaultReturnValue(-1);
blockStateMappings = new Mappings(mapping1_14.getAsJsonObject("blockstates"), mapping1_15.getAsJsonObject("blockstates"), diffmapping.getAsJsonObject("blockstates")); blockStateMappings = new Mappings(mapping1_14.getAsJsonObject("blockstates"), mapping1_15.getAsJsonObject("blockstates"), diffmapping.getAsJsonObject("blockstates"));
blockMappings = new Mappings(mapping1_14.getAsJsonObject("blocks"), mapping1_15.getAsJsonObject("blocks")); blockMappings = new Mappings(mapping1_14.getAsJsonObject("blocks"), mapping1_15.getAsJsonObject("blocks"));
MappingDataLoader.mapIdentifiers(oldToNewItems, mapping1_14.getAsJsonObject("items"), mapping1_15.getAsJsonObject("items")); MappingDataLoader.mapIdentifiers(oldToNewItems, mapping1_14.getAsJsonObject("items"), mapping1_15.getAsJsonObject("items"));

View File

@ -143,8 +143,8 @@ public class InventoryPackets {
} }
public static int getNewItemId(int id) { public static int getNewItemId(int id) {
Integer newId = MappingData.oldToNewItems.get(id); int newId = MappingData.oldToNewItems.get(id);
if (newId == null) { if (newId == -1) {
Via.getPlatform().getLogger().warning("Missing 1.15 item for 1.14 item " + id); Via.getPlatform().getLogger().warning("Missing 1.15 item for 1.14 item " + id);
return 1; return 1;
} }
@ -152,7 +152,7 @@ public class InventoryPackets {
} }
public static int getOldItemId(int id) { public static int getOldItemId(int id) {
Integer oldId = MappingData.oldToNewItems.inverse().get(id); int oldId = MappingData.oldToNewItems.inverse().get(id);
return oldId != null ? oldId : 1; return oldId != -1 ? oldId : 1;
} }
} }

View File

@ -1,17 +1,16 @@
package us.myles.ViaVersion.protocols.protocol1_16to1_15_2.data; package us.myles.ViaVersion.protocols.protocol1_16to1_15_2.data;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import us.myles.ViaVersion.api.Via; import us.myles.ViaVersion.api.Via;
import us.myles.ViaVersion.api.data.MappingDataLoader; import us.myles.ViaVersion.api.data.MappingDataLoader;
import us.myles.ViaVersion.api.data.Mappings; import us.myles.ViaVersion.api.data.Mappings;
import us.myles.ViaVersion.util.Int2IntBiMap;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
public class MappingData { public class MappingData {
public static BiMap<Integer, Integer> oldToNewItems = HashBiMap.create(); public static Int2IntBiMap oldToNewItems = new Int2IntBiMap();
public static Map<String, String> attributeMappings = new HashMap<>(); public static Map<String, String> attributeMappings = new HashMap<>();
public static Mappings blockMappings; public static Mappings blockMappings;
public static Mappings blockStateMappings; public static Mappings blockStateMappings;
@ -23,6 +22,7 @@ public class MappingData {
JsonObject mapping1_15 = MappingDataLoader.loadData("mapping-1.15.json", true); JsonObject mapping1_15 = MappingDataLoader.loadData("mapping-1.15.json", true);
JsonObject mapping1_16 = MappingDataLoader.loadData("mapping-1.16.json", true); JsonObject mapping1_16 = MappingDataLoader.loadData("mapping-1.16.json", true);
oldToNewItems.defaultReturnValue(-1);
blockStateMappings = new Mappings(mapping1_15.getAsJsonObject("blockstates"), mapping1_16.getAsJsonObject("blockstates"), diffmapping.getAsJsonObject("blockstates")); blockStateMappings = new Mappings(mapping1_15.getAsJsonObject("blockstates"), mapping1_16.getAsJsonObject("blockstates"), diffmapping.getAsJsonObject("blockstates"));
blockMappings = new Mappings(mapping1_15.getAsJsonObject("blocks"), mapping1_16.getAsJsonObject("blocks")); blockMappings = new Mappings(mapping1_15.getAsJsonObject("blocks"), mapping1_16.getAsJsonObject("blocks"));
MappingDataLoader.mapIdentifiers(oldToNewItems, mapping1_15.getAsJsonObject("items"), mapping1_16.getAsJsonObject("items"), diffmapping.getAsJsonObject("items")); MappingDataLoader.mapIdentifiers(oldToNewItems, mapping1_15.getAsJsonObject("items"), mapping1_16.getAsJsonObject("items"), diffmapping.getAsJsonObject("items"));

View File

@ -206,8 +206,8 @@ public class InventoryPackets {
} }
public static int getNewItemId(int id) { public static int getNewItemId(int id) {
Integer newId = MappingData.oldToNewItems.get(id); int newId = MappingData.oldToNewItems.get(id);
if (newId == null) { if (newId == -1) {
Via.getPlatform().getLogger().warning("Missing 1.16 item for 1.15.2 item " + id); Via.getPlatform().getLogger().warning("Missing 1.16 item for 1.15.2 item " + id);
return 1; return 1;
} }
@ -215,7 +215,7 @@ public class InventoryPackets {
} }
public static int getOldItemId(int id) { public static int getOldItemId(int id) {
Integer oldId = MappingData.oldToNewItems.inverse().get(id); int oldId = MappingData.oldToNewItems.inverse().get(id);
return oldId != null ? oldId : 1; return oldId != -1 ? oldId : 1;
} }
} }

View File

@ -4,6 +4,8 @@ import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.github.steveice10.opennbt.tag.builtin.ListTag; import com.github.steveice10.opennbt.tag.builtin.ListTag;
import com.github.steveice10.opennbt.tag.builtin.StringTag; import com.github.steveice10.opennbt.tag.builtin.StringTag;
import com.github.steveice10.opennbt.tag.builtin.Tag; import com.github.steveice10.opennbt.tag.builtin.Tag;
import it.unimi.dsi.fastutil.ints.Int2IntMap;
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
import us.myles.ViaVersion.api.minecraft.item.Item; import us.myles.ViaVersion.api.minecraft.item.Item;
import java.util.Collections; import java.util.Collections;
@ -17,7 +19,7 @@ public class ItemRewriter {
private static final Map<String, Integer> POTION_NAME_TO_ID = new HashMap<>(); private static final Map<String, Integer> POTION_NAME_TO_ID = new HashMap<>();
private static final Map<Integer, String> POTION_ID_TO_NAME = new HashMap<>(); private static final Map<Integer, String> POTION_ID_TO_NAME = new HashMap<>();
private static final Map<Integer, Integer> POTION_INDEX = new HashMap<>(); private static final Int2IntMap POTION_INDEX = new Int2IntOpenHashMap(36, 1F);
static { static {
/* Entities */ /* Entities */
@ -218,7 +220,7 @@ public class ItemRewriter {
return str; return str;
} }
// hacky but it works :) // hacky but it works :)
str = "\u00A7r" + str; str = "§r" + str;
return str; return str;
} }
@ -381,21 +383,21 @@ public class ItemRewriter {
oldID -= 8192; oldID -= 8192;
} }
Integer index = POTION_INDEX.get(oldID); int index = POTION_INDEX.get(oldID);
if (index != null) { if (index != -1) {
return index; return index;
} }
oldID = POTION_NAME_TO_ID.get(potionNameFromDamage((short) oldID)); oldID = POTION_NAME_TO_ID.get(potionNameFromDamage((short) oldID));
return (index = POTION_INDEX.get(oldID)) != null ? index : 0; return (index = POTION_INDEX.get(oldID)) != -1 ? index : 0;
} }
private static void registerEntity(Integer id, String name) { private static void registerEntity(int id, String name) {
ENTTIY_ID_TO_NAME.put(id, name); ENTTIY_ID_TO_NAME.put(id, name);
ENTTIY_NAME_TO_ID.put(name, id); ENTTIY_NAME_TO_ID.put(name, id);
} }
private static void registerPotion(Integer id, String name) { private static void registerPotion(int id, String name) {
POTION_INDEX.put(id, POTION_ID_TO_NAME.size()); POTION_INDEX.put(id, POTION_ID_TO_NAME.size());
POTION_ID_TO_NAME.put(id, name); POTION_ID_TO_NAME.put(id, name);
POTION_NAME_TO_ID.put(name, id); POTION_NAME_TO_ID.put(name, id);

View File

@ -211,4 +211,3 @@ public enum MetaIndex {
} }
} }

View File

@ -1,14 +1,13 @@
package us.myles.ViaVersion.protocols.protocol1_9to1_8.sounds; package us.myles.ViaVersion.protocols.protocol1_9to1_8.sounds;
import java.util.HashMap; import it.unimi.dsi.fastutil.ints.Int2IntMap;
import java.util.Map; import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
public class Effect { public class Effect {
private static final Map<Integer, Integer> effects; private static final Int2IntMap EFFECTS = new Int2IntOpenHashMap(17, 1F);
static { static {
effects = new HashMap<>();
addRewrite(1005, 1010); //Play music disc addRewrite(1005, 1010); //Play music disc
addRewrite(1003, 1005); //Iron door open addRewrite(1003, 1005); //Iron door open
addRewrite(1006, 1011); //Iron door close addRewrite(1006, 1011); //Iron door close
@ -26,19 +25,17 @@ public class Effect {
addRewrite(1020, 1029); //Anvil break addRewrite(1020, 1029); //Anvil break
addRewrite(1021, 1030); //Anvil use addRewrite(1021, 1030); //Anvil use
addRewrite(1022, 1031); //Anvil land addRewrite(1022, 1031); //Anvil land
} }
public static int getNewId(int id) { public static int getNewId(int id) {
Integer newId = effects.get(id); return EFFECTS.getOrDefault(id, id);
return newId != null ? newId : id;
} }
public static boolean contains(int oldId) { public static boolean contains(int oldId) {
return effects.containsKey(oldId); return EFFECTS.containsKey(oldId);
} }
private static void addRewrite(int oldId, int newId) { private static void addRewrite(int oldId, int newId) {
effects.put(oldId, newId); EFFECTS.put(oldId, newId);
} }
} }

View File

@ -0,0 +1,128 @@
package us.myles.ViaVersion.util;
import com.google.common.base.Preconditions;
import it.unimi.dsi.fastutil.ints.Int2IntMap;
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
import it.unimi.dsi.fastutil.ints.IntSet;
import it.unimi.dsi.fastutil.objects.ObjectSet;
import org.jetbrains.annotations.NotNull;
import java.util.Map;
/**
* Simple wrapper class for two {@link Int2IntMap}s.
*
* @see #inverse() to get the inversed map
*/
public class Int2IntBiMap implements Int2IntMap {
private final Int2IntMap map;
private final Int2IntBiMap inverse;
public Int2IntBiMap() {
this.map = new Int2IntOpenHashMap();
this.inverse = new Int2IntBiMap(this);
}
private Int2IntBiMap(Int2IntBiMap inverse) {
this.map = new Int2IntOpenHashMap();
this.inverse = inverse;
}
/**
* @return the inverse of this bimap
*/
public Int2IntBiMap inverse() {
return inverse;
}
/**
* Puts the key and value into the maps.
*
* @param key key
* @param value value
* @return old value if present
* @throws IllegalArgumentException if the value already exists in the map
*/
@Override
public int put(int key, int value) {
if (containsKey(key) && value == get(key)) return value;
Preconditions.checkArgument(!containsValue(value), "value already present: %s", value);
map.put(key, value);
inverse.map.put(value, key);
return defaultReturnValue();
}
@Override
public boolean remove(int key, int value) {
map.remove(key, value);
return inverse.map.remove(key, value);
}
@Override
public int get(int key) {
return map.get(key);
}
@Override
public void clear() {
map.clear();
inverse.map.clear();
}
@Override
public int size() {
return map.size();
}
@Override
public boolean isEmpty() {
return map.isEmpty();
}
@Override
@Deprecated
public void putAll(@NotNull Map<? extends Integer, ? extends Integer> m) {
throw new UnsupportedOperationException();
}
@Override
public void defaultReturnValue(int rv) {
map.defaultReturnValue(rv);
inverse.map.defaultReturnValue(rv);
}
@Override
public int defaultReturnValue() {
return map.defaultReturnValue();
}
@Override
public ObjectSet<Entry> int2IntEntrySet() {
return map.int2IntEntrySet();
}
@Override
@NotNull
public IntSet keySet() {
return map.keySet();
}
@Override
@NotNull
public IntSet values() {
return inverse.map.keySet();
}
@Override
public boolean containsKey(int key) {
return map.containsKey(key);
}
@Override
public boolean containsValue(int value) {
return inverse.map.containsKey(value);
}
}

View File

@ -73,7 +73,44 @@
<configuration> <configuration>
<createDependencyReducedPom>false</createDependencyReducedPom> <createDependencyReducedPom>false</createDependencyReducedPom>
<minimizeJar>false</minimizeJar> <minimizeJar>false</minimizeJar>
<filters>
<filter>
<artifact>it.unimi.dsi:fastutil</artifact>
<includes>
<!-- We only want int and Object maps -->
<include>it/unimi/dsi/fastutil/ints/*</include>
<include>it/unimi/dsi/fastutil/objects/*</include>
<include>it/unimi/dsi/fastutil/*.class</include>
</includes>
<excludes>
<!-- Object types -->
<exclude>it/unimi/dsi/fastutil/*/*Reference*</exclude>
<exclude>it/unimi/dsi/fastutil/*/*Boolean*</exclude>
<exclude>it/unimi/dsi/fastutil/*/*Byte*</exclude>
<exclude>it/unimi/dsi/fastutil/*/*Short*</exclude>
<exclude>it/unimi/dsi/fastutil/*/*Float*</exclude>
<exclude>it/unimi/dsi/fastutil/*/*Double*</exclude>
<exclude>it/unimi/dsi/fastutil/*/*Long*</exclude>
<exclude>it/unimi/dsi/fastutil/*/*Char*</exclude>
<!-- Map types -->
<exclude>it/unimi/dsi/fastutil/*/*Custom*</exclude>
<exclude>it/unimi/dsi/fastutil/*/*Linked*</exclude>
<exclude>it/unimi/dsi/fastutil/*/*Sorted*</exclude>
<exclude>it/unimi/dsi/fastutil/*/*Tree*</exclude>
<exclude>it/unimi/dsi/fastutil/*/*Heap*</exclude>
<exclude>it/unimi/dsi/fastutil/*/*Queue*</exclude>
<!-- Crossing fingers -->
<exclude>it/unimi/dsi/fastutil/*/*Big*</exclude>
<exclude>it/unimi/dsi/fastutil/*/*Synchronized*</exclude>
<exclude>it/unimi/dsi/fastutil/*/*Unmodifiable*</exclude>
</excludes>
</filter>
</filters>
<relocations> <relocations>
<relocation>
<pattern>it.unimi.dsi.fastutil</pattern>
<shadedPattern>us.myles.viaversion.libs.fastutil</shadedPattern>
</relocation>
<relocation> <relocation>
<pattern>com.github.steveice10.opennbt</pattern> <pattern>com.github.steveice10.opennbt</pattern>
<shadedPattern>us.myles.viaversion.libs.opennbt</shadedPattern> <shadedPattern>us.myles.viaversion.libs.opennbt</shadedPattern>