Add methods to write IForgeRegistryEntry to ByteBuf (#3806)

This commit is contained in:
diesieben07 2017-05-18 22:47:13 +02:00 committed by LexManos
parent d77033b0d0
commit acdfe97bd6
4 changed files with 122 additions and 3 deletions

View file

@ -20,9 +20,19 @@
package net.minecraftforge.fml.common.network;
import java.io.IOException;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fml.common.registry.FMLControlledNamespacedRegistry;
import net.minecraftforge.fml.common.registry.GameRegistry;
import net.minecraftforge.fml.common.registry.IForgeRegistry;
import net.minecraftforge.fml.common.registry.IForgeRegistryEntry;
import net.minecraftforge.fml.common.registry.PersistentRegistryManager;
import org.apache.commons.lang3.Validate;
import com.google.common.base.Charsets;
@ -31,6 +41,9 @@ import com.google.common.base.Throwables;
import io.netty.buffer.ByteBuf;
import javax.annotation.Nullable;
import javax.annotation.Nonnull;
import com.google.common.collect.ImmutableList;
/**
* Utilities for interacting with {@link ByteBuf}.
@ -219,6 +232,109 @@ public class ByteBufUtils {
}
}
/**
* Write a registry entry to the stream. The serialized format is not specified and must not be relied upon.
* Do not use this to write to a file, it is used for client-server communication only.
* @param out the buffer to write to
* @param entry the registry entry
*/
public static <T extends IForgeRegistryEntry<T>> void writeRegistryEntry(@Nonnull ByteBuf out, @Nonnull T entry)
{
FMLControlledNamespacedRegistry<T> registry = (FMLControlledNamespacedRegistry<T>)GameRegistry.findRegistry(entry.getRegistryType());
writeUTF8String(out, PersistentRegistryManager.getRegistryRegistryName(registry).toString());
writeVarInt(out, registry.getId(entry), 5);
}
/**
* Read a registry entry from the stream. The same format as in {@link #writeRegistryEntry(ByteBuf, IForgeRegistryEntry)} is used.
* @param in the buffer to read from
* @param registry the registry the entry belongs to
* @return the read registry entry
*/
@Nonnull
public static <T extends IForgeRegistryEntry<T>> T readRegistryEntry(@Nonnull ByteBuf in, @Nonnull IForgeRegistry<T> registry)
{
String registryName = readUTF8String(in);
int id = readVarInt(in, 5);
ResourceLocation expectedRegistryName = PersistentRegistryManager.getRegistryRegistryName(registry);
if (!expectedRegistryName.toString().equals(registryName))
{
throw new IllegalArgumentException("Registry mismatch: " + registryName + " != " + expectedRegistryName);
}
T thing = ((FMLControlledNamespacedRegistry<T>)registry).getRaw(id);
if (thing == null)
{
throw new IllegalArgumentException("Unknown ID " + id + " for registry " + expectedRegistryName + " received.");
}
return thing;
}
/**
* Write multiple registry entries from the same registry to the stream. The serialized format may be more compact than using
* {@link #writeRegistryEntry(ByteBuf, IForgeRegistryEntry)} multiple times.
* @param out the buffer to write to
* @param entries the entries to write
*/
public static <T extends IForgeRegistryEntry<T>> void writeRegistryEntries(@Nonnull ByteBuf out, @Nonnull Collection<T> entries)
{
writeVarInt(out, entries.size(), 5);
Iterator<T> it = entries.iterator();
if (it.hasNext())
{
T first = it.next();
FMLControlledNamespacedRegistry<T> registry = (FMLControlledNamespacedRegistry<T>)GameRegistry.findRegistry(first.getRegistryType());
writeUTF8String(out, PersistentRegistryManager.getRegistryRegistryName(registry).toString());
writeVarInt(out, registry.getId(first), 5);
while (it.hasNext()) {
int id = registry.getId(it.next());
if (id == -1) {
throw new IllegalArgumentException("Unregistered IForgeRegistryEntry in collection " + entries + ".");
}
writeVarInt(out, id, 5);
}
}
}
/**
* Read multiple registry entries from the same registries from the stream. The list of entries must have been written by
* {@link #writeRegistryEntries(ByteBuf, Collection)}.
* @param in the buffer to read from
* @param registry the registry the entries belong to
* @return the immutable list of entries
*/
@Nonnull
public static <T extends IForgeRegistryEntry<T>> List<T> readRegistryEntries(@Nonnull ByteBuf in, @Nonnull IForgeRegistry<T> registry)
{
int size = readVarInt(in, 5);
if (size == 0)
{
return ImmutableList.of();
}
else
{
String registryName = readUTF8String(in);
ResourceLocation expectedRegistryName = PersistentRegistryManager.getRegistryRegistryName(registry);
if (!expectedRegistryName.toString().equals(registryName))
{
throw new IllegalArgumentException("Registry mismatch: " + registryName + " != " + expectedRegistryName);
}
ImmutableList.Builder<T> b = ImmutableList.builder();
for (int i = 0; i < size; i++)
{
int id = readVarInt(in, 5);
T thing = ((FMLControlledNamespacedRegistry<T>)registry).getRaw(id);
if (thing == null)
{
throw new IllegalArgumentException("Unknown ID " + id + " for registry " + expectedRegistryName + " received.");
}
b.add(thing);
}
return b.build();
}
}
public static String getContentDump(ByteBuf buffer)
{
int currentLength = buffer.readableBytes();

View file

@ -59,7 +59,7 @@ public interface IForgeRegistryEntry<V>
@Nullable
ResourceLocation getRegistryName();
Class<? super V> getRegistryType();
Class<V> getRegistryType();
// Default implementation, modders who make extra items SHOULD extend this instead of Object.
// We have to do this until we get default implementations in Java 8.
@ -100,6 +100,6 @@ public interface IForgeRegistryEntry<V>
}
@Override
public final Class<? super T> getRegistryType() { return token.getRawType(); };
public final Class<T> getRegistryType() { return (Class<T>) token.getRawType(); };
}
}

View file

@ -236,6 +236,9 @@ public class PersistentRegistryManager
return PersistentRegistry.ACTIVE.getRegistry(registryType);
}
public static ResourceLocation getRegistryRegistryName(IForgeRegistry<?> registry) {
return PersistentRegistry.ACTIVE.registries.inverse().get(registry);
}
public static List<String> injectSnapshot(GameDataSnapshot snapshot, boolean injectFrozenData, boolean isLocalWorld)
{

View file

@ -93,7 +93,7 @@ class CustomRegistryEntry implements ICustomRegistryEntry
}
@Override
public Class<? super ICustomRegistryEntry> getRegistryType()
public Class<ICustomRegistryEntry> getRegistryType()
{
return ICustomRegistryEntry.class;
}