You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
81 lines
3.3 KiB
Java
81 lines
3.3 KiB
Java
package com.razz.dfashion.cosmetic;
|
|
|
|
import com.mojang.serialization.Codec;
|
|
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
|
import com.razz.dfashion.cosmetic.share.SharedCosmeticCache;
|
|
|
|
import io.netty.buffer.ByteBuf;
|
|
import io.netty.handler.codec.DecoderException;
|
|
import net.minecraft.network.codec.ByteBufCodecs;
|
|
import net.minecraft.network.codec.StreamCodec;
|
|
import net.minecraft.resources.Identifier;
|
|
|
|
/**
|
|
* One of two ways an equipped cosmetic slot can reference its content:
|
|
* <ul>
|
|
* <li>{@link Local} — a built-in cosmetic addressed by {@link Identifier}.
|
|
* Resolved against {@code CosmeticCache.cosmetics}.</li>
|
|
* <li>{@link Shared} — a server-side blob addressed by its 64-char content hash.
|
|
* Resolved against {@code ClientSharedCosmeticCache}.</li>
|
|
* </ul>
|
|
*
|
|
* <p>Wire codec tags the variant with a single byte (0 = local, 1 = shared) and caps each
|
|
* inner string length. Invalid shared hashes are rejected via
|
|
* {@link SharedCosmeticCache#isValidHash} on decode.
|
|
*/
|
|
public sealed interface CosmeticRef permits CosmeticRef.Local, CosmeticRef.Shared {
|
|
|
|
record Local(Identifier id) implements CosmeticRef {}
|
|
record Shared(String hash) implements CosmeticRef {}
|
|
|
|
byte TAG_LOCAL = 0;
|
|
byte TAG_SHARED = 1;
|
|
|
|
Codec<CosmeticRef> CODEC = RecordCodecBuilder.create(inst -> inst.group(
|
|
Codec.BOOL.fieldOf("shared").forGetter(r -> r instanceof Shared),
|
|
Codec.STRING.fieldOf("value").forGetter(r -> switch (r) {
|
|
case Local l -> l.id().toString();
|
|
case Shared s -> s.hash();
|
|
})
|
|
).apply(inst, (shared, value) -> shared
|
|
? new Shared(value)
|
|
: new Local(Identifier.parse(value))));
|
|
|
|
StreamCodec<ByteBuf, CosmeticRef> STREAM_CODEC = new StreamCodec<>() {
|
|
private final StreamCodec<ByteBuf, String> LOCAL_STR = ByteBufCodecs.stringUtf8(256);
|
|
private final StreamCodec<ByteBuf, String> SHARED_STR = ByteBufCodecs.stringUtf8(64);
|
|
|
|
@Override public void encode(ByteBuf buf, CosmeticRef ref) {
|
|
switch (ref) {
|
|
case Local l -> {
|
|
buf.writeByte(TAG_LOCAL);
|
|
LOCAL_STR.encode(buf, l.id().toString());
|
|
}
|
|
case Shared s -> {
|
|
buf.writeByte(TAG_SHARED);
|
|
SHARED_STR.encode(buf, s.hash());
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override public CosmeticRef decode(ByteBuf buf) {
|
|
byte tag = buf.readByte();
|
|
return switch (tag) {
|
|
case TAG_LOCAL -> {
|
|
String s = LOCAL_STR.decode(buf);
|
|
Identifier id = Identifier.tryParse(s);
|
|
if (id == null) throw new DecoderException("bad Identifier in CosmeticRef.Local: " + s);
|
|
yield new Local(id);
|
|
}
|
|
case TAG_SHARED -> {
|
|
String hash = SHARED_STR.decode(buf);
|
|
if (!SharedCosmeticCache.isValidHash(hash)) {
|
|
throw new DecoderException("invalid hash in CosmeticRef.Shared");
|
|
}
|
|
yield new Shared(hash);
|
|
}
|
|
default -> throw new DecoderException("bad CosmeticRef tag " + tag);
|
|
};
|
|
}
|
|
};
|
|
} |