93 lines
3.2 KiB
Java
93 lines
3.2 KiB
Java
package net.minecraft.network.codec;
|
|
|
|
import io.netty.buffer.ByteBuf;
|
|
import io.netty.handler.codec.DecoderException;
|
|
import io.netty.handler.codec.EncoderException;
|
|
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
|
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
import java.util.function.Function;
|
|
import net.minecraft.network.VarInt;
|
|
|
|
public class IdDispatchCodec<B extends ByteBuf, V, T> implements StreamCodec<B, V> {
|
|
private static final int UNKNOWN_TYPE = -1;
|
|
private final Function<V, ? extends T> typeGetter;
|
|
private final List<IdDispatchCodec.Entry<B, V, T>> byId;
|
|
private final Object2IntMap<T> toId;
|
|
|
|
IdDispatchCodec(Function<V, ? extends T> typeGetter, List<IdDispatchCodec.Entry<B, V, T>> byId, Object2IntMap<T> toId) {
|
|
this.typeGetter = typeGetter;
|
|
this.byId = byId;
|
|
this.toId = toId;
|
|
}
|
|
|
|
public V decode(B byteBuf) {
|
|
int i = VarInt.read(byteBuf);
|
|
if (i >= 0 && i < this.byId.size()) {
|
|
IdDispatchCodec.Entry<B, V, T> entry = (IdDispatchCodec.Entry<B, V, T>)this.byId.get(i);
|
|
|
|
try {
|
|
return (V)entry.serializer.decode(byteBuf);
|
|
} catch (Exception var5) {
|
|
throw new DecoderException("Failed to decode packet '" + entry.type + "'", var5);
|
|
}
|
|
} else {
|
|
throw new DecoderException("Received unknown packet id " + i);
|
|
}
|
|
}
|
|
|
|
public void encode(B byteBuf, V object) {
|
|
T object2 = (T)this.typeGetter.apply(object);
|
|
int i = this.toId.getOrDefault(object2, -1);
|
|
if (i == -1) {
|
|
throw new EncoderException("Sending unknown packet '" + object2 + "'");
|
|
} else {
|
|
VarInt.write(byteBuf, i);
|
|
IdDispatchCodec.Entry<B, V, T> entry = (IdDispatchCodec.Entry<B, V, T>)this.byId.get(i);
|
|
|
|
try {
|
|
StreamCodec<? super B, V> streamCodec = (StreamCodec<? super B, V>)entry.serializer;
|
|
streamCodec.encode(byteBuf, object);
|
|
} catch (Exception var7) {
|
|
throw new EncoderException("Failed to encode packet '" + object2 + "'", var7);
|
|
}
|
|
}
|
|
}
|
|
|
|
public static <B extends ByteBuf, V, T> IdDispatchCodec.Builder<B, V, T> builder(Function<V, ? extends T> typeGetter) {
|
|
return new IdDispatchCodec.Builder<>(typeGetter);
|
|
}
|
|
|
|
public static class Builder<B extends ByteBuf, V, T> {
|
|
private final List<IdDispatchCodec.Entry<B, V, T>> entries = new ArrayList();
|
|
private final Function<V, ? extends T> typeGetter;
|
|
|
|
Builder(Function<V, ? extends T> typeGetter) {
|
|
this.typeGetter = typeGetter;
|
|
}
|
|
|
|
public IdDispatchCodec.Builder<B, V, T> add(T type, StreamCodec<? super B, ? extends V> serializer) {
|
|
this.entries.add(new IdDispatchCodec.Entry<>(serializer, type));
|
|
return this;
|
|
}
|
|
|
|
public IdDispatchCodec<B, V, T> build() {
|
|
Object2IntOpenHashMap<T> object2IntOpenHashMap = new Object2IntOpenHashMap<>();
|
|
object2IntOpenHashMap.defaultReturnValue(-2);
|
|
|
|
for (IdDispatchCodec.Entry<B, V, T> entry : this.entries) {
|
|
int i = object2IntOpenHashMap.size();
|
|
int j = object2IntOpenHashMap.putIfAbsent(entry.type, i);
|
|
if (j != -2) {
|
|
throw new IllegalStateException("Duplicate registration for type " + entry.type);
|
|
}
|
|
}
|
|
|
|
return new IdDispatchCodec<>(this.typeGetter, List.copyOf(this.entries), object2IntOpenHashMap);
|
|
}
|
|
}
|
|
|
|
record Entry<B, V, T>(StreamCodec<? super B, ? extends V> serializer, T type) {
|
|
}
|
|
}
|