ViaBackwards development - ViaVersion/ViaBackwards GitHub Wiki
Creating a protocol for a new major version
Here's a template to be copied when creating new protocol transformers for the very latest (!) Minecraft version. Only differences when compared to ViaVersion are commented.
Main protocol class
In the main protocol class, the transformation direction is of course the other way around, so
public final class Protocol1_19To1_19_1 extends BackwardsProtocol<ClientboundPackets1_19, ClientboundPackets1_19_1, ServerboundPackets1_19, ServerboundPackets1_19_1> {
from ViaVersion would become the following in ViaBackwards:
public final class Protocol1_19_1To1_19 extends BackwardsProtocol<ClientboundPackets1_19_1, ClientboundPackets1_19, ServerboundPackets1_19_1, ServerboundPackets1_19> {
First, copy the template from the ViaVersion wiki, then apply the required changed below.
// ...
// ViaBackwards uses its own mappings and also needs a translatablerewriter for translation mappings
public static final BackwardsMappings MAPPINGS = new BackwardsMappings("1.x", "1.y", Protocol1_xTo1_y.class); // Uses the ViaVersion protocol class as a parameter!
private final TranslatableRewriter<ClientboundPacketsOld> translatableRewriter = new TranslatableRewriter<>(this);
@Override
protected void registerPackets() {
super.registerPackets();
// Registers translatable mappings
translatableRewriter.registerComponentPacket(ClientboundPacketsOld.ACTIONBAR);
translatableRewriter.registerComponentPacket(ClientboundPacketsOld.TITLE_TEXT);
translatableRewriter.registerComponentPacket(ClientboundPacketsOld.TITLE_SUBTITLE);
translatableRewriter.registerBossBar(ClientboundPacketsOld.BOSSBAR);
translatableRewriter.registerDisconnect(ClientboundPacketsOld.DISCONNECT);
translatableRewriter.registerTabList(ClientboundPacketsOld.TAB_LIST);
translatableRewriter.registerOpenWindow(ClientboundPacketsOld.OPEN_WINDOW);
translatableRewriter.registerCombatKill(ClientboundPacketsOld.COMBAT_KILL);
translatableRewriter.registerComponentPacket(ClientboundPacketsOld.SYSTEM_CHAT);
translatableRewriter.registerComponentPacket(ClientboundPacketsOld.DISGUISED_CHAT);
translatableRewriter.registerPing();
// And more, like chat messages
// ...
// The sound rewriter also needs to register stop sound and named sound packets for the manual id mappings
final SoundRewriter<ClientboundPacketsOld> soundRewriter = new SoundRewriter<>(this);
soundRewriter.registerStopSound(ClientboundPacketsOld.STOP_SOUND);
soundRewriter.register1_19_3Sound(ClientboundPacketsOld.SOUND);
soundRewriter.registerSound(ClientboundPacketsOld.ENTITY_SOUND);
}
@Override
public TranslatableRewriter getTranslatableRewriter() {
return translatableRewriter;
}
Entity data
@Override
public void registerRewrites() {
/*filter().handler((event, meta) -> {
int id = meta.metaType().typeId();
if (id >= ac) {
return;
} else if (id >= ab) {
id--;
}
meta.setMetaType(Types1_z.META_TYPES.byId(id));
});*/
registerMetaTypeHandler(Types1_z.META_TYPES.itemType, Types1_z.META_TYPES.blockStateType, Types1_z.META_TYPES.particleType, Types1_z.META_TYPES.optionalComponentType, Types1_z.META_TYPES.componentType);
filter().filterFamily(Types1_z.MINECART_ABSTRACT).index(11).handler((event, meta) -> {
final int blockState = meta.value();
meta.setValue(protocol.getMappingData().getNewBlockStateId(blockState));
});
// Remove metadata of new entity type
// filter().type(Entity1_xTypes.SNIFFER).removeIndex(newIndex);
}
@Override
public void onMappingDataLoaded() {
mapTypes();
// mapEntityTypeWithData(Entity1_xTypes.SNIFFER, Entity1_xTypes.RAVAGER).jsonName();
}
Mapping new to old entity types has to be done in code, same for their metadata and particle data. Most other registry type mappings (blocks, sounds, items, simple particles, enchantments, ...) are done via the json mappings.
Diff mappings
Wildcard blockstate mappings
Instead of manually mapping every single property iteration of a blockstate, use:
"minecraft:mangrove_wood": "minecraft:acacia_wood[",
The [
at the end signalized that properties are copied across the mappings.