Here you go, proper 1.19.1->1.19 and 1.19->1.18.2 support

Co-authored-by: Tisawesomeness <tis_dev@protonmail.com>
This commit is contained in:
Nassim Jahnke 2022-08-04 16:16:55 +02:00
parent 3d4f4438a8
commit d559c7cff1
No known key found for this signature in database
GPG Key ID: 6BE3B555EBC5982B
21 changed files with 673 additions and 265 deletions

View File

@ -45,8 +45,9 @@ import com.viaversion.viabackwards.protocol.protocol1_16_4to1_17.Protocol1_16_4T
import com.viaversion.viabackwards.protocol.protocol1_16to1_16_1.Protocol1_16To1_16_1;
import com.viaversion.viabackwards.protocol.protocol1_17_1to1_18.Protocol1_17_1To1_18;
import com.viaversion.viabackwards.protocol.protocol1_17to1_17_1.Protocol1_17To1_17_1;
import com.viaversion.viabackwards.protocol.protocol1_18_2to1_19_1.Protocol1_18_2To1_19_1;
import com.viaversion.viabackwards.protocol.protocol1_18_2to1_19.Protocol1_18_2To1_19;
import com.viaversion.viabackwards.protocol.protocol1_18to1_18_2.Protocol1_18To1_18_2;
import com.viaversion.viabackwards.protocol.protocol1_19to1_19_1.Protocol1_19To1_19_1;
import com.viaversion.viabackwards.protocol.protocol1_9_4to1_10.Protocol1_9_4To1_10;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.protocol.ProtocolManager;
@ -58,7 +59,7 @@ import java.util.logging.Logger;
public interface ViaBackwardsPlatform {
String MINIMUM_VV_VERSION = "4.4.1";
String MINIMUM_VV_VERSION = "4.4.2";
String IMPL_VERSION = "$IMPL_VERSION";
/**
@ -81,7 +82,6 @@ public interface ViaBackwardsPlatform {
TranslatableRewriter.loadTranslatables();
final ProtocolManager protocolManager = Via.getManager().getProtocolManager();
protocolManager.setMaxPathDeltaIncrease(1); // Since we skip 1.19
protocolManager.registerProtocol(new Protocol1_9_4To1_10(), ProtocolVersion.v1_9_3, ProtocolVersion.v1_10);
protocolManager.registerProtocol(new Protocol1_10To1_11(), ProtocolVersion.v1_10, ProtocolVersion.v1_11);
@ -117,8 +117,8 @@ public interface ViaBackwardsPlatform {
protocolManager.registerProtocol(new Protocol1_17_1To1_18(), ProtocolVersion.v1_17_1, ProtocolVersion.v1_18);
protocolManager.registerProtocol(new Protocol1_18To1_18_2(), ProtocolVersion.v1_18, ProtocolVersion.v1_18_2);
// 1.19.0 clients cannot join 1.19.1+ servers due to changes in the public profile key. 1.19.0 servers can use ViaBackwards 4.3.1
protocolManager.registerProtocol(new Protocol1_18_2To1_19_1(), ProtocolVersion.v1_18_2, ProtocolVersion.v1_19_1);
protocolManager.registerProtocol(new Protocol1_18_2To1_19(), ProtocolVersion.v1_18_2, ProtocolVersion.v1_19);
protocolManager.registerProtocol(new Protocol1_19To1_19_1(), ProtocolVersion.v1_19, ProtocolVersion.v1_19_1);
}
/**
@ -143,10 +143,6 @@ public interface ViaBackwardsPlatform {
}
default boolean isOutdatedPostLoad() {
if (!Via.getPlatform().isProxy() && Via.getAPI().getServerVersion().highestSupportedVersion() == ProtocolVersion.v1_19.getVersion()) {
// Print a warning but still allow it
getLogger().warning("This version of ViaBackwards does not fully support 1.19 servers. Please downgrade to ViaBackwards 4.3.1 for better support of that version.");
}
return false;
}

View File

@ -18,6 +18,7 @@
package com.viaversion.viabackwards.api.rewriters;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viaversion.api.data.entity.EntityTracker;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.metadata.MetaType;
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
@ -90,6 +91,18 @@ public abstract class EntityRewriter<T extends BackwardsProtocol> extends Entity
});
}
public PacketHandler worldTrackerHandlerByKey() {
return wrapper -> {
EntityTracker tracker = tracker(wrapper.user());
String world = wrapper.get(Type.STRING, 1);
if (tracker.currentWorld() != null && !tracker.currentWorld().equals(world)) {
tracker.clearEntities();
tracker.trackClientEntity();
}
tracker.setCurrentWorld(world);
};
}
/**
* Sets the mapped entity id and returns the unmapped entity type.
*

View File

@ -80,15 +80,6 @@ public class TranslatableRewriter extends ComponentRewriter {
});
}
public void registerChatMessage(ClientboundPacketType packetType) {
protocol.registerClientbound(packetType, new PacketRemapper() {
@Override
public void registerMap() {
handler(wrapper -> processText(wrapper.passthrough(Type.COMPONENT)));
}
});
}
public void registerLegacyOpenWindow(ClientboundPacketType packetType) {
protocol.registerClientbound(packetType, new PacketRemapper() {
@Override

View File

@ -73,7 +73,7 @@ public class Protocol1_12_2To1_13 extends BackwardsProtocol<ClientboundPackets1_
};
translatableRewriter.registerPing();
translatableRewriter.registerBossBar(ClientboundPackets1_13.BOSSBAR);
translatableRewriter.registerChatMessage(ClientboundPackets1_13.CHAT_MESSAGE);
translatableRewriter.registerComponentPacket(ClientboundPackets1_13.CHAT_MESSAGE);
translatableRewriter.registerLegacyOpenWindow(ClientboundPackets1_13.OPEN_WINDOW);
translatableRewriter.registerDisconnect(ClientboundPackets1_13.DISCONNECT);
translatableRewriter.registerCombatEvent(ClientboundPackets1_13.COMBAT_EVENT);

View File

@ -59,7 +59,7 @@ public class Protocol1_13_2To1_14 extends BackwardsProtocol<ClientboundPackets1_
executeAsyncAfterLoaded(Protocol1_14To1_13_2.class, MAPPINGS::load);
translatableRewriter.registerBossBar(ClientboundPackets1_14.BOSSBAR);
translatableRewriter.registerChatMessage(ClientboundPackets1_14.CHAT_MESSAGE);
translatableRewriter.registerComponentPacket(ClientboundPackets1_14.CHAT_MESSAGE);
translatableRewriter.registerCombatEvent(ClientboundPackets1_14.COMBAT_EVENT);
translatableRewriter.registerDisconnect(ClientboundPackets1_14.DISCONNECT);
translatableRewriter.registerTabList(ClientboundPackets1_14.TAB_LIST);

View File

@ -66,7 +66,7 @@ public class Protocol1_13To1_13_1 extends BackwardsProtocol<ClientboundPackets1_
WorldPackets1_13_1.register(this);
TranslatableRewriter translatableRewriter = new TranslatableRewriter(this);
translatableRewriter.registerChatMessage(ClientboundPackets1_13.CHAT_MESSAGE);
translatableRewriter.registerComponentPacket(ClientboundPackets1_13.CHAT_MESSAGE);
translatableRewriter.registerCombatEvent(ClientboundPackets1_13.COMBAT_EVENT);
translatableRewriter.registerDisconnect(ClientboundPackets1_13.DISCONNECT);
translatableRewriter.registerTabList(ClientboundPackets1_13.TAB_LIST);

View File

@ -55,7 +55,7 @@ public class Protocol1_14_4To1_15 extends BackwardsProtocol<ClientboundPackets1_
executeAsyncAfterLoaded(Protocol1_15To1_14_4.class, MAPPINGS::load);
translatableRewriter.registerBossBar(ClientboundPackets1_15.BOSSBAR);
translatableRewriter.registerChatMessage(ClientboundPackets1_15.CHAT_MESSAGE);
translatableRewriter.registerComponentPacket(ClientboundPackets1_15.CHAT_MESSAGE);
translatableRewriter.registerCombatEvent(ClientboundPackets1_15.COMBAT_EVENT);
translatableRewriter.registerDisconnect(ClientboundPackets1_15.DISCONNECT);
translatableRewriter.registerOpenWindow(ClientboundPackets1_15.OPEN_WINDOW);

View File

@ -68,7 +68,7 @@ public final class Protocol1_16_4To1_17 extends BackwardsProtocol<ClientboundPac
protected void registerPackets() {
executeAsyncAfterLoaded(Protocol1_17To1_16_4.class, MAPPINGS::load);
translatableRewriter.registerChatMessage(ClientboundPackets1_17.CHAT_MESSAGE);
translatableRewriter.registerComponentPacket(ClientboundPackets1_17.CHAT_MESSAGE);
translatableRewriter.registerBossBar(ClientboundPackets1_17.BOSSBAR);
translatableRewriter.registerDisconnect(ClientboundPackets1_17.DISCONNECT);
translatableRewriter.registerTabList(ClientboundPackets1_17.TAB_LIST);

View File

@ -0,0 +1,315 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2022 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viabackwards.protocol.protocol1_18_2to1_19;
import com.viaversion.viabackwards.ViaBackwards;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viabackwards.api.rewriters.SoundRewriter;
import com.viaversion.viabackwards.api.rewriters.TranslatableRewriter;
import com.viaversion.viabackwards.protocol.protocol1_18_2to1_19.data.BackwardsMappings;
import com.viaversion.viabackwards.protocol.protocol1_18_2to1_19.data.CommandRewriter1_19;
import com.viaversion.viabackwards.protocol.protocol1_18_2to1_19.packets.BlockItemPackets1_19;
import com.viaversion.viabackwards.protocol.protocol1_18_2to1_19.packets.EntityPackets1_19;
import com.viaversion.viabackwards.protocol.protocol1_18_2to1_19.storage.DimensionRegistryStorage;
import com.viaversion.viabackwards.protocol.protocol1_19to1_19_1.Protocol1_19To1_19_1;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.RegistryType;
import com.viaversion.viaversion.api.minecraft.entities.Entity1_19Types;
import com.viaversion.viaversion.api.protocol.packet.State;
import com.viaversion.viaversion.api.protocol.remapper.PacketRemapper;
import com.viaversion.viaversion.api.rewriter.EntityRewriter;
import com.viaversion.viaversion.api.rewriter.ItemRewriter;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.data.entity.EntityTrackerBase;
import com.viaversion.viaversion.libs.gson.JsonElement;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag;
import com.viaversion.viaversion.protocols.base.ClientboundLoginPackets;
import com.viaversion.viaversion.protocols.base.ServerboundLoginPackets;
import com.viaversion.viaversion.protocols.protocol1_17to1_16_4.ServerboundPackets1_17;
import com.viaversion.viaversion.protocols.protocol1_18to1_17_1.ClientboundPackets1_18;
import com.viaversion.viaversion.protocols.protocol1_19_1to1_19.ChatDecorationResult;
import com.viaversion.viaversion.protocols.protocol1_19_1to1_19.Protocol1_19_1To1_19;
import com.viaversion.viaversion.protocols.protocol1_19to1_18_2.ClientboundPackets1_19;
import com.viaversion.viaversion.protocols.protocol1_19to1_18_2.Protocol1_19To1_18_2;
import com.viaversion.viaversion.protocols.protocol1_19to1_18_2.ServerboundPackets1_19;
import com.viaversion.viaversion.rewriter.CommandRewriter;
import com.viaversion.viaversion.rewriter.StatisticsRewriter;
import com.viaversion.viaversion.rewriter.TagRewriter;
import java.time.Instant;
import java.util.UUID;
public final class Protocol1_18_2To1_19 extends BackwardsProtocol<ClientboundPackets1_19, ClientboundPackets1_18, ServerboundPackets1_19, ServerboundPackets1_17> {
public static final BackwardsMappings MAPPINGS = new BackwardsMappings();
private static final UUID ZERO_UUID = new UUID(0, 0);
private static final byte[] EMPTY_BYTES = new byte[0];
private final EntityPackets1_19 entityRewriter = new EntityPackets1_19(this);
private final BlockItemPackets1_19 blockItemPackets = new BlockItemPackets1_19(this);
private final TranslatableRewriter translatableRewriter = new TranslatableRewriter(this);
public Protocol1_18_2To1_19() {
super(ClientboundPackets1_19.class, ClientboundPackets1_18.class, ServerboundPackets1_19.class, ServerboundPackets1_17.class);
}
@Override
protected void registerPackets() {
executeAsyncAfterLoaded(Protocol1_19To1_18_2.class, () -> {
MAPPINGS.load();
entityRewriter.onMappingDataLoaded();
});
translatableRewriter.registerComponentPacket(ClientboundPackets1_19.ACTIONBAR);
translatableRewriter.registerComponentPacket(ClientboundPackets1_19.TITLE_TEXT);
translatableRewriter.registerComponentPacket(ClientboundPackets1_19.TITLE_SUBTITLE);
translatableRewriter.registerBossBar(ClientboundPackets1_19.BOSSBAR);
translatableRewriter.registerDisconnect(ClientboundPackets1_19.DISCONNECT);
translatableRewriter.registerTabList(ClientboundPackets1_19.TAB_LIST);
translatableRewriter.registerOpenWindow(ClientboundPackets1_19.OPEN_WINDOW);
translatableRewriter.registerCombatKill(ClientboundPackets1_19.COMBAT_KILL);
translatableRewriter.registerPing();
blockItemPackets.register();
entityRewriter.register();
final SoundRewriter soundRewriter = new SoundRewriter(this);
soundRewriter.registerStopSound(ClientboundPackets1_19.STOP_SOUND);
registerClientbound(ClientboundPackets1_19.SOUND, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT); // Sound id
map(Type.VAR_INT); // Source
map(Type.INT); // X
map(Type.INT); // Y
map(Type.INT); // Z
map(Type.FLOAT); // Volume
map(Type.FLOAT); // Pitch
read(Type.LONG); // Seed
handler(soundRewriter.getSoundHandler());
}
});
registerClientbound(ClientboundPackets1_19.ENTITY_SOUND, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT); // Sound id
map(Type.VAR_INT); // Source
map(Type.VAR_INT); // Entity id
map(Type.FLOAT); // Volume
map(Type.FLOAT); // Pitch
read(Type.LONG); // Seed
handler(soundRewriter.getSoundHandler());
}
});
registerClientbound(ClientboundPackets1_19.NAMED_SOUND, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.STRING); // Sound name
map(Type.VAR_INT); // Source
map(Type.INT); // X
map(Type.INT); // Y
map(Type.INT); // Z
map(Type.FLOAT); // Volume
map(Type.FLOAT); // Pitch
read(Type.LONG); // Seed
handler(soundRewriter.getNamedSoundHandler());
}
});
final TagRewriter tagRewriter = new TagRewriter(this);
tagRewriter.removeTags("minecraft:banner_pattern");
tagRewriter.removeTags("minecraft:instrument");
tagRewriter.removeTags("minecraft:cat_variant");
tagRewriter.removeTags("minecraft:painting_variant");
tagRewriter.addEmptyTag(RegistryType.BLOCK, "minecraft:polar_bears_spawnable_on_in_frozen_ocean");
tagRewriter.renameTag(RegistryType.BLOCK, "minecraft:wool_carpets", "minecraft:carpets");
tagRewriter.renameTag(RegistryType.ITEM, "minecraft:wool_carpets", "minecraft:carpets");
tagRewriter.addEmptyTag(RegistryType.ITEM, "minecraft:occludes_vibration_signals");
tagRewriter.registerGeneric(ClientboundPackets1_19.TAGS);
new StatisticsRewriter(this).register(ClientboundPackets1_19.STATISTICS);
final CommandRewriter commandRewriter = new CommandRewriter1_19(this);
registerClientbound(ClientboundPackets1_19.DECLARE_COMMANDS, new PacketRemapper() {
@Override
public void registerMap() {
handler(wrapper -> {
final int size = wrapper.passthrough(Type.VAR_INT);
for (int i = 0; i < size; i++) {
final byte flags = wrapper.passthrough(Type.BYTE);
wrapper.passthrough(Type.VAR_INT_ARRAY_PRIMITIVE); // Children indices
if ((flags & 0x08) != 0) {
wrapper.passthrough(Type.VAR_INT); // Redirect node index
}
final int nodeType = flags & 0x03;
if (nodeType == 1 || nodeType == 2) { // Literal/argument node
wrapper.passthrough(Type.STRING); // Name
}
if (nodeType == 2) { // Argument node
final int argumentTypeId = wrapper.read(Type.VAR_INT);
String argumentType = MAPPINGS.argumentType(argumentTypeId);
if (argumentType == null) {
ViaBackwards.getPlatform().getLogger().warning("Unknown command argument type id: " + argumentTypeId);
argumentType = "minecraft:no";
}
wrapper.write(Type.STRING, commandRewriter.handleArgumentType(argumentType));
commandRewriter.handleArgument(wrapper, argumentType);
if ((flags & 0x10) != 0) {
wrapper.passthrough(Type.STRING); // Suggestion type
}
}
}
wrapper.passthrough(Type.VAR_INT); // Root node index
});
}
});
cancelClientbound(ClientboundPackets1_19.SERVER_DATA);
cancelClientbound(ClientboundPackets1_19.CHAT_PREVIEW);
cancelClientbound(ClientboundPackets1_19.SET_DISPLAY_CHAT_PREVIEW);
registerClientbound(ClientboundPackets1_19.PLAYER_CHAT, ClientboundPackets1_18.CHAT_MESSAGE, new PacketRemapper() {
@Override
public void registerMap() {
handler(wrapper -> {
final JsonElement signedContent = wrapper.read(Type.COMPONENT);
final JsonElement unsignedContent = wrapper.read(Type.OPTIONAL_COMPONENT);
final int chatTypeId = wrapper.read(Type.VAR_INT);
final UUID sender = wrapper.read(Type.UUID);
final JsonElement senderName = wrapper.read(Type.COMPONENT);
final JsonElement teamName = wrapper.read(Type.OPTIONAL_COMPONENT);
final CompoundTag chatType = wrapper.user().get(DimensionRegistryStorage.class).chatType(chatTypeId);
final ChatDecorationResult decorationResult = Protocol1_19_1To1_19.decorateChatMessage(chatType, chatTypeId, senderName, teamName, unsignedContent != null ? unsignedContent : signedContent);
if (decorationResult == null) {
wrapper.cancel();
return;
}
translatableRewriter.processText(decorationResult.content());
wrapper.write(Type.COMPONENT, decorationResult.content());
wrapper.write(Type.BYTE, decorationResult.overlay() ? (byte) 2 : 1);
wrapper.write(Type.UUID, sender);
});
read(Type.LONG); // Timestamp
read(Type.LONG); // Salt
read(Type.BYTE_ARRAY_PRIMITIVE); // Signature
}
});
registerClientbound(ClientboundPackets1_19.SYSTEM_CHAT, ClientboundPackets1_18.CHAT_MESSAGE, new PacketRemapper() {
@Override
public void registerMap() {
handler(wrapper -> {
final JsonElement content = wrapper.passthrough(Type.COMPONENT);
translatableRewriter.processText(content);
// Screw everything that isn't a system or game info type (which would only happen on funny 1.19.0 servers)
final int typeId = wrapper.read(Type.VAR_INT);
wrapper.write(Type.BYTE, typeId == Protocol1_19To1_19_1.GAME_INFO_ID ? (byte) 2 : (byte) 0);
});
create(Type.UUID, ZERO_UUID); // Sender
}
});
registerServerbound(ServerboundPackets1_17.CHAT_MESSAGE, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.STRING); // Message
create(Type.LONG, Instant.now().toEpochMilli()); // Timestamp
create(Type.LONG, 0L); // Salt
handler(wrapper -> {
final String message = wrapper.get(Type.STRING, 0);
if (!message.isEmpty() && message.charAt(0) == '/') {
wrapper.setPacketType(ServerboundPackets1_19.CHAT_COMMAND);
wrapper.set(Type.STRING, 0, message.substring(1));
wrapper.write(Type.VAR_INT, 0); // No signatures
} else {
wrapper.write(Type.BYTE_ARRAY_PRIMITIVE, EMPTY_BYTES); // Signature
}
wrapper.write(Type.BOOLEAN, false); // No signed preview
});
}
});
// Login changes
registerClientbound(State.LOGIN, ClientboundLoginPackets.GAME_PROFILE.getId(), ClientboundLoginPackets.GAME_PROFILE.getId(), new PacketRemapper() {
@Override
public void registerMap() {
map(Type.UUID); // UUID
map(Type.STRING); // Name
handler(wrapper -> {
final int properties = wrapper.read(Type.VAR_INT);
for (int i = 0; i < properties; i++) {
wrapper.read(Type.STRING); // Name
wrapper.read(Type.STRING); // Value
if (wrapper.read(Type.BOOLEAN)) {
wrapper.read(Type.STRING); // Signature
}
}
});
}
});
registerServerbound(State.LOGIN, ServerboundLoginPackets.HELLO.getId(), ServerboundLoginPackets.HELLO.getId(), new PacketRemapper() {
@Override
public void registerMap() {
map(Type.STRING); // Name
// Write empty profile key - requires the enforce-secure-profiles option to be disabled on the server
create(Type.OPTIONAL_PROFILE_KEY, null);
}
});
registerServerbound(State.LOGIN, ServerboundLoginPackets.ENCRYPTION_KEY.getId(), ServerboundLoginPackets.ENCRYPTION_KEY.getId(), new PacketRemapper() {
@Override
public void registerMap() {
map(Type.BYTE_ARRAY_PRIMITIVE); // Keys
create(Type.BOOLEAN, true); // Is nonce
}
});
}
@Override
public void init(final UserConnection user) {
user.put(new DimensionRegistryStorage());
addEntityTracker(user, new EntityTrackerBase(user, Entity1_19Types.PLAYER, true));
}
@Override
public BackwardsMappings getMappingData() {
return MAPPINGS;
}
@Override
public TranslatableRewriter getTranslatableRewriter() {
return translatableRewriter;
}
@Override
public EntityRewriter getEntityRewriter() {
return entityRewriter;
}
@Override
public ItemRewriter getItemRewriter() {
return blockItemPackets;
}
}

View File

@ -15,7 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viabackwards.protocol.protocol1_18_2to1_19_1.data;
package com.viaversion.viabackwards.protocol.protocol1_18_2to1_19.data;
import com.viaversion.viabackwards.api.data.VBMappingDataLoader;
import com.viaversion.viaversion.api.minecraft.nbt.BinaryTagIO;
@ -53,13 +53,13 @@ public final class BackwardsMappings extends com.viaversion.viabackwards.api.dat
}
try {
ListTag chatTypes = BinaryTagIO.readCompressedInputStream(VBMappingDataLoader.getResource("chat-types-1.19.1.nbt")).get("values");
final ListTag chatTypes = BinaryTagIO.readCompressedInputStream(VBMappingDataLoader.getResource("chat-types-1.19.1.nbt")).get("values");
for (final Tag chatType : chatTypes) {
final CompoundTag chatTypeCompound = (CompoundTag) chatType;
final NumberTag idTag = chatTypeCompound.get("id");
defaultChatTypes.put(idTag.asInt(), chatTypeCompound);
}
} catch (IOException e) {
} catch (final IOException e) {
e.printStackTrace();
}
}

View File

@ -15,7 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viabackwards.protocol.protocol1_18_2to1_19_1.data;
package com.viaversion.viabackwards.protocol.protocol1_18_2to1_19.data;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.type.Type;

View File

@ -15,10 +15,10 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viabackwards.protocol.protocol1_18_2to1_19_1.packets;
package com.viaversion.viabackwards.protocol.protocol1_18_2to1_19.packets;
import com.viaversion.viabackwards.api.rewriters.ItemRewriter;
import com.viaversion.viabackwards.protocol.protocol1_18_2to1_19_1.Protocol1_18_2To1_19_1;
import com.viaversion.viabackwards.protocol.protocol1_18_2to1_19.Protocol1_18_2To1_19;
import com.viaversion.viaversion.api.data.ParticleMappings;
import com.viaversion.viaversion.api.data.entity.EntityTracker;
import com.viaversion.viaversion.api.minecraft.chunks.Chunk;
@ -32,13 +32,13 @@ import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.protocols.protocol1_16to1_15_2.data.RecipeRewriter1_16;
import com.viaversion.viaversion.protocols.protocol1_17to1_16_4.ServerboundPackets1_17;
import com.viaversion.viaversion.protocols.protocol1_18to1_17_1.types.Chunk1_18Type;
import com.viaversion.viaversion.protocols.protocol1_19_1to1_19.ClientboundPackets1_19_1;
import com.viaversion.viaversion.protocols.protocol1_19to1_18_2.ClientboundPackets1_19;
import com.viaversion.viaversion.rewriter.BlockRewriter;
import com.viaversion.viaversion.util.MathUtil;
public final class BlockItemPackets1_19 extends ItemRewriter<Protocol1_18_2To1_19_1> {
public final class BlockItemPackets1_19 extends ItemRewriter<Protocol1_18_2To1_19> {
public BlockItemPackets1_19(final Protocol1_18_2To1_19_1 protocol) {
public BlockItemPackets1_19(final Protocol1_18_2To1_19 protocol) {
super(protocol);
}
@ -46,23 +46,23 @@ public final class BlockItemPackets1_19 extends ItemRewriter<Protocol1_18_2To1_1
protected void registerPackets() {
final BlockRewriter blockRewriter = new BlockRewriter(protocol, Type.POSITION1_14);
new RecipeRewriter1_16(protocol).registerDefaultHandler(ClientboundPackets1_19_1.DECLARE_RECIPES);
new RecipeRewriter1_16(protocol).registerDefaultHandler(ClientboundPackets1_19.DECLARE_RECIPES);
registerSetCooldown(ClientboundPackets1_19_1.COOLDOWN);
registerWindowItems1_17_1(ClientboundPackets1_19_1.WINDOW_ITEMS, Type.FLAT_VAR_INT_ITEM_ARRAY_VAR_INT, Type.FLAT_VAR_INT_ITEM);
registerSetSlot1_17_1(ClientboundPackets1_19_1.SET_SLOT, Type.FLAT_VAR_INT_ITEM);
registerEntityEquipmentArray(ClientboundPackets1_19_1.ENTITY_EQUIPMENT, Type.FLAT_VAR_INT_ITEM);
registerAdvancements(ClientboundPackets1_19_1.ADVANCEMENTS, Type.FLAT_VAR_INT_ITEM);
registerSetCooldown(ClientboundPackets1_19.COOLDOWN);
registerWindowItems1_17_1(ClientboundPackets1_19.WINDOW_ITEMS, Type.FLAT_VAR_INT_ITEM_ARRAY_VAR_INT, Type.FLAT_VAR_INT_ITEM);
registerSetSlot1_17_1(ClientboundPackets1_19.SET_SLOT, Type.FLAT_VAR_INT_ITEM);
registerEntityEquipmentArray(ClientboundPackets1_19.ENTITY_EQUIPMENT, Type.FLAT_VAR_INT_ITEM);
registerAdvancements(ClientboundPackets1_19.ADVANCEMENTS, Type.FLAT_VAR_INT_ITEM);
registerClickWindow1_17_1(ServerboundPackets1_17.CLICK_WINDOW, Type.FLAT_VAR_INT_ITEM);
blockRewriter.registerBlockAction(ClientboundPackets1_19_1.BLOCK_ACTION);
blockRewriter.registerBlockChange(ClientboundPackets1_19_1.BLOCK_CHANGE);
blockRewriter.registerVarLongMultiBlockChange(ClientboundPackets1_19_1.MULTI_BLOCK_CHANGE);
blockRewriter.registerEffect(ClientboundPackets1_19_1.EFFECT, 1010, 2001);
blockRewriter.registerBlockAction(ClientboundPackets1_19.BLOCK_ACTION);
blockRewriter.registerBlockChange(ClientboundPackets1_19.BLOCK_CHANGE);
blockRewriter.registerVarLongMultiBlockChange(ClientboundPackets1_19.MULTI_BLOCK_CHANGE);
blockRewriter.registerEffect(ClientboundPackets1_19.EFFECT, 1010, 2001);
registerCreativeInvAction(ServerboundPackets1_17.CREATIVE_INVENTORY_ACTION, Type.FLAT_VAR_INT_ITEM);
protocol.registerClientbound(ClientboundPackets1_19_1.TRADE_LIST, new PacketRemapper() {
protocol.registerClientbound(ClientboundPackets1_19.TRADE_LIST, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT); // Container id
@ -94,9 +94,9 @@ public final class BlockItemPackets1_19 extends ItemRewriter<Protocol1_18_2To1_1
}
});
registerWindowPropertyEnchantmentHandler(ClientboundPackets1_19_1.WINDOW_PROPERTY);
registerWindowPropertyEnchantmentHandler(ClientboundPackets1_19.WINDOW_PROPERTY);
protocol.registerClientbound(ClientboundPackets1_19_1.BLOCK_CHANGED_ACK, null, new PacketRemapper() {
protocol.registerClientbound(ClientboundPackets1_19.BLOCK_CHANGED_ACK, null, new PacketRemapper() {
@Override
public void registerMap() {
read(Type.VAR_INT); // Sequence
@ -104,7 +104,7 @@ public final class BlockItemPackets1_19 extends ItemRewriter<Protocol1_18_2To1_1
}
});
protocol.registerClientbound(ClientboundPackets1_19_1.SPAWN_PARTICLE, new PacketRemapper() {
protocol.registerClientbound(ClientboundPackets1_19.SPAWN_PARTICLE, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT, Type.INT); // Particle id
@ -139,7 +139,7 @@ public final class BlockItemPackets1_19 extends ItemRewriter<Protocol1_18_2To1_1
});
protocol.registerClientbound(ClientboundPackets1_19_1.CHUNK_DATA, new PacketRemapper() {
protocol.registerClientbound(ClientboundPackets1_19.CHUNK_DATA, new PacketRemapper() {
@Override
public void registerMap() {
handler(wrapper -> {

View File

@ -15,12 +15,12 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viabackwards.protocol.protocol1_18_2to1_19_1.packets;
package com.viaversion.viabackwards.protocol.protocol1_18_2to1_19.packets;
import com.viaversion.viabackwards.api.rewriters.EntityRewriter;
import com.viaversion.viabackwards.protocol.protocol1_18_2to1_19_1.Protocol1_18_2To1_19_1;
import com.viaversion.viabackwards.protocol.protocol1_18_2to1_19_1.storage.DimensionRegistryStorage;
import com.viaversion.viabackwards.protocol.protocol1_18_2to1_19_1.storage.StoredPainting;
import com.viaversion.viabackwards.protocol.protocol1_18_2to1_19.Protocol1_18_2To1_19;
import com.viaversion.viabackwards.protocol.protocol1_18_2to1_19.storage.DimensionRegistryStorage;
import com.viaversion.viabackwards.protocol.protocol1_18_2to1_19.storage.StoredPainting;
import com.viaversion.viaversion.api.data.ParticleMappings;
import com.viaversion.viaversion.api.data.entity.StoredEntityData;
import com.viaversion.viaversion.api.minecraft.Position;
@ -39,22 +39,22 @@ import com.viaversion.viaversion.libs.opennbt.tag.builtin.NumberTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.StringTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.Tag;
import com.viaversion.viaversion.protocols.protocol1_18to1_17_1.ClientboundPackets1_18;
import com.viaversion.viaversion.protocols.protocol1_19_1to1_19.ClientboundPackets1_19_1;
import com.viaversion.viaversion.protocols.protocol1_19to1_18_2.ClientboundPackets1_19;
public final class EntityPackets1_19 extends EntityRewriter<Protocol1_18_2To1_19_1> {
public final class EntityPackets1_19 extends EntityRewriter<Protocol1_18_2To1_19> {
public EntityPackets1_19(final Protocol1_18_2To1_19_1 protocol) {
public EntityPackets1_19(final Protocol1_18_2To1_19 protocol) {
super(protocol);
}
@Override
protected void registerPackets() {
registerTracker(ClientboundPackets1_19_1.SPAWN_EXPERIENCE_ORB, Entity1_19Types.EXPERIENCE_ORB);
registerTracker(ClientboundPackets1_19_1.SPAWN_PLAYER, Entity1_19Types.PLAYER);
registerMetadataRewriter(ClientboundPackets1_19_1.ENTITY_METADATA, Types1_19.METADATA_LIST, Types1_18.METADATA_LIST);
registerRemoveEntities(ClientboundPackets1_19_1.REMOVE_ENTITIES);
registerTracker(ClientboundPackets1_19.SPAWN_EXPERIENCE_ORB, Entity1_19Types.EXPERIENCE_ORB);
registerTracker(ClientboundPackets1_19.SPAWN_PLAYER, Entity1_19Types.PLAYER);
registerMetadataRewriter(ClientboundPackets1_19.ENTITY_METADATA, Types1_19.METADATA_LIST, Types1_18.METADATA_LIST);
registerRemoveEntities(ClientboundPackets1_19.REMOVE_ENTITIES);
protocol.registerClientbound(ClientboundPackets1_19_1.SPAWN_ENTITY, new PacketRemapper() {
protocol.registerClientbound(ClientboundPackets1_19.SPAWN_ENTITY, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT); // Entity id
@ -98,7 +98,7 @@ public final class EntityPackets1_19 extends EntityRewriter<Protocol1_18_2To1_19
}
});
protocol.registerClientbound(ClientboundPackets1_19_1.ENTITY_EFFECT, new PacketRemapper() {
protocol.registerClientbound(ClientboundPackets1_19.ENTITY_EFFECT, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT); // Entity id
@ -115,7 +115,7 @@ public final class EntityPackets1_19 extends EntityRewriter<Protocol1_18_2To1_19
}
});
protocol.registerClientbound(ClientboundPackets1_19_1.JOIN_GAME, new PacketRemapper() {
protocol.registerClientbound(ClientboundPackets1_19.JOIN_GAME, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.INT); // Entity ID
@ -180,7 +180,7 @@ public final class EntityPackets1_19 extends EntityRewriter<Protocol1_18_2To1_19
}
});
protocol.registerClientbound(ClientboundPackets1_19_1.RESPAWN, new PacketRemapper() {
protocol.registerClientbound(ClientboundPackets1_19.RESPAWN, new PacketRemapper() {
@Override
public void registerMap() {
handler(wrapper -> {
@ -204,7 +204,7 @@ public final class EntityPackets1_19 extends EntityRewriter<Protocol1_18_2To1_19
}
});
protocol.registerClientbound(ClientboundPackets1_19_1.PLAYER_INFO, new PacketRemapper() {
protocol.registerClientbound(ClientboundPackets1_19.PLAYER_INFO, new PacketRemapper() {
@Override
public void registerMap() {
handler(wrapper -> {
@ -303,7 +303,7 @@ public final class EntityPackets1_19 extends EntityRewriter<Protocol1_18_2To1_19
packet.write(Type.BYTE, storedPainting.direction());
try {
// TODO Race condition
packet.send(Protocol1_18_2To1_19_1.class);
packet.send(Protocol1_18_2To1_19.class);
} catch (Exception e) {
throw new RuntimeException(e);
}
@ -323,8 +323,6 @@ public final class EntityPackets1_19 extends EntityRewriter<Protocol1_18_2To1_19
filter().type(Entity1_19Types.WARDEN).cancel(16); // Anger
mapEntityTypeWithData(Entity1_19Types.WARDEN, Entity1_19Types.IRON_GOLEM).jsonName();
filter().type(Entity1_19Types.ALLAY).cancel(16); // Dancing
filter().type(Entity1_19Types.ALLAY).cancel(17); // Can duplicate
mapEntityTypeWithData(Entity1_19Types.ALLAY, Entity1_19Types.VEX).jsonName();
filter().type(Entity1_19Types.GOAT).cancel(18);

View File

@ -15,9 +15,9 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viabackwards.protocol.protocol1_18_2to1_19_1.storage;
package com.viaversion.viabackwards.protocol.protocol1_18_2to1_19.storage;
import com.viaversion.viabackwards.protocol.protocol1_18_2to1_19_1.Protocol1_18_2To1_19_1;
import com.viaversion.viabackwards.protocol.protocol1_18_2to1_19.Protocol1_18_2To1_19;
import com.viaversion.viaversion.api.connection.StorableObject;
import com.viaversion.viaversion.libs.fastutil.ints.Int2ObjectMap;
import com.viaversion.viaversion.libs.fastutil.ints.Int2ObjectOpenHashMap;
@ -42,8 +42,7 @@ public final class DimensionRegistryStorage implements StorableObject {
}
public @Nullable CompoundTag chatType(final int id) {
if (chatTypes.isEmpty()) return Protocol1_18_2To1_19_1.MAPPINGS.chatType(id);
return chatTypes.get(id);
return chatTypes.isEmpty() ? Protocol1_18_2To1_19.MAPPINGS.chatType(id) : chatTypes.get(id);
}
public void addChatType(final int id, final CompoundTag chatType) {

View File

@ -15,7 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viabackwards.protocol.protocol1_18_2to1_19_1.storage;
package com.viaversion.viabackwards.protocol.protocol1_18_2to1_19.storage;
import com.viaversion.viaversion.api.connection.StorableObject;
import com.viaversion.viaversion.api.minecraft.Position;

View File

@ -15,28 +15,24 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viabackwards.protocol.protocol1_18_2to1_19_1;
package com.viaversion.viabackwards.protocol.protocol1_19to1_19_1;
import com.google.common.base.Preconditions;
import com.viaversion.viabackwards.ViaBackwards;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viabackwards.api.rewriters.SoundRewriter;
import com.viaversion.viabackwards.api.rewriters.TranslatableRewriter;
import com.viaversion.viabackwards.protocol.protocol1_18_2to1_19_1.data.BackwardsMappings;
import com.viaversion.viabackwards.protocol.protocol1_18_2to1_19_1.data.CommandRewriter1_19;
import com.viaversion.viabackwards.protocol.protocol1_18_2to1_19_1.packets.BlockItemPackets1_19;
import com.viaversion.viabackwards.protocol.protocol1_18_2to1_19_1.packets.EntityPackets1_19;
import com.viaversion.viabackwards.protocol.protocol1_18_2to1_19_1.storage.DimensionRegistryStorage;
import com.viaversion.viabackwards.protocol.protocol1_18_2to1_19_1.storage.ReceivedMessagesStorage;
import com.viaversion.viabackwards.protocol.protocol1_19to1_19_1.packets.EntityPackets1_19_1;
import com.viaversion.viabackwards.protocol.protocol1_19to1_19_1.storage.ChatRegistryStorage;
import com.viaversion.viabackwards.protocol.protocol1_19to1_19_1.storage.NonceStorage;
import com.viaversion.viabackwards.protocol.protocol1_19to1_19_1.storage.ReceivedMessagesStorage;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.PlayerMessageSignature;
import com.viaversion.viaversion.api.minecraft.RegistryType;
import com.viaversion.viaversion.api.minecraft.ProfileKey;
import com.viaversion.viaversion.api.minecraft.entities.Entity1_19Types;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.packet.State;
import com.viaversion.viaversion.api.protocol.remapper.PacketRemapper;
import com.viaversion.viaversion.api.rewriter.EntityRewriter;
import com.viaversion.viaversion.api.rewriter.ItemRewriter;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.data.entity.EntityTrackerBase;
import com.viaversion.viaversion.libs.gson.JsonElement;
@ -49,45 +45,38 @@ import com.viaversion.viaversion.libs.kyori.adventure.text.serializer.gson.GsonC
import com.viaversion.viaversion.libs.opennbt.tag.builtin.ByteTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.ListTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.NumberTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.StringTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.Tag;
import com.viaversion.viaversion.protocols.base.ClientboundLoginPackets;
import com.viaversion.viaversion.protocols.base.ServerboundLoginPackets;
import com.viaversion.viaversion.protocols.protocol1_17to1_16_4.ServerboundPackets1_17;
import com.viaversion.viaversion.protocols.protocol1_18to1_17_1.ClientboundPackets1_18;
import com.viaversion.viaversion.protocols.protocol1_19_1to1_19.ClientboundPackets1_19_1;
import com.viaversion.viaversion.protocols.protocol1_19_1to1_19.ServerboundPackets1_19_1;
import com.viaversion.viaversion.protocols.protocol1_19to1_18_2.Protocol1_19To1_18_2;
import com.viaversion.viaversion.rewriter.CommandRewriter;
import com.viaversion.viaversion.rewriter.StatisticsRewriter;
import com.viaversion.viaversion.rewriter.TagRewriter;
import com.viaversion.viaversion.protocols.protocol1_19to1_18_2.ClientboundPackets1_19;
import com.viaversion.viaversion.protocols.protocol1_19to1_18_2.ServerboundPackets1_19;
import com.viaversion.viaversion.protocols.protocol1_19to1_18_2.packets.EntityPackets;
import com.viaversion.viaversion.util.CipherUtil;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public final class Protocol1_18_2To1_19_1 extends BackwardsProtocol<ClientboundPackets1_19_1, ClientboundPackets1_18, ServerboundPackets1_19_1, ServerboundPackets1_17> {
public final class Protocol1_19To1_19_1 extends BackwardsProtocol<ClientboundPackets1_19_1, ClientboundPackets1_19, ServerboundPackets1_19_1, ServerboundPackets1_19> {
public static final BackwardsMappings MAPPINGS = new BackwardsMappings();
public static final int SYSTEM_CHAT_ID = 1;
public static final int GAME_INFO_ID = 2;
private static final UUID ZERO_UUID = new UUID(0, 0);
private static final byte[] EMPTY_BYTES = new byte[0];
private final EntityPackets1_19 entityRewriter = new EntityPackets1_19(this);
private final BlockItemPackets1_19 blockItemPackets = new BlockItemPackets1_19(this);
private final EntityPackets1_19_1 entityRewriter = new EntityPackets1_19_1(this);
private final TranslatableRewriter translatableRewriter = new TranslatableRewriter(this);
public Protocol1_18_2To1_19_1() {
super(ClientboundPackets1_19_1.class, ClientboundPackets1_18.class, ServerboundPackets1_19_1.class, ServerboundPackets1_17.class);
public Protocol1_19To1_19_1() {
super(ClientboundPackets1_19_1.class, ClientboundPackets1_19.class, ServerboundPackets1_19_1.class, ServerboundPackets1_19.class);
}
@Override
protected void registerPackets() {
executeAsyncAfterLoaded(Protocol1_19To1_18_2.class, () -> {
MAPPINGS.load();
entityRewriter.onMappingDataLoaded();
});
translatableRewriter.registerComponentPacket(ClientboundPackets1_19_1.ACTIONBAR);
translatableRewriter.registerComponentPacket(ClientboundPackets1_19_1.TITLE_TEXT);
translatableRewriter.registerComponentPacket(ClientboundPackets1_19_1.TITLE_SUBTITLE);
@ -98,109 +87,40 @@ public final class Protocol1_18_2To1_19_1 extends BackwardsProtocol<ClientboundP
translatableRewriter.registerCombatKill(ClientboundPackets1_19_1.COMBAT_KILL);
translatableRewriter.registerPing();
blockItemPackets.register();
entityRewriter.register();
final SoundRewriter soundRewriter = new SoundRewriter(this);
soundRewriter.registerStopSound(ClientboundPackets1_19_1.STOP_SOUND);
registerClientbound(ClientboundPackets1_19_1.SOUND, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT); // Sound id
map(Type.VAR_INT); // Source
map(Type.INT); // X
map(Type.INT); // Y
map(Type.INT); // Z
map(Type.FLOAT); // Volume
map(Type.FLOAT); // Pitch
read(Type.LONG); // Seed
handler(soundRewriter.getSoundHandler());
}
});
registerClientbound(ClientboundPackets1_19_1.ENTITY_SOUND, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT); // Sound id
map(Type.VAR_INT); // Source
map(Type.VAR_INT); // Entity id
map(Type.FLOAT); // Volume
map(Type.FLOAT); // Pitch
read(Type.LONG); // Seed
handler(soundRewriter.getSoundHandler());
}
});
registerClientbound(ClientboundPackets1_19_1.NAMED_SOUND, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.STRING); // Sound name
map(Type.VAR_INT); // Source
map(Type.INT); // X
map(Type.INT); // Y
map(Type.INT); // Z
map(Type.FLOAT); // Volume
map(Type.FLOAT); // Pitch
read(Type.LONG); // Seed
handler(soundRewriter.getNamedSoundHandler());
}
});
final TagRewriter tagRewriter = new TagRewriter(this);
tagRewriter.removeTags("minecraft:banner_pattern");
tagRewriter.removeTags("minecraft:instrument");
tagRewriter.removeTags("minecraft:cat_variant");
tagRewriter.removeTags("minecraft:painting_variant");
tagRewriter.addEmptyTag(RegistryType.BLOCK, "minecraft:polar_bears_spawnable_on_in_frozen_ocean");
tagRewriter.renameTag(RegistryType.BLOCK, "minecraft:wool_carpets", "minecraft:carpets");
tagRewriter.renameTag(RegistryType.ITEM, "minecraft:wool_carpets", "minecraft:carpets");
tagRewriter.addEmptyTag(RegistryType.ITEM, "minecraft:occludes_vibration_signals");
tagRewriter.registerGeneric(ClientboundPackets1_19_1.TAGS);
new StatisticsRewriter(this).register(ClientboundPackets1_19_1.STATISTICS);
final CommandRewriter commandRewriter = new CommandRewriter1_19(this);
registerClientbound(ClientboundPackets1_19_1.DECLARE_COMMANDS, new PacketRemapper() {
registerClientbound(ClientboundPackets1_19_1.JOIN_GAME, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.INT); // Entity ID
map(Type.BOOLEAN); // Hardcore
map(Type.UNSIGNED_BYTE); // Gamemode
map(Type.BYTE); // Previous Gamemode
map(Type.STRING_ARRAY); // World List
map(Type.NBT); // Dimension registry
map(Type.STRING); // Dimension key
map(Type.STRING); // World
handler(wrapper -> {
final int size = wrapper.passthrough(Type.VAR_INT);
for (int i = 0; i < size; i++) {
final byte flags = wrapper.passthrough(Type.BYTE);
wrapper.passthrough(Type.VAR_INT_ARRAY_PRIMITIVE); // Children indices
if ((flags & 0x08) != 0) {
wrapper.passthrough(Type.VAR_INT); // Redirect node index
}
final ChatRegistryStorage chatTypeStorage = wrapper.user().get(ChatRegistryStorage.class);
chatTypeStorage.clear();
final int nodeType = flags & 0x03;
if (nodeType == 1 || nodeType == 2) { // Literal/argument node
wrapper.passthrough(Type.STRING); // Name
}
if (nodeType == 2) { // Argument node
final int argumentTypeId = wrapper.read(Type.VAR_INT);
String argumentType = MAPPINGS.argumentType(argumentTypeId);
if (argumentType == null) {
ViaBackwards.getPlatform().getLogger().warning("Unknown command argument type id: " + argumentTypeId);
argumentType = "minecraft:no";
}
wrapper.write(Type.STRING, commandRewriter.handleArgumentType(argumentType));
commandRewriter.handleArgument(wrapper, argumentType);
if ((flags & 0x10) != 0) {
wrapper.passthrough(Type.STRING); // Suggestion type
}
}
final CompoundTag registry = wrapper.get(Type.NBT, 0);
final ListTag chatTypes = ((CompoundTag) registry.get("minecraft:chat_type")).get("value");
for (final Tag chatType : chatTypes) {
final CompoundTag chatTypeCompound = (CompoundTag) chatType;
final NumberTag idTag = chatTypeCompound.get("id");
chatTypeStorage.addChatType(idTag.asInt(), chatTypeCompound);
}
wrapper.passthrough(Type.VAR_INT); // Root node index
// Replace with 1.19 chat types
// Ensures that the client has a chat type for system message, with and without overlay
registry.put("minecraft:chat_type", EntityPackets.CHAT_REGISTRY.clone());
});
handler(entityRewriter.worldTrackerHandlerByKey());
}
});
cancelClientbound(ClientboundPackets1_19_1.SERVER_DATA);
cancelClientbound(ClientboundPackets1_19_1.CHAT_PREVIEW);
cancelClientbound(ClientboundPackets1_19_1.SET_DISPLAY_CHAT_PREVIEW);
registerClientbound(ClientboundPackets1_19_1.PLAYER_CHAT, ClientboundPackets1_18.CHAT_MESSAGE, new PacketRemapper() {
registerClientbound(ClientboundPackets1_19_1.PLAYER_CHAT, ClientboundPackets1_19.SYSTEM_CHAT, new PacketRemapper() {
@Override
public void registerMap() {
handler(wrapper -> {
@ -222,7 +142,7 @@ public final class Protocol1_18_2To1_19_1 extends BackwardsProtocol<ClientboundP
final PacketWrapper chatAckPacket = wrapper.create(ServerboundPackets1_19_1.CHAT_ACK);
chatAckPacket.write(Type.PLAYER_MESSAGE_SIGNATURE_ARRAY, messagesStorage.lastSignatures());
chatAckPacket.write(Type.OPTIONAL_PLAYER_MESSAGE_SIGNATURE, null);
chatAckPacket.sendToServer(Protocol1_18_2To1_19_1.class);
chatAckPacket.sendToServer(Protocol1_19To1_19_1.class);
}
}
@ -263,13 +183,12 @@ public final class Protocol1_18_2To1_19_1 extends BackwardsProtocol<ClientboundP
translatableRewriter.processText(decoratedMessage);
wrapper.write(Type.COMPONENT, decoratedMessage);
wrapper.write(Type.BYTE, (byte) 1);
wrapper.write(Type.UUID, signature.uuid());
wrapper.write(Type.VAR_INT, SYSTEM_CHAT_ID);
});
}
});
registerClientbound(ClientboundPackets1_19_1.SYSTEM_CHAT, ClientboundPackets1_18.CHAT_MESSAGE, new PacketRemapper() {
registerClientbound(ClientboundPackets1_19_1.SYSTEM_CHAT, new PacketRemapper() {
@Override
public void registerMap() {
handler(wrapper -> {
@ -277,28 +196,47 @@ public final class Protocol1_18_2To1_19_1 extends BackwardsProtocol<ClientboundP
translatableRewriter.processText(content);
final boolean overlay = wrapper.read(Type.BOOLEAN);
wrapper.write(Type.BYTE, overlay ? (byte) 2 : (byte) 0);
wrapper.write(Type.VAR_INT, overlay ? GAME_INFO_ID : SYSTEM_CHAT_ID);
});
create(Type.UUID, ZERO_UUID); // Sender
}
});
registerServerbound(ServerboundPackets1_17.CHAT_MESSAGE, new PacketRemapper() {
registerServerbound(ServerboundPackets1_19.CHAT_MESSAGE, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.STRING); // Message
create(Type.LONG, Instant.now().toEpochMilli()); // Timestamp
create(Type.LONG, 0L); // Salt
map(Type.LONG); // Timestamp
map(Type.LONG); // Salt
// Set empty signature
read(Type.BYTE_ARRAY_PRIMITIVE);
create(Type.BYTE_ARRAY_PRIMITIVE, EMPTY_BYTES);
map(Type.BOOLEAN); // Signed preview
handler(wrapper -> {
final String message = wrapper.get(Type.STRING, 0);
if (!message.isEmpty() && message.charAt(0) == '/') {
wrapper.setPacketType(ServerboundPackets1_19_1.CHAT_COMMAND);
wrapper.set(Type.STRING, 0, message.substring(1));
wrapper.write(Type.VAR_INT, 0); // No signatures
} else {
wrapper.write(Type.BYTE_ARRAY_PRIMITIVE, EMPTY_BYTES); // Signature
final ReceivedMessagesStorage messagesStorage = wrapper.user().get(ReceivedMessagesStorage.class);
messagesStorage.resetUnacknowledgedCount();
wrapper.write(Type.PLAYER_MESSAGE_SIGNATURE_ARRAY, messagesStorage.lastSignatures());
wrapper.write(Type.OPTIONAL_PLAYER_MESSAGE_SIGNATURE, null); // No last unacknowledged
});
}
});
registerServerbound(ServerboundPackets1_19.CHAT_COMMAND, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.STRING); // Command
map(Type.LONG); // Timestamp
map(Type.LONG); // Salt
handler(wrapper -> {
final int signatures = wrapper.passthrough(Type.VAR_INT);
for (int i = 0; i < signatures; i++) {
wrapper.passthrough(Type.STRING); // Argument name
// Set empty signature
wrapper.read(Type.BYTE_ARRAY_PRIMITIVE);
wrapper.write(Type.BYTE_ARRAY_PRIMITIVE, EMPTY_BYTES);
}
wrapper.write(Type.BOOLEAN, false); // No signed preview
wrapper.passthrough(Type.BOOLEAN); // Signed preview
final ReceivedMessagesStorage messagesStorage = wrapper.user().get(ReceivedMessagesStorage.class);
messagesStorage.resetUnacknowledgedCount();
@ -308,22 +246,13 @@ public final class Protocol1_18_2To1_19_1 extends BackwardsProtocol<ClientboundP
}
});
// Login changes
registerClientbound(State.LOGIN, ClientboundLoginPackets.GAME_PROFILE.getId(), ClientboundLoginPackets.GAME_PROFILE.getId(), new PacketRemapper() {
registerClientbound(ClientboundPackets1_19_1.SERVER_DATA, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.UUID); // UUID
map(Type.STRING); // Name
handler(wrapper -> {
final int properties = wrapper.read(Type.VAR_INT);
for (int i = 0; i < properties; i++) {
wrapper.read(Type.STRING); // Name
wrapper.read(Type.STRING); // Value
if (wrapper.read(Type.BOOLEAN)) {
wrapper.read(Type.STRING); // Signature
}
}
});
map(Type.OPTIONAL_COMPONENT); // Motd
map(Type.OPTIONAL_STRING); // Encoded icon
map(Type.BOOLEAN); // Previews chat
read(Type.BOOLEAN); // Enforces secure chat
}
});
@ -331,17 +260,57 @@ public final class Protocol1_18_2To1_19_1 extends BackwardsProtocol<ClientboundP
@Override
public void registerMap() {
map(Type.STRING); // Name
// Write empty profile key and uuid - requires the enforce-secure-profiles option to be disabled on the server
handler(wrapper -> {
final ProfileKey profileKey = wrapper.read(Type.OPTIONAL_PROFILE_KEY);
if (profileKey == null) {
wrapper.user().put(new NonceStorage(null));
}
});
// Write empty profile key and uuid (since keys are not compatible) - requires the enforce-secure-profiles option to be disabled on the server
create(Type.OPTIONAL_PROFILE_KEY, null);
create(Type.OPTIONAL_UUID, null);
}
});
registerClientbound(State.LOGIN, ClientboundLoginPackets.HELLO.getId(), ClientboundLoginPackets.HELLO.getId(), new PacketRemapper() {
@Override
public void registerMap() {
map(Type.STRING); // Server id
handler(wrapper -> {
if (wrapper.user().get(NonceStorage.class) != null) {
// Is already using the encrypted nonce
return;
}
final byte[] publicKey = wrapper.passthrough(Type.BYTE_ARRAY_PRIMITIVE);
final byte[] nonce = wrapper.passthrough(Type.BYTE_ARRAY_PRIMITIVE);
wrapper.user().put(new NonceStorage(CipherUtil.encryptNonce(publicKey, nonce)));
});
}
});
registerServerbound(State.LOGIN, ServerboundLoginPackets.ENCRYPTION_KEY.getId(), ServerboundLoginPackets.ENCRYPTION_KEY.getId(), new PacketRemapper() {
@Override
public void registerMap() {
map(Type.BYTE_ARRAY_PRIMITIVE); // Keys
create(Type.BOOLEAN, true); // Is nonce
map(Type.BYTE_ARRAY_PRIMITIVE); // Key
handler(wrapper -> {
final NonceStorage nonceStorage = wrapper.user().remove(NonceStorage.class);
final boolean isNonce = wrapper.read(Type.BOOLEAN);
wrapper.write(Type.BOOLEAN, true);
if (isNonce) {
// Nonce, just pass it through
wrapper.passthrough(Type.BYTE_ARRAY_PRIMITIVE);
return;
}
if (nonceStorage == null || nonceStorage.nonce() == null) {
throw new IllegalArgumentException("Server sent nonce is missing");
}
wrapper.read(Type.LONG); // Salt
wrapper.read(Type.BYTE_ARRAY_PRIMITIVE); // Signature
wrapper.write(Type.BYTE_ARRAY_PRIMITIVE, nonceStorage.nonce());
});
}
});
@ -351,7 +320,7 @@ public final class Protocol1_18_2To1_19_1 extends BackwardsProtocol<ClientboundP
map(Type.VAR_INT);
map(Type.STRING);
handler(wrapper -> {
String identifier = wrapper.get(Type.STRING, 0);
final String identifier = wrapper.get(Type.STRING, 0);
if (identifier.equals("velocity:player_info")) {
byte[] data = wrapper.passthrough(Type.REMAINING_BYTES);
// Velocity modern forwarding version above 1 includes the players public key.
@ -365,7 +334,7 @@ public final class Protocol1_18_2To1_19_1 extends BackwardsProtocol<ClientboundP
if (data.length == 1 && data[0] > 1) {
data[0] = 1;
} else if (data.length == 0) { // Or the version is omitted (default version would be used)
data = new byte[] { 1 };
data = new byte[]{1};
wrapper.set(Type.REMAINING_BYTES, 0, data);
} else {
ViaBackwards.getPlatform().getLogger().warning("Received unexpected data in velocity:player_info (length=" + data.length + ")");
@ -382,16 +351,11 @@ public final class Protocol1_18_2To1_19_1 extends BackwardsProtocol<ClientboundP
@Override
public void init(final UserConnection user) {
user.put(new DimensionRegistryStorage());
user.put(new ChatRegistryStorage());
user.put(new ReceivedMessagesStorage());
addEntityTracker(user, new EntityTrackerBase(user, Entity1_19Types.PLAYER, true));
}
@Override
public BackwardsMappings getMappingData() {
return MAPPINGS;
}
@Override
public TranslatableRewriter getTranslatableRewriter() {
return translatableRewriter;
@ -402,15 +366,8 @@ public final class Protocol1_18_2To1_19_1 extends BackwardsProtocol<ClientboundP
return entityRewriter;
}
@Override
public ItemRewriter getItemRewriter() {
return blockItemPackets;
}
private @Nullable JsonElement decorateChatMessage(final PacketWrapper wrapper, final int chatTypeId, final JsonElement senderName, @Nullable final JsonElement targetName, final JsonElement message) {
translatableRewriter.processText(message);
CompoundTag chatType = wrapper.user().get(DimensionRegistryStorage.class).chatType(chatTypeId);
CompoundTag chatType = wrapper.user().get(ChatRegistryStorage.class).chatType(chatTypeId);
if (chatType == null) {
ViaBackwards.getPlatform().getLogger().warning("Chat message has unknown chat type id " + chatTypeId + ". Message: " + message);
return null;

View File

@ -0,0 +1,51 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2022 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viabackwards.protocol.protocol1_19to1_19_1.packets;
import com.viaversion.viabackwards.api.rewriters.EntityRewriter;
import com.viaversion.viabackwards.protocol.protocol1_19to1_19_1.Protocol1_19To1_19_1;
import com.viaversion.viaversion.api.minecraft.entities.Entity1_19Types;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.type.types.version.Types1_19;
import com.viaversion.viaversion.protocols.protocol1_19_1to1_19.ClientboundPackets1_19_1;
public final class EntityPackets1_19_1 extends EntityRewriter<Protocol1_19To1_19_1> {
public EntityPackets1_19_1(final Protocol1_19To1_19_1 protocol) {
super(protocol);
}
@Override
protected void registerPackets() {
registerMetadataRewriter(ClientboundPackets1_19_1.ENTITY_METADATA, Types1_19.METADATA_LIST);
registerRemoveEntities(ClientboundPackets1_19_1.REMOVE_ENTITIES);
registerSpawnTracker(ClientboundPackets1_19_1.SPAWN_ENTITY);
}
@Override
public void registerRewrites() {
filter().type(Entity1_19Types.ALLAY).cancel(16); // Dancing
filter().type(Entity1_19Types.ALLAY).cancel(17); // Can duplicate
}
@Override
public EntityType typeFromId(final int typeId) {
return Entity1_19Types.getTypeFromId(typeId);
}
}

View File

@ -0,0 +1,47 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2022 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viabackwards.protocol.protocol1_19to1_19_1.storage;
import com.viaversion.viaversion.api.connection.StorableObject;
import com.viaversion.viaversion.libs.fastutil.ints.Int2ObjectMap;
import com.viaversion.viaversion.libs.fastutil.ints.Int2ObjectOpenHashMap;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag;
import com.viaversion.viaversion.protocols.protocol1_19to1_18_2.Protocol1_19To1_18_2;
import org.checkerframework.checker.nullness.qual.Nullable;
public final class ChatRegistryStorage implements StorableObject {
private final Int2ObjectMap<CompoundTag> chatTypes = new Int2ObjectOpenHashMap<>();
public @Nullable CompoundTag chatType(final int id) {
return chatTypes.isEmpty() ? Protocol1_19To1_18_2.MAPPINGS.chatType(id) : chatTypes.get(id);
}
public void addChatType(final int id, final CompoundTag chatType) {
chatTypes.put(id, chatType);
}
public void clear() {
chatTypes.clear();
}
@Override
public boolean clearOnServerSwitch() {
return false;
}
}

View File

@ -0,0 +1,34 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2022 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viabackwards.protocol.protocol1_19to1_19_1.storage;
import com.viaversion.viaversion.api.connection.StorableObject;
import org.checkerframework.checker.nullness.qual.Nullable;
public final class NonceStorage implements StorableObject {
private final byte[] nonce;
public NonceStorage(final byte @Nullable[] nonce) {
this.nonce = nonce;
}
public byte @Nullable [] nonce() {
return nonce;
}
}

View File

@ -15,7 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viabackwards.protocol.protocol1_18_2to1_19_1.storage;
package com.viaversion.viabackwards.protocol.protocol1_19to1_19_1.storage;
import com.viaversion.viaversion.api.connection.StorableObject;
import com.viaversion.viaversion.api.minecraft.PlayerMessageSignature;

View File

@ -3,8 +3,9 @@
"gui.acknowledge": "Acknowledge",
"gui.socialInteractions.report": "Report",
"gui.socialInteractions.tooltip.report": "Report player",
"gui.socialInteractions.tooltip.report.disabled": "Cannot create report: reporting service unavailable",
"gui.socialInteractions.tooltip.report.no_messages": "Cannot create report: no recent messages from player %s",
"gui.socialInteractions.tooltip.report.disabled": "The reporting service is unavailable",
"gui.socialInteractions.tooltip.report.no_messages": "No reportable messages from player %s",
"gui.socialInteractions.tooltip.report.not_reportable": "This player can't be reported, because their chat messages can't be verified on this server",
"gui.socialInteractions.narration.hide": "Hide messages from %s",
"gui.socialInteractions.narration.show": "Show messages from %s",
"gui.socialInteractions.narration.report": "Report player %s",
@ -75,6 +76,30 @@
"gui.banned.description.temporary": "%s Until then, you can<61>t play online or join Realms.",
"gui.banned.description.permanent": "Your account is permanently banned, which means you can<61>t play online or join Realms.",
"menu.playerReporting": "Player Reporting",
"multiplayer.disconnect.unsigned_chat": "Received chat packet with missing or invalid signature.",
"multiplayer.disconnect.too_many_pending_chats": "Too many unacknowledged chat messages",
"multiplayer.disconnect.chat_validation_failed": "Chat message validation failure",
"multiplayer.unsecureserver.toast.title": "Chat messages can't be verified",
"multiplayer.unsecureserver.toast": "Messages sent on this server may be modified and might not reflect the original message",
"chat.previewInput": "Press [%s] to preview",
"chat.tag.not_secure": "This message is not secure, which means that it might have been modified by the server",
"chat.tag.modified": "This message has been modified by the server.",
"chat.tag.modified.original": "Original text: %s",
"chat.tag.filtered": "This message has been filtered by the server.",
"chat.filtered_full": "The server has hidden your message for some players.",
"disconnect.loginFailedInfo.userBanned": "You are banned from playing online",
"options.chatPreview.live": "While Typing",
"options.chatPreview.confirm": "When Sending",
"options.chatPreview.tooltip.off": "Any modifications applied to your chat messages by a server will not be previewed and will be treated as insecure.",
"options.chatPreview.tooltip.live": "If a server uses Chat Previews: Any modifications applied to your chat messages by a server will be dynamically sent for previewing as the chat message is typed.",
"options.chatPreview.tooltip.confirm": "If a server uses Chat Previews: A chat preview is only generated when attempting to send a message that does not have a preview or is waiting for a preview.\nSending the message requires confirmation.",
"title.multiplayer.disabled.banned.temporary": "Your account is temporarily suspended from online play",
"title.multiplayer.disabled.banned.permanent": "Your account is permanently suspended from online play",
"gui.minutes": "%s minute(s)",
"gui.hours": "%s hour(s)",
"gui.days": "%s day(s)"
},
"1.19": {
"selectWorld.loading_list": "Loading world list",
"flat_world_preset.unknown": "???",
"flat_world_preset.minecraft.classic_flat": "Classic Flat",
@ -97,37 +122,22 @@
"multiplayer.disconnect.invalid_public_key_signature": "Invalid signature for profile public key.\nTry restarting your game.",
"multiplayer.disconnect.invalid_public_key": "Unable to parse profile public key.",
"multiplayer.disconnect.out_of_order_chat": "Out-of-order chat packet received. Did your system time change?",
"multiplayer.disconnect.unsigned_chat": "Received chat packet with missing or invalid signature.",
"multiplayer.disconnect.too_many_pending_chats": "Too many unacknowledged chat messages",
"multiplayer.disconnect.chat_validation_failed": "Chat message validation failure",
"multiplayer.unsecureserver.toast.title": "Chat messages can't be verified",
"multiplayer.unsecureserver.toast": "Messages sent on this server may be modified and might not reflect the original message",
"chatPreview.warning.title": "This server uses Chat Preview",
"chatPreview.warning.content": "Chat Preview allows the server to see your messages before they are sent to other players. This allows a server to send you a preview of your chat messages with custom modifications and styling applied.\n\nThe Chat Preview behavior can be changed in your Chat Settings. Current setting is: [%s]",
"chatPreview.warning.content": "Chat Preview allows the server to see your messages in real time as you type them, even before they<65>re sent. This is often used to preview your message with styling applied.\n\nChat Preview is on by default, but can be turned off in Chat Settings.",
"chatPreview.warning.check": "Do not notify again for this server",
"chatPreview.warning.toast.title": "Chat Preview is enabled",
"chatPreview.warning.toast": "This server uses Chat Preview and can see your messages as you type them, even before they're sent. You can turn this off in Chat Settings.",
"chat.disabled.profile.moreInfo": "Chat not allowed by account settings. Cannot send or view messages.",
"chat.previewInput": "Press [%s] to preview",
"chat.tag.not_secure": "This message is not secure, which means that it might have been modified by the server",
"chat.tag.modified": "This message has been modified by the server.",
"chat.tag.modified.original": "Original text: %s",
"disconnect.loginFailedInfo.userBanned": "You are banned from playing online",
"chat.preview": "Type to preview",
"options.darknessEffectScale": "Darkness Pulsing",
"options.darknessEffectScale.tooltip": "Controls how much the Darkness effect pulses when a Warden or Sculk Shrieker gives it to you.",
"options.chatPreview": "Chat Preview",
"options.chatPreview.live": "While Typing",
"options.chatPreview.confirm": "When Sending",
"options.chatPreview.tooltip.off": "Any modifications applied to your chat messages by a server will not be previewed and will be treated as insecure.",
"options.chatPreview.tooltip.live": "If a server uses Chat Previews: Any modifications applied to your chat messages by a server will be dynamically sent for previewing as the chat message is typed.",
"options.chatPreview.tooltip.confirm": "If a server uses Chat Previews: A chat preview is only generated when attempting to send a message that does not have a preview or is waiting for a preview.\nSending the message requires confirmation.",
"options.chatPreview.tooltip": "Chat Preview allows servers to see your messages as you type, which allows them to style your message. You can still chat if you turn this off.",
"options.onlyShowSecureChat": "Only Show Secure Chat",
"options.onlyShowSecureChat.tooltip": "Only display messages from other players that can be verified to have been sent by that player, and have not been modified.",
"options.directionalAudio": "Directional Audio",
"options.directionalAudio.on.tooltip": "Uses HRTF-based directional audio to improve the simulation of 3D sound. Requires HRTF compatible audio hardware, and is best experienced with headphones.",
"options.directionalAudio.off.tooltip": "Classic Stereo sound",
"title.multiplayer.disabled.banned.temporary": "Your account is temporarily suspended from online play",
"title.multiplayer.disabled.banned.permanent": "Your account is permanently suspended from online play",
"block.minecraft.mangrove_planks": "Mangrove Planks",
"block.minecraft.mangrove_propagule": "Mangrove Propagule",
"block.minecraft.mangrove_door": "Mangrove Door",
@ -174,7 +184,7 @@
"item.minecraft.mangrove_chest_boat": "Mangrove Boat with Chest",
"item.minecraft.recovery_compass": "Recovery Compass",
"item.minecraft.music_disc_5": "Music Disc",
"item.minecraft.music_disc_5.desc": "Samuel Åberg - 5",
"item.minecraft.music_disc_5.desc": "Samuel <EFBFBD>berg - 5",
"item.minecraft.disc_fragment_5": "Disc Fragment",
"item.minecraft.disc_fragment_5.desc": "Music Disc - 5",
"item.minecraft.allay_spawn_egg": "Allay Spawn Egg",
@ -204,9 +214,6 @@
"death.attack.sting.item": "%1$s was stung to death by %2$s using %3$s",
"effect.minecraft.darkness": "Darkness",
"enchantment.minecraft.swift_sneak": "Swift Sneak",
"gui.minutes": "%s minute(s)",
"gui.hours": "%s hour(s)",
"gui.days": "%s day(s)",
"subtitles.block.frogspawn.hatch": "Tadpole hatches",
"subtitles.block.sculk.charge": "Sculk bubbles",
"subtitles.block.sculk.spread": "Sculk spreads",